启动使用 UIScrollView 的 UIPageControl 的 App 时,如何将默认页面设置在右侧而不是左侧(反向)?

Posted

技术标签:

【中文标题】启动使用 UIScrollView 的 UIPageControl 的 App 时,如何将默认页面设置在右侧而不是左侧(反向)?【英文标题】:How to set the default page on the right side instead on the left (reverse) when launching App that used UIPageControl of UIScrollView? 【发布时间】:2009-08-19 17:10:08 【问题描述】:

我的案例:

我有来自 Apple 的原创 Page Control 应用程序。我想在 UIScrollView 底部的页面控件的右侧修改应用程序的启动? 默认情况下,启动时 - 它位于左侧的第一页上。例如,我有 7 页。所以,我希望第一页出现在第 7 页的最后一页和第 6 页的第二页,依此类推。简而言之,与默认相反。

我知道必须有一个代码可以做到这一点。我不确定它是什么。 请帮忙。谢谢!

以下是来自 Apple 的 Page Control 应用的说明:

页面控件

此应用程序演示了如何使用 UIScrollView 的分页功能来使用水平滚动作为在不同内容页面之间导航的机制。每个页面都由其自己的视图控制器管理,该控制器仅在需要时加载。 UIPageControl 显示在窗口底部,作为在页面之间移动的替代界面

AppDelegate.m 中的代码

#import "AppDelegate.h"
#import "MyViewController.h"

static NSUInteger kNumberOfPages = 7;

@interface AppDelegate (PrivateMethods)

- (void)loadScrollViewWithPage:(int)page;
- (void)scrollViewDidScroll:(UIScrollView *)sender;

@end

@implementation AppDelegate

@synthesize window, scrollView, pageControl, viewControllers;

- (void)dealloc 
    [viewControllers release];
    [scrollView release];
    [pageControl release];
    [window release];
    [super dealloc];


- (void)applicationDidFinishLaunching:(UIApplication *)application 
    // view controllers are created lazily
    // in the meantime, load the array with placeholders which will be replaced on demand
    NSMutableArray *controllers = [[NSMutableArray alloc] init];
    for (unsigned i = 0; i < kNumberOfPages; i++) 
        [controllers addObject:[NSNull null]];
    
    self.viewControllers = controllers;
    [controllers release];

    // a page is the width of the scroll view
    scrollView.pagingEnabled = YES;
    scrollView.contentSize = CGSizeMake(scrollView.frame.size.width * kNumberOfPages, scrollView.frame.size.height);
    scrollView.showsHorizontalScrollIndicator = NO;
    scrollView.showsVerticalScrollIndicator = NO;
    scrollView.scrollsToTop = NO;
    scrollView.delegate = self;

    pageControl.numberOfPages = kNumberOfPages;
    pageControl.currentPage = 0;

    // pages are created on demand
    // load the visible page
    // load the page on either side to avoid flashes when the user starts scrolling
    [self loadScrollViewWithPage:0];
    [self loadScrollViewWithPage:1];


- (void)loadScrollViewWithPage:(int)page 
    if (page < 0) return;
    if (page >= kNumberOfPages) return;

    // replace the placeholder if necessary
    MyViewController *controller = [viewControllers objectAtIndex:page];
    if ((NSNull *)controller == [NSNull null]) 
        controller = [[MyViewController alloc] initWithPageNumber:page];
        [viewControllers replaceObjectAtIndex:page withObject:controller];
        [controller release];
    

    // add the controller's view to the scroll view
    if (nil == controller.view.superview) 
        CGRect frame = scrollView.frame;
        frame.origin.x = frame.size.width * page;
        frame.origin.y = 0;
        controller.view.frame = frame;
        [scrollView addSubview:controller.view];
    


- (void)scrollViewDidScroll:(UIScrollView *)sender 
    // We don't want a "feedback loop" between the UIPageControl and the scroll delegate in
    // which a scroll event generated from the user hitting the page control triggers updates from
    // the delegate method. We use a boolean to disable the delegate logic when the page control is used.
    if (pageControlUsed) 
        // do nothing - the scroll was initiated from the page control, not the user dragging
        return;
    
    // Switch the indicator when more than 50% of the previous/next page is visible
    CGFloat pageWidth = scrollView.frame.size.width;
    int page = floor((scrollView.contentOffset.x - pageWidth / 2) / pageWidth) + 1;
    pageControl.currentPage = page;

    // load the visible page and the page on either side of it (to avoid flashes when the user starts scrolling)
    [self loadScrollViewWithPage:page - 1];
    [self loadScrollViewWithPage:page];
    [self loadScrollViewWithPage:page + 1];

    // A possible optimization would be to unload the views+controllers which are no longer visible


// At the end of scroll animation, reset the boolean used when scrolls originate from the UIPageControl
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView 
    pageControlUsed = NO;


- (IBAction)changePage:(id)sender 
    int page = pageControl.currentPage;
    // load the visible page and the page on either side of it (to avoid flashes when the user starts scrolling)
    [self loadScrollViewWithPage:page - 1];
    [self loadScrollViewWithPage:page];
    [self loadScrollViewWithPage:page + 1];
    // update the scroll view to the appropriate page
    CGRect frame = scrollView.frame;
    frame.origin.x = frame.size.width * page;
    frame.origin.y = 0;
    [scrollView scrollRectToVisible:frame animated:YES];
    // Set the boolean used when scrolls originate from the UIPageControl. See scrollViewDidScroll: above.
    pageControlUsed = YES;


@end

【问题讨论】:

【参考方案1】:

从 Apple 获取 PageControl 示例,下面是执行此操作的代码。我对其进行了测试,它工作正常,除了在您将应用程序从初始点启动到最后一个点时注意到页面控件的跳转,但我不知道如何解决这个问题。如果这对您不起作用,请告诉我。

- (void)applicationDidFinishLaunching:(UIApplication *)application 
    // view controllers are created lazily
    // in the meantime, load the array with placeholders which will be replaced on demand
    NSMutableArray *controllers = [[NSMutableArray alloc] init];
    for (unsigned i = 0; i < kNumberOfPages; i++) 
        [controllers addObject:[NSNull null]];
    
    self.viewControllers = controllers;
    [controllers release];

    // a page is the width of the scroll view
    scrollView.pagingEnabled = YES;
    scrollView.contentSize = CGSizeMake(scrollView.frame.size.width * kNumberOfPages, scrollView.frame.size.height);
    scrollView.showsHorizontalScrollIndicator = NO;
    scrollView.showsVerticalScrollIndicator = NO;
    scrollView.scrollsToTop = NO;
    scrollView.delegate = self;

    // First, set the number of pages
    pageControl.numberOfPages = kNumberOfPages;
    // Then, tell the page control that you're on the last page (numPages - 1, since we're 0-indexed)
    pageControl.currentPage = kNumberOfPages - 1;

    // Now, we have to tell the frame that we're at the end of the frame
    // So we set the content offset to be the last page
    scrollView.contentOffset = CGPointMake(scrollView.frame.size.width * (kNumberOfPages - 1), 0);

    // pages are created on demand
    // load the visible page
    // load the page on either side to avoid flashes when the user starts scrolling
    // [self loadScrollViewWithPage:0];
    // [self loadScrollViewWithPage:1];

    // Now, instead of loading the original page, we load the last two pages
    [self loadScrollViewWithPage:kNumberOfPages - 1];
    [self loadScrollViewWithPage:kNumberOfPages - 2];

【讨论】:

我想我试过了。那没有用。 numPages - 1 只会回到上一个之前的上一个。比如说,有 7 页。它将转到第 6 页。但是当向右或向左滚动时,它会变回原始页面 1,2,3 等。代码中必须有一些东西需要更改才能反转。 我必须实际尝试一下代码。我会在今天晚些时候尝试做,然后发回更完整的解决方案。 嘿 Itay,非常感谢!那太好了。欣赏它。 更新了经过测试且有效的解决方案。如果它不起作用,请告诉我。 嘿Itay!你真是个天才!它有效 - 跳转点可能与实例化时的页面控件有关。无论如何,非常感谢!【参考方案2】:

好吧,你可以将你的 scrollViews 偏移设置为最后一页,然后它将从最后一页开始,你必须向右滚动而不是向左滚动...使用 UIScrollViews - (void)setContentOffset: (CGPoint)contentOffset 动画:(BOOL)动画方法。

【讨论】:

对不起,我对这个东西有点新手。假设您必须放置 setContentOffset。你到底把它放在代码的什么地方? (我把代码供参考)另外,如果你要使用 setContentOffset - 它会影响 UIPageControl 吗? 也许在你实例化你的scrollView之后,对于pagesControl,你需要做的就是设置我认为的活动页面..

以上是关于启动使用 UIScrollView 的 UIPageControl 的 App 时,如何将默认页面设置在右侧而不是左侧(反向)?的主要内容,如果未能解决你的问题,请参考以下文章

UIScrollView 以启动为中心

如何在我的应用重新启动时动态恢复 UIScrollView 的缩放级别和位置?

iOS开发 首次启动显示用户引导,第二次启动直接进入App,UIScrollView,UIPageControl,NSUserDefaults

奇怪的滚动问题( UIScrollView )

UIScrollView 似乎在大 ContentSizes 上使用了大量内存

需求加载一个 UIScrollView