Demo地址:https://github.com/FlashHand/BuffKit
运行BuffDemo里的工程,找到轮播图即可查看。
使用简介:
{
BFLoopView *bfLoopView;
}
//.m
NSMutableArray *btnArr=[NSMutableArray new];
for (int i=0; i<3; i++) {
UIButton *btn=[[UIButton alloc]initWithFrame:CGRectMake(0, 0, self.view.width, 220)];
[btn setTitle:[NSString stringWithFormat:@"Button:%d",i] forState:UIControlStateNormal];
UIImage *img=[UIImage imageNamed:[NSString stringWithFormat:@"loop%d.jpg",i+1]];
[btn setBackgroundImage:img forState:UIControlStateNormal];
[btn setBackgroundColor:[UIColor lightGrayColor]];
[btn addTarget:self action:@selector(loopViewClickAction:) forControlEvents:UIControlEventTouchUpInside];
[btn setTag:i];
[btnArr addObject:btn];
}
//period是播放周期,duration是滑动动画的持续时间.
bfLoopView=[BFLoopView loopViewWithItems:btnArr
frame:CGRectMake(0, 64, self.view.width, 220) loopPeriod:4
animationDuration:1
animationStyle:BuffLoopViewAnimationStyleEasyInOut
indexChanged:^(NSInteger loopIndex) {
//当前页面索引变化时执行的回调
}];
[self.view addSubview:bfLoopView];
[bfLoopView setShouldAnimation:YES];//开始并允许自动轮播,
[bfLoopView setShouldAnimation:NO];//停止并禁止自动轮播,
实现自动轮播的思路:
1.使用无限宽的UISCrollView(实际上是INT16_MAX+1
[loopView setPagingEnabled:YES];
[loopView setBounces:NO];
[loopView setContentSize:CGSizeMake(frame.size.width*(INT16_MAX+1), frame.size.height)];
[loopView setShowsVerticalScrollIndicator:NO];
[loopView setShowsHorizontalScrollIndicator:NO];
[loopView setDirectionalLockEnabled:YES];
2.放置所有视图,这里我决定把视图放置在UISCrollView偏居中的位置,下面是计算方法,这样算的好处是:一是能确保初始位置是偏居中的,二是确保初始位置的偏移量是单页宽度的整数倍
CGFloat initialOffsetX=floor(loopView.contentSize.width/2.0/loopItems.count/loopView.width)*loopView.width*loopItems.count;
[loopView setContentOffset:CGPointMake(initialOffsetX, 0)];
3.控制自动轮播
通过CADisplayLink+NSTimer实现对UIScrollView的准确控制,
若使用UIView或UIScrollView自带的动画则动画的时间曲线不好控制,轮播时可能会卡住且没法处理。
NSTimer控制何时开始播放动画
CADisplayLink配合CACurrentMediaTime()控制动画的播放过程
具体请查看demo
4.关于动画的时间曲线,时间曲线是通过这个block去计算的
static void(^_bfAnimationFunction)(CGFloat p);
当你需要自定义时间曲线函数的时候可以通过调用
setLoopAnimationStyle:BuffLoopViewAnimationStyleCustom
然后使用“
-(void)setCustomAnimationStyle:(void(^)(CGFloat p))animationFunction;”来实现自定义的时间曲线,且该函数必须满足f(0)=0,f(1)=1
预先设置block可以避免在CADisplayLink的触发的函数里做多余的判断,导致性能降低
下面是不同的时间曲线的映射方法:
算法参考:
http://www.cnblogs.com/cloudgamer/archive/2009/01/06/Tween.html
https://github.com/danro/jquery-easing/blob/master/jquery.easing.js
//easing 算法
//x ∈ [0,1]
//Linear:f(x)=x
BuffLoopViewAnimationStyleLinear = 1,
//easyIn:f(x)=-cos(x * (M_PI/2)+1
BuffLoopViewAnimationStyleEasyIn = 2,
//easyInOut:f(x)=-0.5*cos(M_PI*x)+0.5
BuffLoopViewAnimationStyleEasyInOut = 3,
//easyOut:f(x)=sin(x * M_PI/2)
BuffLoopViewAnimationStyleEasyOut = 4,
//custom:使用 "-(void)setAnimationStyle:(void(^)(CGFloat p))animationFunction;"自定义切换效果。
//注意,必须满足f(0)=0,f(1)=1
BuffLoopViewAnimationStyleCustom = 100,
5.添加页面切换回调:
static void(^_bfIndexChanged)(NSInteger i);
默认会显示一个UIPageControl,若不需要刻意隐藏掉然后利用_bfIndexChanged获取页面切换情况。
你可以直接运行demo,找到LoopViewController查看轮播图的使用方式。
如果你有任何问题或意见,欢迎通过简书留言: )