12

アプリケーションのスクロール部分にUIPageControlを使用することを検討してきましたが、それがどのように機能するのか疑問に思いました。ドキュメントには、ページの変更、ページ数の設定などの方法が示されていますが、ページコントロール自体には、どのような種類のスクロールビューも含まれていません。

UIPageControlクラスとUIScrollViewクラスは、ページインジケーターを表示する場合(アプリページを含むiPhoneのホーム画面など)に組み合わせて使用​​することになっていますか?

4

5 に答える 5

20

UITableView と同じように機能し、iPhone のホーム画面などで使用される方法で UIPageControl と UIScrollView の概念をマージするクラス (PagedView) を作成しました。

概念は基本的に次のとおりです。Pag​​edViewDelegate を実装して、PagedView の各ページのページ数とビューを返す必要があります。ビューの再利用は、UITableView と同じように機能します。インターフェイス ビルダーを使用して、scrollview アウトレットと pageControl アウトレットを接続します。

このクラスが有用であると思われる場合はお知らせください。

.h ファイル:

//
//  PagedView.h
//
//  Created by Werner Altewischer on 22/10/10.
//  Copyright 2010 werner-it.com. All rights reserved.
//

@protocol ReusableObject

- (NSString *)reuseIdentifier;
- (void)prepareForReuse;

@end

@class PagedView;

@protocol PagedViewDelegate

- (NSUInteger)numberOfPagesInPagedView:(PagedView *)view;
- (UIView *)pagedView:(PagedView *)view viewForPageAtIndex:(NSUInteger)page;

@end

@interface PagedView : UIView<UIScrollViewDelegate> {
    IBOutlet UIScrollView *scrollView;
    IBOutlet UIPageControl *pageControl;
    NSMutableDictionary *pageViewDictionary;
    NSMutableDictionary *reuseViewDictionary;

    IBOutlet id <PagedViewDelegate> delegate;
}

@property (nonatomic, assign) IBOutlet id <PagedViewDelegate> delegate;

- (UIView<ReusableObject> *)dequeueReusableViewWithIdentifier:(NSString *)identifier;

- (void)scrollToPageAtIndex:(NSUInteger)pageIndex animated:(BOOL)animated;
- (NSInteger)indexForSelectedPage;

- (CGSize)pageSize;
- (void)reloadData;

@end

.m ファイル:

//
//  PagedView.m
//
//  Created by Werner Altewischer on 22/10/10.
//  Copyright 2010 werner-it.com. All rights reserved.
//



#define TT_RELEASE_SAFELY(__POINTER) { [__POINTER release]; __POINTER = nil; }

    @interface PagedView (Private)

    - (NSUInteger)pageCount;

    - (UIView *)loadViewForIndex:(NSUInteger)pageIndex;
    - (void)unloadViewForIndex:(NSUInteger)pageIndex;
    - (void)loadViewsForVisiblePages:(BOOL)reloadData;  
    - (UIView *)viewForIndex:(NSUInteger)pageIndex;

    @end

    @implementation PagedView

    @synthesize delegate;

    - (void)dealloc {
        TT_RELEASE_SAFELY(pageViewDictionary);
        TT_RELEASE_SAFELY(reuseViewDictionary);
        TT_RELEASE_SAFELY(scrollView);
        TT_RELEASE_SAFELY(pageControl);
        [super dealloc];
    }

    - (CGSize)pageSize {
        return scrollView.frame.size;
    }

    - (void)reloadData {
        if (!pageViewDictionary) {
            //First time initialization 
            pageViewDictionary = [NSMutableDictionary new];
            reuseViewDictionary = [NSMutableDictionary new];
            [pageControl addTarget:self action:@selector(pageChanged:) forControlEvents:UIControlEventValueChanged];
            scrollView.delegate = self;
            scrollView.pagingEnabled = YES;
        }

        CGSize size = self.pageSize;

        NSUInteger numberOfPages = self.pageCount;  
        pageControl.numberOfPages = MAX(1, numberOfPages);
        [scrollView setContentSize:CGSizeMake(size.width * numberOfPages, size.height)];
        pageControl.currentPage = self.indexForSelectedPage;

        pageControl.hidden = (numberOfPages == 0);

        [self loadViewsForVisiblePages:YES];
    }

    - (void)layoutSubviews {
        if (!pageViewDictionary) {
            [self reloadData];
        }
    }

    - (void)scrollToPageAtIndex:(NSUInteger)pageIndex animated:(BOOL)animated {
        if (pageIndex < self.pageCount) {
            CGSize size = scrollView.frame.size;
            CGRect rect = CGRectMake(size.width * pageIndex, 0, size.width, size.height);
            [scrollView scrollRectToVisible:rect animated:animated];
        }
    }

    - (NSInteger)indexForSelectedPage {
        CGFloat cx = scrollView.contentOffset.x;
        NSUInteger index = (NSUInteger)(cx / scrollView.frame.size.width);
        if (index >= self.pageCount) {
            index = NSNotFound;
        }
        return index;
    }

    #pragma mark -
    #pragma mark UIScrollViewDelegate implementation

    - (void)scrollViewWillBeginDragging:(UIScrollView *)theScrollView {
        theScrollView.userInteractionEnabled = NO; 
    }

    - (void)scrollViewDidEndDecelerating:(UIScrollView *)theScrollView {
        if (theScrollView == scrollView) {
            pageControl.currentPage = self.indexForSelectedPage;
            [self loadViewsForVisiblePages:NO];
            theScrollView.userInteractionEnabled = YES; 
        }
    }

    - (void)pageChanged:(UIPageControl *)thePageControl {
        if (pageControl == thePageControl) {
            [self scrollToPageAtIndex:pageControl.currentPage animated:YES];
            [self loadViewsForVisiblePages:NO];
        }
    }

    - (UIView<ReusableObject> *)dequeueReusableViewWithIdentifier:(NSString *)identifier {
        UIView<ReusableObject> *v = [[[reuseViewDictionary objectForKey:identifier] retain] autorelease];
        if (v) {
            [v prepareForReuse];
            [reuseViewDictionary removeObjectForKey:identifier];
        }
        return v;
    }

    @end


    @implementation PagedView (Private)

    - (NSUInteger)pageCount {
        return [self.delegate numberOfPagesInPagedView:self];
    }

    - (UIView *)viewForIndex:(NSUInteger)pageIndex {
        id key = [NSNumber numberWithUnsignedInteger:pageIndex];
        return [pageViewDictionary objectForKey:key];
    }

    - (UIView *)loadViewForIndex:(NSUInteger)pageIndex {
        id key = [NSNumber numberWithUnsignedInteger:pageIndex];
        UIView *v = [pageViewDictionary objectForKey:key];
        if (!v) {
            CGSize size = self.pageSize;
            UIView *v = [self.delegate pagedView:self viewForPageAtIndex:pageIndex];
            if (v) {
                v.frame = CGRectMake(pageIndex * size.width, 0, size.width, size.height);
                [scrollView addSubview:v];      
                [pageViewDictionary setObject:v forKey:key];
            }
        } 
        return v;
    }

    - (void)unloadViewForIndex:(NSUInteger)pageIndex {
        id key = [NSNumber numberWithUnsignedInteger:pageIndex];
        UIView *v = [pageViewDictionary objectForKey:key];
        if (v) {
            if ([v conformsToProtocol:@protocol(ReusableObject)]) {
                NSString *reuseIdentifier = [(id <ReusableObject>)v reuseIdentifier];
                [reuseViewDictionary setObject:v forKey:reuseIdentifier];
            }
            [v removeFromSuperview];
            [pageViewDictionary removeObjectForKey:key];
        }

    }

    - (void)loadViewsForVisiblePages:(BOOL)reloadData {

        //load the selected view and the one in front and behind

        NSUInteger selectedPage = self.indexForSelectedPage;
        NSUInteger numberOfPages = self.pageCount;

        int intSelectedPage = (selectedPage == NSNotFound) ? -2 : (int)selectedPage;

        //Find the max number present in the pageViewDictionary
        NSUInteger existingPageCount = 0;
        for (NSNumber *key in pageViewDictionary) {
            if ([key unsignedIntegerValue] >= existingPageCount) {
                existingPageCount = [key unsignedIntegerValue] + 1;
            }
        }

        for (int i = 0; i < MAX(numberOfPages, existingPageCount); ++i) {
            if (i >= numberOfPages || 
                i < (intSelectedPage - 1) ||
                i > (intSelectedPage + 1)) {
                [self unloadViewForIndex:i];
            } else {
                if (reloadData) {
                    //Unload the view if we're reloading all the data
                    [self unloadViewForIndex:i];
                }
                [self loadViewForIndex:i];
            }
        }

        [reuseViewDictionary removeAllObjects];
    }

    @end
于 2010-10-25T11:49:25.967 に答える
10

ページング ビットは、UIScrollView でページング プロパティを設定することによって実際に行われます。ページ コントロールは単なる便利な UI 構造ですが、実際にはページング自体とは何の関係もありません。

于 2009-07-09T14:26:16.073 に答える
7

UIPageControl does two things: (1) it displays dots, including a highlighted dot for the currently selected page, and (2) it generates a UIControlEventValueChanged event when the user taps on it. Tap on the right side of the control to page to the right; tap on the left side to page to the left. You should implement this behavior to be consistent with the HIG!

To trap the event, add:

[myUiPageControl addTarget:self action:@selector(pageChanged:) forControlEvents:UIControlEventValueChanged];

and that delegate function as well:

-(void)pageChanged:(UIPageControl*)thePageControl;

The name can be whatever you want; I used "pageChanged" for example. The callback signature can be pageChanged, pageChanged:, or pageChanged:forEvent:. This callback function should cause your scrollview (or what have you) to update.

Paging, itself, is usually done by using a UIScrollView with paging enabled and scrollbars hidden. Tell the scrollview to use paging and flicks magically move page by page; make sure you trap that change to update the currentPage property of the UIPageControl.

于 2011-06-07T22:18:54.350 に答える
2

正解です。UIPageControlは、ページの下部にあるドット以外は何も描画しません。そのためには別のビューが必要です。

于 2009-07-09T13:36:50.447 に答える
1

Werner Altewischer クラスを使用するには、PagedViewDelegate をインターフェイスに追加し、以下に示すようにクラスを完成させます。

@interface ViewController (){
    //header view
    UIPageControl* headPageControl;
    UIScrollView* headScrollView;
    PagedView* headerView;
    NSMutableArray* headerViews;
}
//header view
-(void)initHeader;
-(void)setHeaderViews:(NSMutableArray*)views;
-(void)addHeaderView:(UIView*)view;
-(void)popHeader;

@end

@implementation ViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
    [self initHeader];
    [self popHeader];  
}

-(void)initHeader
{
    float frameWidth = self.view.frame.size.width;

    headPageControl = [[UIPageControl alloc]initWithFrame:CGRectMake(0, HEADER_HEIGHT-PAGE_CONTROL_HEIGHT, frameWidth, PAGE_CONTROL_HEIGHT)];
    [headPageControl setBackgroundColor:[UIColor colorWithWhite:0.0 alpha:0.5]];

    headerViews = [NSMutableArray array];

    headScrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, frameWidth, HEADER_HEIGHT)];
    headScrollView.showsHorizontalScrollIndicator = NO;

    headerView = [[PagedView alloc] initWithFrame:CGRectMake(0, 0, frameWidth, HEADER_HEIGHT)];
    headerView.delegate = self;
    headerView.pageControl = headPageControl;
    headerView.scrollView = headScrollView;

    [headerView addSubview:headScrollView];
    [headerView addSubview:headPageControl];

    [headerView setBackgroundColor:[UIColor darkGrayColor]];
    [self.view addSubview:headerView];
}

-(NSUInteger)numberOfPagesInPagedView:(PagedView *)view
{
    //NSLog(@"number of pages %i", headPageControl.numberOfPages);
    return headPageControl.numberOfPages;
}

-(UIView*)pagedView:(PagedView *)view viewForPageAtIndex:(NSUInteger)page
{
    //NSLog(@"open page %i", page);
    return [headerViews objectAtIndex:page];
}

-(void)setHeaderViews:(NSMutableArray*)views
{
    headerViews = views;
    headPageControl.numberOfPages = headerViews.count;
}

-(void)addHeaderView:(UIView*)view
{
    [headerViews addObject:view];
    headPageControl.numberOfPages = headerViews.count;
}

-(void)popHeader
{
    float frameWidth = self.view.frame.size.width;
    CGRect _frame = CGRectMake(0, 0, frameWidth, HEADER_HEIGHT);
    UIView* v = [[UIView alloc] initWithFrame:_frame];
    [v setBackgroundColor:[UIColor greenColor]];
    [self addHeaderView:v];

    UIView* v0 = [[UIView alloc] initWithFrame:_frame];
    [v0 setBackgroundColor:[UIColor purpleColor]];
    [self addHeaderView:v0];

    UIView* v1 = [[UIView alloc] initWithFrame:_frame];
    [v1 setBackgroundColor:[UIColor yellowColor]];
    [self addHeaderView:v1];
}
于 2012-10-18T12:39:19.963 に答える