如何缩放 UIScrollView 中锚点位于中心的视图?

问题描述 投票:0回答:2

我在 UIScrollView 中有一个视图,用户可以在其中放大。

视图与 UIScrollView 框架具有相同的大小。但是,该视图的子视图更大且居中。它是一个与 UIScrollView 大小相同且内容居中的容器。

缩小时,UIScrollView 会更改内容的比例,并在左上角使用一个尴尬的锚点,而不是居中的锚点。

有没有办法改变这种行为,以便在放大或缩小时缩放相对于中心而不是左上角发生?

iphone objective-c ios uiscrollview
2个回答
18
投票

行为可以更改为围绕中心缩放,但技术很棘手。

假设您有一个大小为 (300,300) 的滚动视图,其中有一个可缩放子视图

self.imageView
,最初位于 (0,0,300,300)。现在你想缩小。发生的情况是,当您缩小时,
contentOffset
始终保持 (0,0)。这会导致您使用左上角的锚点进行缩放的外观。

但是,更改任何视图上的锚点在这里都没有帮助;这是因为滚动视图的缩放行为不仅仅是应用于某些子视图的缩放转换。滚动视图中内容的外观由

contentInset
contentOffset
控制,它们是滚动视图维护的单独变量。您需要修改缩放期间内容偏移和内容插入的行为。

一种解决方案是随着滚动视图的滚动动态调整

contentInset
。目的是保持图像始终位于滚动视图可见区域的中心。

初始化滚动视图时,像这样准备它的框架:

 - (void) viewDidLoad {
      //// .......
      self.scrollView.zoomScale = 1;
      self.scrollView.minimumZoomScale = fminf(1, fminf(self.scrollView.frame.size.width/(self.imageView.image.size.width+1), self.scrollView.frame.size.height/(self.imageView.image.size.height+1)));
      CGFloat leftMargin = (self.scrollView.frame.size.width - self.imageView.image.size.width)*0.5;
      CGFloat topMargin = (self.scrollView.frame.size.height - self.imageView.image.size.height)*0.5;
      self.imageView.frame = CGRectMake(0, 0, self.imageView.image.size.width, self.imageView.image.size.height);
      [self assignInsetsOnScroller]; // this has to be done before settings contentOffset!
      self.scrollView.contentOffset = CGPointMake(fmaxf(0,-leftMargin), fmaxf(0,-topMargin));
      self.scrollView.contentSize = CGSizeMake(fmaxf(self.imageView.image.size.width, self.scrollView.frame.size.width+1), fmaxf(self.imageView.image.size.height, self.scrollView.frame.size.height+1));
   }

为滚动视图设置委托,覆盖

scrollViewDidScroll:
,然后执行如下操作:

 - (void)scrollViewDidScroll:(UIScrollView *)scrollView {
    [self assignInsetsOnScroller];
 }
 - (void) assignInsetsOnScroller {
    CGFloat leftMargin = (scrollView.frame.size.width - self.imageView.frame.size.width)*0.5;
    CGFloat topMargin = (scrollView.frame.size.height - self.imageView.frame.size.height)*0.5;
    scrollView.contentInset = UIEdgeInsetsMake(fmaxf(0, topMargin), fmaxf(0, leftMargin), 0, 0);
 }

每个捏合手势都会产生滚动动作。结果是动态调整插图,使

imageView
始终显示在滚动视图的中心。


Swift 5: 简单多了。无需进行任何设置 - 只需将

contentOffset
设置在
scrollViewDidScroll
内即可。

func scrollViewDidScroll(_ scrollView: UIScrollView) {
    let leftMargin = (scrollView.bounds.width - scrollView.contentSize.width) * 0.5
    let topMargin = (scrollView.bounds.height - scrollView.contentSize.height) * 0.5
    scrollView.contentInset = UIEdgeInsets(top: topMargin, left: leftMargin, bottom: 0, right: 0)
}

0
投票

是的,我相信您可以更改视图图层的

anchorPoint
。就像这样 -

[self.yourView.layer setAnchorPoint:CGPointMake(0.5, 0)];

该图中恰当地定义了锚点的坐标 -

enter image description here

如果您希望动画从左中心锚定,请将锚点设置为

(0.0, 0.5)
,即图中的 B 点。

© www.soinside.com 2019 - 2024. All rights reserved.