轉(zhuǎn)載:http://blog.csdn.net/u013282507/article/details/54136812
一淹魄、實(shí)現(xiàn)效果
要實(shí)現(xiàn)這樣的效果總共分三步:實(shí)現(xiàn)橫向滾動(dòng)堡距、居中放大甲锡、自動(dòng)居中兆蕉。下面就仔細(xì)說(shuō)一下具體的細(xì)節(jié):
橫向滾動(dòng)是通過(guò)UICollectionView的橫向滾動(dòng)特性實(shí)現(xiàn)的缤沦,這里的數(shù)據(jù)源用plist文件模擬了一下
初始化數(shù)據(jù):
[objc]view plaincopy
NSString*filePath?=?[[NSBundlemainBundle]pathForResource:@"DataPropertyList"ofType:@"plist"];
NSArray*arr?=?[NSArrayarrayWithContentsOfFile:filePath];
NSMutableArray*models?=?[NSMutableArraynew];
for(NSDictionary*dic?in?arr)?{
XLCardModel*model?=?[XLCardModelnew];
[modelsetValuesForKeysWithDictionary:dic];
[modelsaddObject:model];
}
下面是Collectionview創(chuàng)建的方法:
[objc]view plaincopy
XLCardSwitchFlowLayout*flowLayout?=?[[XLCardSwitchFlowLayoutalloc]init];
[flowLayoutsetItemSize:CGSizeMake(200,self.bounds.size.height)];
//設(shè)置滾動(dòng)方向
[flowLayoutsetScrollDirection:UICollectionViewScrollDirectionHorizontal];
_collectionView?=?[[UICollectionViewalloc]initWithFrame:self.boundscollectionViewLayout:flowLayout];
_collectionView.showsHorizontalScrollIndicator=false;
_collectionView.backgroundColor=?[UIColorclearColor];
[_collectionViewregisterClass:[XLCardclass]forCellWithReuseIdentifier:@"XLCard"];
[_collectionViewsetUserInteractionEnabled:YES];
_collectionView.delegate=self;
_collectionView.dataSource=self;
[selfaddSubview:_collectionView];
數(shù)據(jù)源方法:
[objc]view plaincopy
-(UICollectionViewCell*)collectionView:(UICollectionView*)collectionViewcellForItemAtIndexPath:(NSIndexPath*)indexPath
{
staticNSString*?cellId?=@"XLCard";
XLCard*?card?=?[collectionViewdequeueReusableCellWithReuseIdentifier:cellIdforIndexPath:indexPath];
card.model=?_models[indexPath.row];
returncard;
}
這里用到了一個(gè)是自定義的FlowLayout虎韵,在以后放大工能中會(huì)使用到,實(shí)現(xiàn)的效果如下:
要實(shí)現(xiàn)第一個(gè)cell和最后一個(gè)cell都能滾動(dòng)到屏幕居中的位置還需要加一下縮進(jìn):
[objc]view plaincopy
//設(shè)置左右縮進(jìn)
-(CGFloat)collectionInset
{
returnself.bounds.size.width/2.0f-?[selfcellWidth]/2.0f;
}
-(UIEdgeInsets)collectionView:(UICollectionView*)collectionViewlayout:(UICollectionViewLayout*)collectionViewLayoutinsetForSectionAtIndex:(NSInteger)section
{
returnUIEdgeInsetsMake(0,?[selfcollectionInset],0,?[selfcollectionInset]);
}
效果如下:
在自定義的UIcollectionFlowLayout中的layoutAttributesForElementsInRect方法里中設(shè)置放大的功能缸废,放大功能主要是通過(guò)余弦函數(shù)曲線特性實(shí)現(xiàn)的包蓝,當(dāng)x = 0時(shí)y = 1,兩側(cè)遞減:
可以參考我之前寫過(guò)的一篇博客:利用余弦函數(shù)實(shí)現(xiàn)卡片瀏覽工具
[objc]view plaincopy
//設(shè)置放大動(dòng)畫
-(NSArray?*)layoutAttributesForElementsInRect:(CGRect)rect
{
NSArray*arr?=?[selfgetCopyOfAttributes:[superlayoutAttributesForElementsInRect:rect]];
//屏幕中線
CGFloat?centerX?=self.collectionView.contentOffset.x+self.collectionView.bounds.size.width/2.0f;
//刷新cell縮放
for(UICollectionViewLayoutAttributes*attributes?in?arr)?{
CGFloat?distance?=?fabs(attributes.center.x-?centerX);
//移動(dòng)的距離和屏幕寬度的的比例
CGFloat?apartScale?=?distance/self.collectionView.bounds.size.width;
//把卡片移動(dòng)范圍固定到?-π/4到?+π/4這一個(gè)范圍內(nèi)
CGFloat?scale?=?fabs(cos(apartScale*?M_PI/4));
//設(shè)置cell的縮放?按照余弦函數(shù)曲線?越居中越趨近于1
attributes.transform=?CGAffineTransformMakeScale(1.0,?scale);
}
returnarr;
}
[objc]view plaincopy
//防止報(bào)錯(cuò)?先復(fù)制attributes
-?(NSArray*)getCopyOfAttributes:(NSArray*)attributes
{
NSMutableArray*copyArr?=?[NSMutableArraynew];
for(UICollectionViewLayoutAttributes*attribute?in?attributes)?{
[copyArraddObject:[attributecopy]];
}
returncopyArr;
}
[objc]view plaincopy
//是否需要重新計(jì)算布局
-(BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds
{
returntrue;
}
實(shí)現(xiàn)效果如下:
設(shè)置全局屬性养晋,保存拖拽開始位置、結(jié)束位置和更新之后的位置梁钾。在手指拖拽開始記錄起始位置绳泉,手指離開時(shí)記錄結(jié)束位置并居中卡片。
[objc]view plaincopy
NSInteger?_currentIndex;
CGFloat?_dragStartX;
CGFloat?_dragEndX;
[objc]view plaincopy
//手指拖動(dòng)開始
-(void)scrollViewWillBeginDragging:(UIScrollView*)scrollView
{
_dragStartX?=?scrollView.contentOffset.x;
}
//手指拖動(dòng)停止
-(void)scrollViewDidEndDragging:(UIScrollView*)scrollViewwillDecelerate:(BOOL)decelerate
{
_dragEndX?=?scrollView.contentOffset.x;
dispatch_async(dispatch_get_main_queue(),?^{
[selffixCellToCenter];
});
}
[objc]view plaincopy
//配置cell居中
-(void)fixCellToCenter
{
//最小滾動(dòng)距離
floatdragMiniDistance?=self.bounds.size.width/20.0f;
if(_dragStartX?-??_dragEndX?>=?dragMiniDistance)?{
_currentIndex?-=1;//向右
}elseif(_dragEndX?-??_dragStartX?>=?dragMiniDistance){
_currentIndex?+=1;//向左
}
NSInteger?maxIndex?=?[_collectionViewnumberOfItemsInSection:0]?-1;
_currentIndex?=?_currentIndex?<=0?0:?_currentIndex;
_currentIndex?=?_currentIndex?>=?maxIndex???maxIndex?:?_currentIndex;
[_collectionViewscrollToItemAtIndexPath:[NSIndexPathindexPathForRow:_currentIndexinSection:0]atScrollPosition:UICollectionViewScrollPositionCenteredHorizontallyanimated:YES];
}
[objc]view plaincopy
_cardSwitch?=?[[XLCardSwitchalloc]initWithFrame:CGRectMake(0,64,self.view.bounds.size.width,self.view.bounds.size.height-64)];
_cardSwitch.models=?models;
_cardSwitch.delegate=self;
[self.viewaddSubview:_cardSwitch];
[objc]view plaincopy
-(void)XLCardSwitchDidSelectedAt:(NSInteger)index
{
NSLog(@"選中了:%zd",index);
}