Ios UIScrollView-何时设置contentSize
我有一个UIViewController,它的视图层次结构如下所示: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
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];