横向方向期间的UIPageControl和UIScrollView

时间:2013-03-03 16:52:42

标签: ios uiview uiscrollview screen-orientation uipagecontrol

我遇到UIPageControl和UIScrollView问题。

- (void)viewDidLoad
{
    [super viewDidLoad];

    imageArray = [[NSArray alloc] initWithObjects:@"image1.jpg", @"image2.jpg", @"image3.jpg", nil];

    for (int i = 0; i < [imageArray count]; i++) {
        CGRect frame;
        frame.origin.x = self.scrollView.frame.size.width * i;
        frame.origin.y = 0;
        frame.size = self.scrollView.frame.size;

        UIImageView *imageView = [[UIImageView alloc] initWithFrame:frame];
        imageView.image = [UIImage imageNamed:[imageArray objectAtIndex:i]];
        [self.scrollView addSubview:imageView];
    }
    scrollView.contentSize = CGSizeMake(scrollView.frame.size.width * [imageArray count], scrollView.frame.size.height);

    scrollView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin;
    pageControl.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleTopMargin;
}

#pragma mark - UIScrollView Delegate

- (void)scrollViewDidScroll:(UIScrollView *)sender
{
    CGFloat pageWidth = self.scrollView.frame.size.width;
    int page = floor((self.scrollView.contentOffset.x - pageWidth / 2) / pageWidth) + 1;
    self.pageControl.currentPage = page;
}

将方向更改为横向时会出现问题。 image1.jpg与image2.jpg共享视图,这不是我想要的。

但如果我将方向改回肖像,视图就会很好。

1 个答案:

答案 0 :(得分:3)

问题是页面大小已经改变(即滚动视图的宽度),但图像的宽度没有改变。

一种解决方案是,当您旋转时,重新执行调整UIImageViews大小的计算并计算scrollview的contentSize。也就是说,将for循环和赋值转移到 viewDidLoad 中的scrollView.contentSize并转换为私有方法,比如sizeImagesAndSetContentSize。从 willAnimateRotationToInterfaceOrientation:duration 调用: 如下所示:

- (void)viewDidLoad
{
    [super viewDidLoad];

    imageArray = [[NSArray alloc] initWithObjects:@"image1.jpg", @"image2.jpg", @"image3.jpg", nil];

    [self sizeImagesAndSetContentSize];

    scrollView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin;
    pageControl.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleTopMargin;
}


- (void) sizeImagesAndSetContentSize {
       for (int i = 0; i < [imageArray count]; i++) {
            CGRect frame;
            frame.origin.x = self.scrollView.frame.size.width * i;
            frame.origin.y = 0;
            frame.size = self.scrollView.frame.size;

            UIImageView *imageView = [[UIImageView alloc] initWithFrame:frame];
            imageView.image = [UIImage imageNamed:[imageArray objectAtIndex:i]];
            [self.scrollView addSubview:imageView];
        }
        scrollView.contentSize = CGSizeMake(scrollView.frame.size.width * [imageArray count], scrollView.frame.size.height);
}
- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation duration:(NSTimeInterval)duration {
    [self sizeImagesAndSetContentSize];

}

顺便说一下, viewDidLoad 不是进行几何计算的地方 - 就像涉及scrollView框架的东西一样,因为几何体没有设置。在 viewDidLoad 中,事物的大小是它们在故事板(或笔尖)中的大小,并且尚未根据实际设备和实际方向进行调整。如果它到目前为止适用于您,那是因为您从故事板布局的方向开始。可能是最好的地方,因此调用 sizeImagesAndSetContentSize 的方法是 viewDidLayoutSubviews 。实际上,如果你在那里移动调用,则不需要在旋转时显式调用它,因为当旋转发生时,视图会显示子视图,并且将自动调用 viewDidLayoutSubviews 。所以我建议:

- (void)viewDidLoad
{
    [super viewDidLoad];

    imageArray = [[NSArray alloc] initWithObjects:@"image1.jpg", @"image2.jpg", @"image3.jpg", nil];

    scrollView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin;
    pageControl.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleTopMargin;
}

- (void) sizeImagesAndSetContentSize {
       for (int i = 0; i < [imageArray count]; i++) {
            CGRect frame;
            frame.origin.x = self.scrollView.frame.size.width * i;
            frame.origin.y = 0;
            frame.size = self.scrollView.frame.size;

            UIImageView *imageView = [[UIImageView alloc] initWithFrame:frame];
            imageView.image = [UIImage imageNamed:[imageArray objectAtIndex:i]];
            [self.scrollView addSubview:imageView];
        }
        scrollView.contentSize = CGSizeMake(scrollView.frame.size.width * [imageArray count], scrollView.frame.size.height);
}

- (void)viewDidLayoutSubviews {
    [self sizeImagesAndSetContentSize];
}

附录:
添加文字到图片:

要在图像顶部添加文本,您可以在滚动视图的“顶部”添加文本元素,如标签。考虑下面的应用程序的屏幕截图。在顶级云幻灯片放映视图中,有一个全景的滚动视图,并且在相同的层次结构级别,但在子视图列表的下方(因此在滚动视图的“顶部”)是描述的标签,3个按钮和一个UIPageControl。标签设置为通过支柱和弹簧在旋转时调整大小(这在iOS 5上运行),因此您不必弄乱它。

Storyboard structure for text overlay

此应用程序更改描述标签以匹配当前在滚动视图页面中显示的图像 - 因此它必须检测页面更改。此应用程序在滚动视图委托协议方法 scrollViewDidEndDecelerating:中执行此操作,其中当滚动停止并填写正确的描述时,它决定屏幕上的哪个图像。

另一种方法是在每个UIImage上放置一个标签,但这很麻烦,这就是我的应用程序不这样做的原因。您可能希望视图包含UIImage和标签,以便重新定位标签是有意义的。可能在代码中创建它...对我来说,太麻烦了。

顺便说一句,我应该说在滚动视图中使用页面模式可能不再是执行此操作的“最佳实践”方式。我正在将我的应用程序转换为使用UIPageViewController,这应该简化应用程序。例如,您不必执行resize-on-rotate操作,因为UIPageViewControl的各个子VC可以自动调整大小。