转改:UIPageControl
大家都见过iPhone上的那几个小点点了。那就是iPhone用来控制翻页的UIPageControl控件,但是许多人不会用UIPageControl,又不愿意去看Apple的文档和例子。所以首先我们来讲讲这个控件的使用。
1、新建项目UsingPageControl。删除MainWindow.xib文件。 在Resources组中添加几张图片,在这里我随便找了几张动物的图片,你也可以另外找几张。
2、编辑delegate类代码,#import "UsingPageControlViewController.h",在application:didFinishLaunchingWithOptions:方法中加入以下代码:
UIViewController *vc=[[UsingPageControlViewController alloc]init];
[window addSubview:vc.view];
3、加入框架QuartzCore.framework。然后新建类UsingPageControlViewController,继承UIViewController。在interface中声明必要变量:
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#import <QuartzCore/QuartzCore.h>
@interfaceUsingPageControlViewController : UIViewController {
UIPageControl* pageCtr;
NSMutableArray* pages;
UIView *pageView;
int previousPage;
}
-(void)transitionPage:(int)from toPage:(int)to;
-(CATransition *) getAnimation:(NSString *) direction;
@end
4、在implementation中,编辑init方法,把我们要用到的3个图片文件名放入到pages数组:
-(id)init{
if (self = [super init]) {
pages=[[NSMutableArray alloc]initWithObjects:@"Dolphin.png",
@"Butterfly.png",
@"Hippopotamus.png",
nil];
}
return self;
}
5、编辑loadView方法,在上方放入一个UIPageControl用于翻页,在下方放入一个UIView用于显示图片,注意上下分开,不要重叠,避免UIPageControl被遮挡住:
-(void)loadView{
[super loadView];
CGRect viewBounds = self.view.frame;
viewBounds.origin.y = 0.0;
viewBounds.size.height = 460.0;
//控件区域
pageCtr=[[UIPageControl alloc]initWithFrame:CGRectMake(viewBounds.origin.x,
viewBounds.origin.y,
viewBounds.size.width,
60)];
pageCtr.backgroundColor=[UIColor blackColor];
pageCtr.numberOfPages = 3;
pageCtr.currentPage = 0;
// 设定翻页事件的处理方法
[pageCtr addTarget:self action:@selector(pageTurn:)
forControlEvents:UIControlEventValueChanged];
[self.view addSubview:pageCtr];
// 页面区域
CGRect contentFrame=CGRectMake(viewBounds.origin.x,
viewBounds.origin.y+60,
viewBounds.size.width,
viewBounds.size.height-60);
pageView=[[UIView alloc]initWithFrame:contentFrame];
[pageView setBackgroundColor:[UIColor brownColor]];
// 添加两个imageview,动画切换时用
for (int i=0; i<2; i++) {
[pageView addSubview:[[UIImageView alloc] initWithFrame:CGRectMake(0,
0,
contentFrame.size.width,
contentFrame.size.height)]];
}
// 设置最上面的subview(显示的图片)
[[[pageView subviews] lastObject] setImage:[UIImage imageNamed:
[pages objectAtIndex:0]]];
[self.view addSubview:pageView];
}
6、翻页控件在感知到翻页动作时,会调用pageTurning方法:
-(void)pageTurn:(UIPageControl*)pageControl{
[self transitionPage:previousPage toPage:pageControl.currentPage];
previousPage=pageControl.currentPage;
}
7、transitionPage方法是这样定义的:
-(void)transitionPage:(int)from toPage:(int)to{
NSLog(@"previouspage:%d",from);
NSLog(@"currentpage:%d",to);
CATransition *transition;
if (from!=to) {
if(from<to){
transition=[self getAnimation:kCATransitionFromLeft];
}else{
transition=[self getAnimation:kCATransitionFromRight];
}
// 取出pageView的下面的图片作为准备显示的图片
UIImageView *newImage=(UIImageView *)[[pageView subviews] objectAtIndex:0];
// 将视图修改为要显示的图片
[newImagesetImage:[UIImage imageNamed:[pages objectAtIndex:to]]];
// 将pageView的上下图片交换
[pageView exchangeSubviewAtIndex:0 withSubviewAtIndex:1];
// 显示上面的图片,隐藏下面的图片
[[pageView.subviews objectAtIndex:0] setHidden:YES];
[[pageView.subviews objectAtIndex:1] setHidden:NO];
// 设置转换动画
[[pageView layer] addAnimation:transition forKey:@"pageTurnAnimation"];
}
}
8、其中getAnimation方法根据用户手指滑动的方向返回CATransition转换动画:
// 返回一个转换动画
-(CATransition *) getAnimation:(NSString *) direction
{
CATransition *animation = [CATransition animation];
[animation setDelegate:self];
[animation setType:kCATransitionPush];
[animation setSubtype:direction];
[animation setDuration:1.0f];
[animation setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]];
return animation;
}
这是一个翻页动画,通过其subtype属性设定翻页从哪边开始:上、下、左、右4个方向。duration属性是动画转换的时间;timingFunction属性指定转换过程中要使用的特效,使用常量字符串指定5种不同的效果(但不知什么原因,在这里不管设成什么值,都只有一种效果:淡入淡出)。
程序最终效果如下:
http://img.ph.126.net/OOXkrJ0gGIDLFYbTK-216g==/1347139238554061973.png
使用UIPageControl的例子如前面所示。但光以控件形式使用 UIPageControl还是不好用,因为虽然用户能通过手指扫动UIPageControl控件进行翻页,但UIPageControl控件在屏幕上所占的区域还是太小了,如果用户在整个屏幕都能通过扫动来进行翻页就更好了,这无疑大大增强的用户的体验。
这需要我们增加一个UIView控件,让它占据屏幕的整个区域。让UIView能识别用户手指扫动的手势,即几个touchesXXX方法。这样用户在屏幕上滑动手指时,实际上会被UIView捕捉为扫动手势。
首先,我们来实现这个UIView。新建类 SwipeView。SwipeView借鉴了《iPhone开发秘籍》中 Henry Yu 的实现,甚至我们都不需要做多少改变。
#import <UIKit/UIKit.h>
#import <QuartzCore/QuartzCore.h>
@interface SwipeView : UIView {
CGPoint startTouchPosition;
NSString *direction;
UIViewController *host;
}
- (void) setHost: (UIViewController *) aHost;
@end
#import "SwipeView.h"
@implementation SwipeView
- (id)initWithFrame:(CGRect)frame {
if ((self = [super initWithFrame:frame])) {
// Initializationcode
}
return self;
}
- (void) setHost: (UIViewController *) aHost
{
host = aHost;
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];
startTouchPosition = [touch locationInView:self];
direction = NULL;
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch =touches.anyObject;
CGPoint currentTouchPosition =[touch locationInView:self];
#defineHORIZ_SWIPE_DRAG_MIN 12
#defineVERT_SWIPE_DRAG_MAX 4
if (fabsf(startTouchPosition.x -currentTouchPosition.x) >=
HORIZ_SWIPE_DRAG_MIN &&
fabsf(startTouchPosition.y - currentTouchPosition.y) <=
VERT_SWIPE_DRAG_MAX)
{
// Horizontal Swipe
if (startTouchPosition.x <currentTouchPosition.x) {
direction = kCATransitionFromLeft;
}
else
direction = kCATransitionFromRight;
}
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
if (host!=nil && direction) {
SEL sel=NSSelectorFromString(@"swipeTo:");
if([host respondsToSelector:sel]) {
[host performSelector:sel withObject:direction];
}
}
}
@end
首先,打开我们前面所做的工程UsingPageControl。
在UsingPageControlVeiwController中导入头文件SwipeView.h。将UsingPageControlViewController中的pageView修改为SwipeView类型。
同时在pageView的初始化时使用SwipeView的initWithFrame方法,并调用setHost:方法:
pageView=[[SwipeView alloc]initWithFrame:contentFrame];
[pageView setHost:self];
接下来,我们需要在SwipeView的Host类UsingPageControlVeiwController实现指定的swipeTo:方法:
// SwipeView 的协议(委托)方法
- (void) swipeTo: (NSString *) aDirection
{
NSLog(@"swipe to");
int to=previousPage;
if ([aDirection isEqualToString:kCATransitionFromRight])
{
to++;
}else {
to--;
}
if (to>=0 && to<=2) {
// pageCtrl的值改变并调用pageTuren方法
[self transitionPage:previousPage toPage:to];
previousPage=pageCtr.currentPage=to;
}
}
自定义UIPageControl(可改变点颜色)
1.继承自UIPageControl ,2.并准备两张图片 一个用于高亮显示 一个用于普通显示
关键代码如下
- (void) setImagePageStateNormal:(UIImage *)image
{
[imagePageStateNormal release];
imagePageStateNormal = [image retain];
[self updateDots];
}
- (void) setImagePageStateHightlighted:(UIImage *)image
{
[imagePageStateHightlighted release];
imagePageStateHightlighted = [image retain];
[self updateDots];
}
- (void) endTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event
{
[super endTrackingWithTouch:touch withEvent:event];
[self updateDots];
}
- (void) updateDots
{
if (imagePageStateNormal || imagePageStateHightlighted) {
NSArray *subView = self.subviews;
for (int i = 0; i < [subView count]; i++) {
UIImageView *dot = [subView objectAtIndex:i];
dot.image = (self.currentPage == i ? imagePageStateHightlighted : imagePageStateNormal);
}
}
}
UI控件篇——UIPageControl及其自定义
UIPageControl类提供一行点来指示当前显示的是多页面视图的哪一页。当然,由于UIPageControl类可视样式的点击不太好操作,所以最好是确保再添加了可选择的导航选项,以便让页面控件看起来更像一个指示器,而不是一个控件。当用户界面需要按页面进行显示时,使用UIPageControl控件将要显示的用户界面内容分页进行显示会使编程工作变得快捷。
用户点击页面控件,会触发UIControlEventValueChanged事件,并启动设置为控件动作的任何方法。可以通过调用currentPage查询控件的新值,并通过调整numberOfPages属性设置可用的页面数。
// 初始化页面控件
pageControl.numberOfPages = 9;
pageControl.currentPage = 0;
[pageControl addTarget:self action:@selector(pageTurn) forControlEvents:UIControlEventValueChanged];
- (void)pageTurn:(UIPageControl *)pageControl
{
CATransition *transition;
int secondPage = [pageControl currentPage];
if((secondPage - currentPage)>0)
transition = [self getAnimation:@"fromRight"];
else
transition = [self getAnimation:@"fromLeft"];
UIImageView *newView = (UIImageView *)[[contentView subviews] objectAtIndex:0];
[newView setImage:[UIImage imageNamed:[NSString stringWithFormat:@"ipad_wallpaper%02d.jpg",secondPage+1]]];
[contentView exchangeSubviewAtIndex:0 withSubviewAtIndex:1];
[[contentView layer] addAnimation:transition forKey:@"transitionView Animation"];
currentPage = [pageControl currentPage];
}
结合ScrollView后关于UIPageControl的页面设置算法:
// 在ScrollView的委托方法中
int index = fabs(scrollView.contentOffset.x) / scrollView.frame.size.width;
pageControl.currentPage = index;
自定义之一:给UIPageControl控件添加背景
1 int pagesCount =5;
2 UIPageControl *pageControl = [[UIPageControl alloc] init];
3 pageControl.center = CGPointMake(self.view.frame.size.width/2, self.view.frame.size.height-15); // 设置pageControl的位置
4 pageControl.numberOfPages = pagesCount;
5 pageControl.currentPage = 0;
6
7 [pageControl setBounds:CGRectMake(0,0,16*(pagesCount-1)+16,16)]; //页面控件上的圆点间距基本在16左右。
8 [pageControl.layer setCornerRadius:8]; // 圆角层
9 [pageControl.setBackgroundColor:[UIColor clorWithWhite:0.0 alpha:0.2]];
10 [self.view addSubview:pageControl];
1 int pagesCount =5;
2 UIPageControl *pageControl = [[UIPageControl alloc] init];
3 pageControl.center = CGPointMake(self.view.frame.size.width/2, self.view.frame.size.height-15); // 设置pageControl的位置
4 pageControl.numberOfPages = pagesCount;
5 pageControl.currentPage = 0;
6
7 [pageControl setBounds:CGRectMake(0,0,16*(pagesCount-1)+16,16)]; //页面控件上的圆点间距基本在16左右。
8 [pageControl.layer setCornerRadius:8]; // 圆角层
9 [pageControl.setBackgroundColor:[UIColor clorWithWhite:0.0 alpha:0.2]];
10 [self.view addSubview:pageControl];