的UIScrollView变焦不工作,自动布局(UIScrollView Zoom Does Not

2019-07-18 11:33发布

用严格的自动布局环境的UIScrollView缩放似乎并没有工作。

这是特别令人沮丧,因为iOS 6的发布说明肯定使我相信它应该在写“纯粹的自动布局方法”在这里http://developer.apple.com/library/ios/#releasenotes/General/RN- iOSSDK-6_0 / _index.html

我看了看在WWDC 2012张幻灯片会话202,228和232并没有看到这个答案。

我已经看到了在互联网上专门针对这一问题,唯一的问题是UIScrollView的与自动布局放大 ,但它并没有提供该问题的代码并没有回答。

此用户https://stackoverflow.com/users/341994/matt已经给UIScrollView的自动布局问题,许多伟大的回应,甚至链接到git的枢纽代码,但我一直没能找到任何有回答了这个问题。

我试图煮沸这个问题降低到绝对最低,使其清楚。

我创建了一个故事板新的单一视图的应用,并取得了在界面生成器没有变化。

我添加了一个大的图片文件到项目“pic.jpg”。

SVFViewController.h

#import <UIKit/UIKit.h> 
@interface SVFViewController : UIViewController <UIScrollViewDelegate>
@property (nonatomic) UIImageView *imageViewPointer;
@end

SVFViewController.m

#import "SVFViewController.h"

@interface SVFViewController ()

@end

@implementation SVFViewController


- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.

    UIScrollView *scrollView = [[UIScrollView alloc] init];
    UIImageView *imageView = [[UIImageView alloc] init];
    [imageView setImage:[UIImage imageNamed:@"pic.jpg"]];
    [self.view addSubview:scrollView];
    [scrollView addSubview:imageView];

    scrollView.translatesAutoresizingMaskIntoConstraints = NO;
    imageView.translatesAutoresizingMaskIntoConstraints = NO;
    self.imageViewPointer = imageView;
    scrollView.maximumZoomScale = 2;
    scrollView.minimumZoomScale = .5;
    scrollView.delegate = self;

    NSDictionary *viewsDictionary = NSDictionaryOfVariableBindings(scrollView,imageView);
    NSLog(@"Current views dictionary: %@", viewsDictionary);
    [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[scrollView]|" options:0 metrics: 0 views:viewsDictionary]];
    [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[scrollView]|" options:0 metrics: 0 views:viewsDictionary]];
    [scrollView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[imageView]|" options:0 metrics: 0 views:viewsDictionary]];
    [scrollView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[imageView]|" options:0 metrics: 0 views:viewsDictionary]];
}

-(UIView*)viewForZoomingInScrollView:(UIScrollView *)scrollView{
    return self.imageViewPointer;
}

@end

请注意,我做了一个特别的努力,使这是很像在iOS 6的发布说明提供的示例代码,只是做了最低限度,以实现变焦。

所以,这个问题?

当你运行该应用程序,并在滚动视图平移,一切都很好。 但是,当你放大的问题是显而易见的,图像闪烁来回,以及图像的滚动视图中的位置变得更加不妥每变焦。

它看起来像有战斗持续了内容的ImageView的偏移量,现在看来,这被设置为不同的值由两个不同的东西与每一个“放大”。 (所述的ImageView的内容污损性的NSLog的出现,以确认这一点)。

我在做什么错在这里? 有谁知道如何实现财产在纯粹的自动版式环境一个UIScrollView内变焦。 有没有这种随时随地在那里的一个例子吗?

请帮忙。

Answer 1:

再次,重新阅读的iOS SDK 6.0版本说明我发现:

请注意,您可以滚动视图的子视图出现通过创建视图和滚动视图的子树,外视图之间的约束,如滚动视图的上海华浮动(不滚动)比其他滚动内容。

你的子视图连接到外视图。 换句话说,向图,其中滚动视图嵌入。

并应用约束以下方式我有它的工作:

[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[scrollView]|" options:0 metrics: 0 views:viewsDictionary]];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[scrollView]|" options:0 metrics: 0 views:viewsDictionary]];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[imageView(width)]" options:0 metrics:@{@"width":@(self.imageViewPointer.image.size.width)} views:viewsDictionary]];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[imageView(height)]" options:0 metrics:@{@"height":@(self.imageViewPointer.image.size.height)} views:viewsDictionary]];


Answer 2:

出现的问题是ImageView的位置时变焦过程中的变化。 该ImageView的的原点位置将改变成为变焦时为负值。 我相信这就是为什么干运动发生。 同时,缩放完成后的ImageView的仍然是在错误的位置,这意味着滚动会出现偏移。

如果您实现-(void) scrollViewDidZoom:(UIScrollView *)scrollView ,在此期间日志的UIImageView的框架,你可以看到它的原点改变。

我最终使事情通过实施类似的战略制定出此

而且除了改变内容查看的框架,而放大

-(void) scrollViewDidZoom:(UIScrollView *)scrollView {
    CGRect cFrame = self.contentView.frame;
    cFrame.origin = CGPointZero;
    self.contentView.frame = cFrame;
}


Answer 3:

这些解决方案都还挺工作。 下面是我做的,没有任何黑客或子类要求,在此设置:

[view]
  [scrollView]
    [container]
      [imageView]
      [imageView2]
  1. 在图1B中,挂钩顶部,导致,底部和尾随scrollViewview
  2. 钩往上顶,领导,底部和尾部containerscrollView
  3. 挂钩中心-x和的中心-Y container到中心-x和的中心-Y scrollView 并将其标记为在编译时间除去 。 这是只需要沉默IB的警告。
  4. 实施viewForZoomingInScrollView:在视图控制器,它应该是滚动视图的委托,并从该方法返回container
  5. 当设置imageView形象,确定最低变焦倍数(如现在将在本机尺寸显示),把它:

     CGSize mySize = self.view.bounds.size; CGSize imgSize = _imageView.image.size; CGFloat scale = fminf(mySize.width / imgSize.width, mySize.height / imgSize.height); _scrollView.minimumZoomScale = scale; _scrollView.zoomScale = scale; _scrollView.maximumZoomScale = 4 * scale; 

这个工作对我来说,在设定图像缩放滚动视图来显示整个图像,并允许放大4倍的初始大小。



Answer 4:

让我们假设你在故事板有“ UIImageView ”内部“ UIScrollView ”内部“ UIView ”。

链接“的所有约束UIScrollView ”与视图控制器+在UIView的两个约束( Horizontal Space - Scroll View - View Horizontal Space - Scroll View - View

设置AS代表视图控制器用于“ UIScrollView ”。

然后执行以下代码:

@interface VC () <UIScrollViewDelegate>
@property (weak, nonatomic) IBOutlet UIScrollView *scrollView;
@property (weak, nonatomic) IBOutlet UIImageView *imageView;
@property (strong, nonatomic) IBOutletCollection(NSLayoutConstraint) NSArray* constraints;
@end

@implementation FamilyTreeImageVC

- (void)viewDidLoad {
    [super viewDidLoad];
    [self.scrollView removeConstraints:self.constraints];
}


- (UIView*)viewForZoomingInScrollView:(UIScrollView *)scrollView {
    return self.imageView;
}

-(void) scrollViewDidZoom:(UIScrollView *)scrollView {
    CGRect cFrame = self.imageView.frame;
    cFrame.origin = CGPointZero;
    self.imageView.frame = cFrame;
}


Answer 5:

试图实现从只使用滚动型故事板制作的项目变焦时我有同样的问题。

我通过添加单独的捏手势识别器固定它。 我刚刚从工具箱中拖动它到我的场景。 然后我把它连接到一个动作我所谓的“doPinch”实现变焦。 我把它连接到插座我所谓的“pinchRecognizer”这样我就可以访问它的规模属性。 这似乎覆盖内置的滚动型变焦和跳动消失。 也许它不会与更优雅是个起点,或是手柄同样的错误。 这是在IB布局的顶部很少的工作。

只要你介绍缩放手势识别器到现场你既需要行动和viewForZoomingInScrollView方法。 错过要么和变焦停止工作。

在我的视图控制器的代码是这样的:

- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView
{
return self.zoomableImage;
}

- (IBAction)doPinch:(id)sender

{
NSLog(@"In the pinch action now with scale: %f", self.pinchRecognizer.scale);
[scrollView setZoomScale:self.pinchRecognizer.scale animated:NO];
}

这个非常基本的实现确实有一个副作用:当你回过头来缩放图像和缩放比例更多一些值1.0F所以跳回到原来的规模。

您可以通过引入财产“currentScale”跟踪规模,并设置缩放手势识别器的规模,当你再次开始缩小排序了这一点。 您需要使用手势识别器的状态属性:

- (IBAction)doPinch:(id)sender
{
NSLog(@"In the pinch action now with scale: %f", self.pinchRecognizer.scale);
NSLog(@"Gesture recognizer state is: %d", self.pinchRecognizer.state);

switch (self.pinchRecognizer.state)
{
    case 1:
        NSLog(@"Zoom begins, with current scale set to: %f", self.currentScale);
        [self.pinchRecognizer setScale:self.currentScale];
        break;
    case 3:
        NSLog(@"Zoom ends, with pinch recognizer scale set to: %f", self.pinchRecognizer.scale);
        self.currentScale = self.pinchRecognizer.scale;
    default:
        break;
}

[scrollView setZoomScale:self.pinchRecognizer.scale animated:NO];
}


Answer 6:

所以,这就是我成功地工作了。

下面是我的变化原文:

@interface ScrollViewZoomTestViewController () <UIScrollViewDelegate>

@property (nonatomic, strong) UIImageView* imageViewPointer;

// These properties are new
@property (nonatomic, strong) NSMutableArray* imageViewConstraints;
@property (nonatomic) BOOL imageViewConstraintsNeedUpdating;
@property (nonatomic, strong) UIScrollView* scrollViewPointer;

@end

@implementation ScrollViewZoomTestViewController

- (void)viewDidLoad
{
    [super viewDidLoad];

    UIScrollView *scrollView = [[UIScrollView alloc] init];
    UIImageView *imageView = [[UIImageView alloc] init];
    [imageView setImage:[UIImage imageNamed:@"pic.jpg"]];
    [self.view addSubview:scrollView];
    [scrollView addSubview:imageView];

    scrollView.translatesAutoresizingMaskIntoConstraints = NO;
    imageView.translatesAutoresizingMaskIntoConstraints = NO;
    self.imageViewPointer = imageView;
    // New
    self.scrollViewPointer = scrollView;
    scrollView.maximumZoomScale = 2;
    scrollView.minimumZoomScale = .5;
    scrollView.delegate = self;

    NSDictionary *viewsDictionary = NSDictionaryOfVariableBindings(scrollView, imageView);
    NSLog(@"Current views dictionary: %@", viewsDictionary);
    [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[scrollView]|" options:0 metrics: 0 views:viewsDictionary]];
    [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[scrollView]|" options:0 metrics: 0 views:viewsDictionary]];

    // Saving the image view width & height constraints
    self.imageViewConstraints = [[NSMutableArray alloc] init];
    // Constrain the image view to be the same width & height of the scroll view
    [_imageViewConstraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[imageView(scrollView)]|" options:0 metrics: 0 views:viewsDictionary]];
    [_imageViewConstraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[imageView(scrollView)]|" options:0 metrics: 0 views:viewsDictionary]];

    // Add the image view constraints to the VIEW, not the scroll view
    [self.view addConstraints:_imageViewConstraints];

    // Flag
    self.imageViewConstraintsNeedUpdating = YES;
}

所以,在这里回顾一下,我将所有的约束self.view的,节省了设置的约束UIImageViewNSMutableArray属性,设置该标志UIImageView约束需要更新。

在这些初始约束UIImageView工作,将其设置为开始。 这将是相同的宽度和高度作为UIScrollView 。 然而,这不会让我们放大图像视图。 这将保持相同的width / height作为滚动视图。 不是我们想要的。 这就是为什么我节省了限制和设置标志。 我们会照顾的,在一分钟。

现在,设置缩放视图:

- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView
{
    return self.imageViewPointer;
}

好了,现在我们需要真正让我们放大。 我去除初始UIImageView约束和加入一些新的,这个时间约束到UIScrollViewcontentSize widthheight

- (void)scrollViewWillBeginZooming:(UIScrollView *)scrollView withView:(UIView *)view
{
    if(_imageViewConstraintsNeedUpdating)
    {
        // Remove the previous image view constraints
        [self.view removeConstraints:_imageViewConstraints];

        // Replace them with new ones, this time constraining against the `width` & `height` of the scroll view's content, not the scroll view itself
        NSDictionary *viewsDictionary = NSDictionaryOfVariableBindings(_scrollViewPointer, _imageViewPointer);
        [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[_imageViewPointer(width)]|" options:0 metrics:@{@"width" : @(_scrollViewPointer.contentSize.width)} views:viewsDictionary]];
        [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[_imageViewPointer(height)]|" options:0 metrics:@{@"height" : @(_scrollViewPointer.contentSize.height)} views:viewsDictionary]];

        self.imageViewConstraintsNeedUpdating = NO;
    }
}

@end

我们不能设置限制了这样的-viewDidLoad因为图像没有被渲染到UIImageView然而,这样UIScrollViewcontentSize将是{0,0}

这似乎很哈克给我,但它的工作,但它确实使用纯自动布局,我找不到更好的方式来做到这一点。 在我看来,像苹果需要提供一个更好的方式来放大内容UIScrollView ,并使用自动布局的限制。



文章来源: UIScrollView Zoom Does Not Work With Autolayout