Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/100.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios UIScrollView-何时设置contentSize_Ios_Uiviewcontroller_Uiscrollview_Uiimageview_Uiscrollviewdelegate - Fatal编程技术网

Ios UIScrollView-何时设置contentSize

Ios UIScrollView-何时设置contentSize,ios,uiviewcontroller,uiscrollview,uiimageview,uiscrollviewdelegate,Ios,Uiviewcontroller,Uiscrollview,Uiimageview,Uiscrollviewdelegate,我有一个UIViewController,它的视图层次结构如下所示: ui视图 UIScrollView UIImageView < >我有代码将图像视图放在滚动视图的框架中间,像这样: - (void)scrollViewDidZoom:(UIScrollView *)scrollView { [self recenterContent:scrollView]; } - (void)recenterContent:(UIScrollView *)scrollView

我有一个UIViewController,它的视图层次结构如下所示:

  • ui视图
    • UIScrollView
      • UIImageView
< >我有代码将图像视图放在滚动视图的框架中间,像这样:

- (void)scrollViewDidZoom:(UIScrollView *)scrollView {
    [self recenterContent:scrollView];
}

- (void)recenterContent:(UIScrollView *)scrollView {
    //this centers the content when it is smaller than the scrollView's bounds
    CGFloat offsetX = MAX((scrollView.bounds.size.width - scrollView.contentSize.width) * 0.5, 0.0);
    CGFloat offsetY = MAX((scrollView.bounds.size.height - scrollView.contentSize.height) * 0.5, 0.0);
    
    self.scrollView.contentInset = UIEdgeInsetsMake(offsetY, offsetX, 0.f, 0.f);
}
这在缩放内容时可以正常工作,但在视图控制器首次加载时,它不会居中。这是因为
scrollView.contentSize
总是
0
。所以我的问题是-设置scrollView.contentSize之后,我应该在什么时候调用这个方法?什么时候开始

我在
viewdilayoutsubviews
中进行了尝试,然后设置了滚动视图的边界,但没有设置内容大小。有什么方法可以保证滚动视图的内容大小设置

或者,当图像小于滚动视图时,是否有更好的方法保持图像居中?我试图实现的是使图像视图不在滚动视图的顶部,并且我使用的工作正常,除非滚动视图的内容大小未设置。但是,如果有更好的方法可以做到这一点,而不必调整
contentInset
,我也会同意的


更新 这是我目前拥有的

它几乎可以工作,但无论我尝试什么,我都无法在加载视图时使其看起来正确。它现在的工作方式是它从中心开始,因为当它调用
recenterContent
方法时,在显示视图之前,滚动视图的内容大小是CGSizeZero,因此计算是错误的。但是如果我在视图显示后尝试重新居中显示内容,那么在它居中之前会有一个明显的延迟

如果我使用AutoLayout约束来指定大小,我只是对何时设置滚动视图的contentSize感到困惑

这是我的密码。有人看到它有什么毛病吗

@interface MyImageViewController ()

@property (strong, nonatomic) UIScrollView *scrollView;
@property (strong, nonatomic) UIImageView *imageView;
@property (assign, nonatomic) BOOL needsZoomScale;

@end

@implementation MyImageViewController

- (void)loadView {
    self.view = [[UIView alloc] init];
    [self.view addSubview:self.scrollView];
    [self.scrollView addSubview:self.imageView];
    
    self.needsZoomScale = YES;
    
    [NSLayoutConstraint activateConstraints:@[
        [self.scrollView.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor],
        [self.scrollView.topAnchor constraintEqualToAnchor:self.view.topAnchor],
        [self.scrollView.trailingAnchor constraintEqualToAnchor:self.view.trailingAnchor],
        [self.scrollView.bottomAnchor constraintEqualToAnchor:self.view.bottomAnchor],
        
        [self.imageView.leadingAnchor constraintEqualToAnchor:self.scrollView.contentLayoutGuide.leadingAnchor],
        [self.imageView.topAnchor constraintEqualToAnchor:self.scrollView.contentLayoutGuide.topAnchor],
        [self.imageView.trailingAnchor constraintEqualToAnchor:self.scrollView.contentLayoutGuide.trailingAnchor],
        [self.imageView.bottomAnchor constraintEqualToAnchor:self.scrollView.contentLayoutGuide.bottomAnchor]
    ]];
}

- (void)viewDidLoad {
    [super viewDidLoad];
    
    UITapGestureRecognizer *doubleTapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(doubleTapZoom:)];
    doubleTapGesture.numberOfTapsRequired = 2;
    [self.imageView addGestureRecognizer:doubleTapGesture];
}

- (CGRect)zoomRectForScrollView:(UIScrollView *)scrollView withScale:(CGFloat)scale withCenter:(CGPoint)center {
    CGRect zoomRect;
    
    //the zoom rect is in the content view's coordinates. At a zoom scale of 1.0, the zoom rect would be the size
    //of the scroll view's bounds. As the zoom scale decreases, so more content is visible, the size of the rect
    //grows.
    zoomRect.size.width = scrollView.frame.size.width / scale;
    zoomRect.size.height = scrollView.frame.size.height / scale;
    
    //choose an origin so as to get the right center
    zoomRect.origin.x = center.x - (zoomRect.size.width / 2.0);
    zoomRect.origin.y = center.y - (zoomRect.size.height / 2.0);
    
    return zoomRect;
}

- (void)doubleTapZoom:(UITapGestureRecognizer *)sender {
    UIView *tappedView = sender.view;
    CGPoint tappedPoint = [sender locationInView:tappedView];
    
    if (tappedPoint.x <= 0) {
        tappedPoint.x = 1;
    }
    
    if (tappedPoint.y <= 0) {
        tappedPoint.y = 1;
    }
    
    if (tappedPoint.x >= tappedView.bounds.size.width) {
        tappedPoint.x = tappedView.bounds.size.width - 1;
    }
    
    if (tappedPoint.y >= tappedView.bounds.size.height) {
        tappedPoint.y = tappedView.bounds.size.height - 1;
    }

    CGFloat zoomScale;
    if (self.scrollView.zoomScale < 1) {
        zoomScale = 1;
    } else if (self.scrollView.zoomScale < self.scrollView.maximumZoomScale) {
        zoomScale = self.scrollView.maximumZoomScale;
    } else {
        zoomScale = self.scrollView.minimumZoomScale;
    }
    
    CGRect zoomRect = [self zoomRectForScrollView:self.scrollView withScale:zoomScale withCenter:tappedPoint];
    
    [self.scrollView zoomToRect:zoomRect animated:YES];
}

- (UIScrollView *)scrollView {
    if (!self->_scrollView) {
        self->_scrollView = [[UIScrollView alloc] init];
        self->_scrollView.translatesAutoresizingMaskIntoConstraints = NO;
        self->_scrollView.minimumZoomScale = 0.1f;
        self->_scrollView.maximumZoomScale = 4.0f;
        self->_scrollView.bounces = YES;
        self->_scrollView.bouncesZoom = YES;
        self->_scrollView.delegate = self;
        self->_scrollView.backgroundColor = [UIColor blackColor];
    }
    return self->_scrollView;
}

- (UIImageView *)imageView {
    if (!self->_imageView) {
        self->_imageView = [[UIImageView alloc] init];
        self->_imageView.translatesAutoresizingMaskIntoConstraints = NO;
        self->_imageView.userInteractionEnabled = YES;
    }
    return self->_imageView;
}

- (UIImage *)image {
    return self.imageView.image;
}

- (void)setImage:(UIImage *)image {
    self.imageView.image = image;
    self.needsZoomScale = YES;
    [self updateZoomScale];
}

- (void)updateZoomScale {
    if (self.needsZoomScale && self.image) {
        CGSize size = self.view.bounds.size;
        
        if (size.width == 0.0f || size.height == 0.0f) {
            return;
        }
            
        UIImage *image = self.image;
        CGSize imageSize = CGSizeMake(image.size.width * image.scale, image.size.height * image.scale);
        if (imageSize.width > 0 && imageSize.height > 0) {
            CGFloat widthScale = size.width / imageSize.width;
            CGFloat heightScale = size.height / imageSize.height;
            CGFloat minScale = MIN(widthScale, heightScale);
                
            self.scrollView.minimumZoomScale = minScale;
            self.scrollView.zoomScale = minScale;
            self.needsZoomScale = NO;
        }
    }
}

- (void)viewWillLayoutSubviews {
    [super viewWillLayoutSubviews];
    [self updateZoomScale];
}

- (void)viewDidLayoutSubviews {
    [super viewDidLayoutSubviews];
    [self recenterContent:self.scrollView];
}

- (void)viewDidAppear:(BOOL)animated {
    [super viewDidAppear:animated];
    [self recenterContent:self.scrollView];
}

#pragma mark - UIScrollViewDelegate

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

- (void)scrollViewDidZoom:(UIScrollView *)scrollView {
    [self recenterContent:scrollView];
}

- (void)recenterContent:(UIScrollView *)scrollView {
    //this centers the content when it is smaller than the scrollView's bounds
    CGFloat offsetX = MAX((scrollView.bounds.size.width - scrollView.contentSize.width) * 0.5, 0.0);
    CGFloat offsetY = MAX((scrollView.bounds.size.height - scrollView.contentSize.height) * 0.5, 0.0);
    
    self.scrollView.contentInset = UIEdgeInsetsMake(offsetY, offsetX, 0.f, 0.f);
}

@end
@接口MyImageViewController()
@属性(强,非原子)UIScrollView*scrollView;
@属性(强,非原子)UIImageView*imageView;
@属性(赋值,非原子)BOOL needsZoomScale;
@结束
@MyImageViewController的实现
-(void)负荷视图{
self.view=[[UIView alloc]init];
[self.view addSubview:self.scrollView];
[self.scrollView addSubview:self.imageView];
self.needszoomsale=是;
[NSLayoutConstraint activateConstraints:@[
[self.scrollView.leadingAnchor约束QualtAnchor:self.view.leadingAnchor],
[self.scrollView.topAnchor约束QualToAnchor:self.view.topAnchor],
[self.scrollView.trailingAnchor约束QualToAnchor:self.view.trailingAnchor],
[self.scrollView.bottomAnchor约束QualtAnchor:self.view.bottomAnchor],
[self.imageView.leadingAnchor约束Qualtoancher:self.scrollView.contentLayoutGuide.leadingAnchor],
[self.imageView.topAnchor约束QualtAnchor:self.scrollView.contentLayoutGuide.topAnchor],
[self.imageView.trailingAnchor约束Qualtoanch:self.scrollView.contentLayoutGuide.trailingAnchor],
[self.imageView.bottomAnchor约束Qualtoanch:self.scrollView.contentLayoutGuide.bottomAnchor]
]];
}
-(无效)viewDidLoad{
[超级视图下载];
UITapGestureRecognizer*DoubleTap手势=[[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(doubleTapZoom:)];
DoubleTapstore.numberOfTapsRequired=2;
[self.imageView添加手势识别器:双击手势];
}
-(CGRect)缩放透视图:(UIScrollView*)带刻度的滚动视图:(CGFloat)带中心的刻度:(CGPoint)中心{
CGRect-zoomRect;
//缩放矩形位于内容视图的坐标中。当缩放比例为1.0时,缩放矩形将为大小
//随着缩放比例的减小,更多的内容可见,矩形的大小
//成长。
zoomRect.size.width=scrollView.frame.size.width/比例;
zoomRect.size.height=滚动视图.frame.size.height/比例;
//选择一个原点以获得正确的中心
zoomRect.origin.x=center.x-(zoomRect.size.width/2.0);
zoomRect.origin.y=center.y-(zoomRect.size.height/2.0);
返回zoomRect;
}
-(无效)doubleTapZoom:(UITapgestureRecognitor*)发送方{
UIView*tappedView=sender.view;
CGPoint tappedPoint=[发送方位置查看:tappedView];
if(tappedPoint.x=tappedView.bounds.size.height){
tappedPoint.y=tappedView.bounds.size.height-1;
}
动物鳞片;
如果(self.scrollView.zoomScale<1){
zoomScale=1;
}else if(self.scrollView.zoomScale_scrollView){
self->_scrollView=[[UIScrollView alloc]init];
self->\u scrollView.translatesAutoResizengMaskintoConstraints=否;
self->_scrollView.minimumZoomScale=0.1f;
self->_scrollView.maximumZoomScale=4.0f;
self->\u scrollView.bounces=是;
self->\u scrollView.bouncesZoom=YES;
self->\u scrollView.delegate=self;
self->_scrollView.backgroundColor=[UIColor blackColor];
}
返回self->\u滚动视图;
}
-(UIImageView*)图像视图{
如果(!self->\u imageView){
self->_imageView=[[UIImageView alloc]init];
self->\u imageView.translatesAutoResizengmaskintoConstraints=否;
self->_imageView.userInteractionEnabled=YES;
}
返回self->\u imageView;
}
-(UIImage*)图像{
返回self.imageView.image;
}
-(void)setImage:(UIImage*)图像{
选择
// ---------------------------------
@interface MyImageViewController : UIViewController <UIScrollViewDelegate>
@end

@interface MyImageViewController ()

@property (strong, nonatomic) UIScrollView *scrollView;
@property (strong, nonatomic) UIImageView *imageView;
@property (assign, nonatomic) BOOL needsZoomScale;

@end

@implementation MyImageViewController

- (void)loadView {
    self.view = [[UIView alloc] init];
    [self.view addSubview:self.scrollView];
    [self.scrollView addSubview:self.imageView];

    self.needsZoomScale = YES;
    
    // ---------------------------------
    //  respect safe area
    UILayoutGuide *g = [self.view safeAreaLayoutGuide];
    //  saves on a little typing
    UILayoutGuide *sg = [self.scrollView contentLayoutGuide];
    // ---------------------------------

    [NSLayoutConstraint activateConstraints:@[
        [self.scrollView.leadingAnchor constraintEqualToAnchor:g.leadingAnchor],
        [self.scrollView.topAnchor constraintEqualToAnchor:g.topAnchor],
        [self.scrollView.trailingAnchor constraintEqualToAnchor:g.trailingAnchor],
        [self.scrollView.bottomAnchor constraintEqualToAnchor:g.bottomAnchor],
        
        [self.imageView.leadingAnchor constraintEqualToAnchor:sg.leadingAnchor],
        [self.imageView.topAnchor constraintEqualToAnchor:sg.topAnchor],
        [self.imageView.trailingAnchor constraintEqualToAnchor:sg.trailingAnchor],
        [self.imageView.bottomAnchor constraintEqualToAnchor:sg.bottomAnchor]
    ]];
}

- (void)viewDidLoad {
    [super viewDidLoad];
    
    UITapGestureRecognizer *doubleTapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(doubleTapZoom:)];
    doubleTapGesture.numberOfTapsRequired = 2;
    [self.imageView addGestureRecognizer:doubleTapGesture];
}

- (CGRect)zoomRectForScrollView:(UIScrollView *)scrollView withScale:(CGFloat)scale withCenter:(CGPoint)center {
    CGRect zoomRect;
    
    //the zoom rect is in the content view's coordinates. At a zoom scale of 1.0, the zoom rect would be the size
    //of the scroll view's bounds. As the zoom scale decreases, so more content is visible, the size of the rect
    //grows.
    zoomRect.size.width = scrollView.frame.size.width / scale;
    zoomRect.size.height = scrollView.frame.size.height / scale;
    
    //choose an origin so as to get the right center
    zoomRect.origin.x = center.x - (zoomRect.size.width / 2.0);
    zoomRect.origin.y = center.y - (zoomRect.size.height / 2.0);
    
    return zoomRect;
}

- (void)doubleTapZoom:(UITapGestureRecognizer *)sender {
    UIView *tappedView = sender.view;
    CGPoint tappedPoint = [sender locationInView:tappedView];
    
    if (tappedPoint.x <= 0) {
        tappedPoint.x = 1;
    }
    
    if (tappedPoint.y <= 0) {
        tappedPoint.y = 1;
    }
    
    if (tappedPoint.x >= tappedView.bounds.size.width) {
        tappedPoint.x = tappedView.bounds.size.width - 1;
    }
    
    if (tappedPoint.y >= tappedView.bounds.size.height) {
        tappedPoint.y = tappedView.bounds.size.height - 1;
    }
    
    CGFloat zoomScale;
    if (self.scrollView.zoomScale < 1) {
        zoomScale = 1;
    } else if (self.scrollView.zoomScale < self.scrollView.maximumZoomScale) {
        zoomScale = self.scrollView.maximumZoomScale;
    } else {
        zoomScale = self.scrollView.minimumZoomScale;
    }
    
    CGRect zoomRect = [self zoomRectForScrollView:self.scrollView withScale:zoomScale withCenter:tappedPoint];
    
    [self.scrollView zoomToRect:zoomRect animated:YES];
}

- (UIScrollView *)scrollView {
    if (!self->_scrollView) {
        self->_scrollView = [[UIScrollView alloc] init];
        self->_scrollView.translatesAutoresizingMaskIntoConstraints = NO;
        self->_scrollView.minimumZoomScale = 0.1f;
        self->_scrollView.maximumZoomScale = 4.0f;
        self->_scrollView.bounces = YES;
        self->_scrollView.bouncesZoom = YES;
        self->_scrollView.delegate = self;
        self->_scrollView.backgroundColor = [UIColor blackColor];
    }
    return self->_scrollView;
}

- (UIImageView *)imageView {
    if (!self->_imageView) {
        self->_imageView = [[UIImageView alloc] init];
        self->_imageView.translatesAutoresizingMaskIntoConstraints = NO;
        self->_imageView.userInteractionEnabled = YES;
    }
    return self->_imageView;
}

- (UIImage *)image {
    return self.imageView.image;
}

- (void)setImage:(UIImage *)image {
    self.imageView.image = image;
    
    // ---------------------------------
    //  set the frame here
    self.imageView.frame = CGRectMake(0.0, 0.0, image.size.width, image.size.height);
    
    // ---------------------------------
    //  not needed ... unless maybe changing the image while view is showing?
    //self.needsZoomScale = YES;
    //[self updateZoomScale];
}

- (void)updateZoomScale {
    if (self.needsZoomScale && self.image) {
        CGSize size = self.view.bounds.size;
        
        if (size.width == 0.0f || size.height == 0.0f) {
            return;
        }
        
        UIImage *image = self.image;
        CGSize imageSize = CGSizeMake(image.size.width * image.scale, image.size.height * image.scale);
        if (imageSize.width > 0 && imageSize.height > 0) {
            CGFloat widthScale = size.width / imageSize.width;
            CGFloat heightScale = size.height / imageSize.height;
            CGFloat minScale = MIN(widthScale, heightScale);
            
            self.scrollView.minimumZoomScale = minScale;
            self.scrollView.zoomScale = minScale;
            self.needsZoomScale = NO;
        }
    }
}

// ---------------------------------
//  Don't need this
//- (void)viewWillLayoutSubviews {
//  [super viewWillLayoutSubviews];
//  [self updateZoomScale];
//}
// ---------------------------------

- (void)viewDidLayoutSubviews {
    [super viewDidLayoutSubviews];

    // ---------------------------------
    //  update zoom scale here
    [self updateZoomScale];
    // ---------------------------------
    
    [self recenterContent:self.scrollView];
}

// ---------------------------------
//  Don't need this
//- (void)viewDidAppear:(BOOL)animated {
//  [super viewDidAppear:animated];
//  [self recenterContent:self.scrollView];
//}
// ---------------------------------

#pragma mark - UIScrollViewDelegate

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

- (void)scrollViewDidZoom:(UIScrollView *)scrollView {
    [self recenterContent:scrollView];
}

- (void)recenterContent:(UIScrollView *)scrollView {
    //this centers the content when it is smaller than the scrollView's bounds
    CGFloat offsetX = MAX((scrollView.bounds.size.width - scrollView.contentSize.width) * 0.5, 0.0);
    CGFloat offsetY = MAX((scrollView.bounds.size.height - scrollView.contentSize.height) * 0.5, 0.0);
    
    self.scrollView.contentInset = UIEdgeInsetsMake(offsetY, offsetX, 0.f, 0.f);
}

@end
MyImageViewController *vc = [MyImageViewController new];

UIImage *img = [UIImage imageNamed:@"bkg"];
if (nil == img) {
    NSLog(@"Could not load image!!!!");
    return;
}
[vc setImage:img];

[self.navigationController pushViewController:vc animated:YES];