動(dòng)畫二

隔了好多天退疫,因?yàn)樵诿e的事渠缕。。褒繁。
那我們現(xiàn)在要做什么亦鳞,上一篇講到一個(gè)滾動(dòng)大屏圖,巨丑。
趁著回憶的時(shí)間燕差,先添兩行代碼

 //隱藏滾動(dòng)條
 self.collectionView.showsVerticalScrollIndicator = NO;
 self.collectionView.showsHorizontalScrollIndicator = NO;

開始正題

讓item變小

毫無疑問遭笋,這是一個(gè)很簡單的事情。我們首先應(yīng)該去設(shè)置itemSize,然后設(shè)置行(這里是縱向)間距徒探,其次可以做一個(gè)組邊距(sectionInset)使其兩邊留白瓦呼。
當(dāng)然簡單的事情就要考慮的稍微多一點(diǎn),這個(gè)size要怎么設(shè)置(200测暗,300)央串,這樣可能在不同大小的屏幕上會(huì)有很明顯的差別,那有人會(huì)說可以像Masonry(一個(gè)layout的框架)設(shè)置與其他UI的關(guān)系位置偷溺,這是一種策略蹋辅,但是不見得好,因?yàn)樗皇且粋€(gè)純色的東西挫掏。根據(jù)其他位置拉伸變化(即便可以保持圖片不拉伸)也不見得好侦另,所以可以看很多代碼會(huì)有一堆屏幕大小的宏,然后根據(jù)一個(gè)(200尉共,300)針對(duì)某一尺寸的屏幕褒傅,對(duì)于不同的屏幕,按屏幕比等比擴(kuò)大的代碼袄友。這個(gè)可以自行實(shí)現(xiàn)殿托,我做簡單易懂一點(diǎn)

#define ItemHeight (ScreenHeight * (5.0 / 9))
#define ItemWidth (ScreenWidth * (3.0 / 5))

然后相應(yīng)的代碼變成

self.itemSize = CGSizeMake(ItemWidth, ItemHeight);
self.scrollDirection = UICollectionViewScrollDirectionHorizontal;   //水平方向
self.sectionInset = UIEdgeInsetsMake(0, ScreenWidth/2 - ItemWidth/2, 0, ScreenWidth/2 - ItemWidth/2);   //設(shè)置組邊距
self.minimumLineSpacing = (ScreenWidth - ItemWidth)/4;

這里忘了提一個(gè)東西,我在這次加了一個(gè)pch(全局不需要自己導(dǎo)入的.h - -),當(dāng)然里面放太多的東西會(huì)影響效率剧蚣,至于添加方法自行百度支竹,也可以做個(gè).h自行導(dǎo)入,差不多

cell居中設(shè)置

現(xiàn)在我們的跑一下我們的代碼鸠按,當(dāng)你停止滑動(dòng)的時(shí)候礼搁,它會(huì)停在一個(gè)當(dāng)前的位置,但是這個(gè)位置可能是兩個(gè)卡片(cell)的中間目尖,或者偏一點(diǎn)的地方薛训,我們需要的是對(duì)卡片進(jìn)行操作邀桑,所以需要讓它居中。所以引入一個(gè)問題撼港,如果只是不小心的觸碰到屏幕辙喂,稍稍的滑了一下局齿,需要切換嗎罢浇?顯然是不需要的讼积,把這個(gè)一下量化一下(設(shè)置為distance)以后,變成<distance的距離不需要切換烦衣,而>distance的距離就切換卡片篮赢。在這樣的思路確定以后齿椅,我們開始實(shí)現(xiàn)這個(gè)邏輯
代理也是繼承的琉挖,所以這樣的效果應(yīng)該在scrollView的代理里實(shí)現(xiàn)

//開始拖拽collectionView(scrollView的子類)
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
//停止拖拽collectionView
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate

在這兩個(gè)方法里面可以拿到起始的位置启泣,和結(jié)束的位置,他們到底是怎么樣的示辈,可以在里面打印輸出一下

//向左滑
2018-01-29 19:37:03.265 卡片轉(zhuǎn)場(chǎng)1[31481:1202165] 開始拖動(dòng)0.000000
2018-01-29 19:37:04.624 卡片轉(zhuǎn)場(chǎng)1[31481:1202165] 停止拖動(dòng)105.000000
2018-01-29 19:37:06.905 卡片轉(zhuǎn)場(chǎng)1[31481:1202165] 開始拖動(dòng)105.000000
2018-01-29 19:37:07.729 卡片轉(zhuǎn)場(chǎng)1[31481:1202165] 停止拖動(dòng)124.000000
2018-01-29 19:37:10.943 卡片轉(zhuǎn)場(chǎng)1[31481:1202165] 開始拖動(dòng)124.000000

//向右滑
2018-01-29 19:38:26.746 卡片轉(zhuǎn)場(chǎng)1[31481:1202165] 開始拖動(dòng)1449.000000
2018-01-29 19:38:28.164 卡片轉(zhuǎn)場(chǎng)1[31481:1202165] 停止拖動(dòng)1404.000000
2018-01-29 19:38:30.113 卡片轉(zhuǎn)場(chǎng)1[31481:1202165] 開始拖動(dòng)1404.000000
2018-01-29 19:38:30.547 卡片轉(zhuǎn)場(chǎng)1[31481:1202165] 停止拖動(dòng)1371.333333
2018-01-29 19:38:32.806 卡片轉(zhuǎn)場(chǎng)1[31481:1202165] 開始拖動(dòng)1371.333333

明白這樣的變化以后寥茫,我們聲明幾個(gè)類內(nèi)的變量

   CGFloat     _startDragX;        //開始移動(dòng)的位置
   CGFloat     _endDragX;          //停止移動(dòng)的位置
   CGFloat     _dragMiniDistance;  //最小移動(dòng)的臨界值
   NSInteger   _currentIndex;      //當(dāng)前切換到的卡片索引位置
   NSInteger   _maxIndex;          //最大的索引位置
//在開始拖動(dòng)的方法里獲取到 _startDragX
_startDragX = scrollView.contentOffset.x;
//在停止拖動(dòng)的方法里獲取到_endDragX
_endDragX = scrollView.contentOffset.x;
然后根據(jù)上面的邏輯進(jìn)行一系列的簡單運(yùn)算判斷:
CGFloat delta = _startDragX - _endDragX;

if (delta >= _dragMiniDistance) {
    //向右滑動(dòng)
    _currentIndex -= 1;  
 } else if (delta * -1 >= _dragMiniDistance) {
     //向左滑動(dòng)
     _currentIndex += 1;
 }
    
 _currentIndex = _currentIndex <= 0 ? 0 : _currentIndex;
 _currentIndex = _currentIndex >= _maxIndex ? _maxIndex : _currentIndex;

這樣我們就可以調(diào)用scrollToItemAtIndexPath: atScrollPosition這個(gè)方法實(shí)現(xiàn)滑動(dòng)了,但是這里要注意一點(diǎn)矾麻,就是所有tableView,collectionView這些數(shù)據(jù)源方法的特殊性纱耻,如果你同步執(zhí)行的話,他們的數(shù)據(jù)源方法可能還沒有在內(nèi)部算清险耀,所以就會(huì)出Bug弄喘,所以對(duì)于這個(gè)方法,我們需要用主隊(duì)列異步去執(zhí)行甩牺,很多代碼里面就把類似上面的一堆運(yùn)算也扔在異步隊(duì)列里蘑志,其實(shí)不用,我們只是要把UI更新放進(jìn)去.

dispatch_async(dispatch_get_main_queue(), ^{
 [self.collectionView scrollToItemAtIndexPath:[NSIndexPath indexPathForRow:_currentIndex inSection:0]
 atScrollPosition:UICollectionViewScrollPositionCenteredHorizontally animated:YES];
 });

//順帶利用這個(gè)_currentIndex的索引贬派,可以把背后的蒙版也換一下
self.BgView.image = [UIImage imageNamed:self.imageArray[_currentIndex].cardPicName];

調(diào)整布局屬性

現(xiàn)在有個(gè)問題需要我們考慮急但,就是每個(gè)卡片的大小都是一樣,看示例gif明顯當(dāng)前屏幕中間的大搞乏,兩邊的小波桩。所以我們也要這樣做,調(diào)整cell的大小请敦,在UICollectionView里面镐躲,他們的大小(還有透明度這些屬性)是歸于布局屬性負(fù)責(zé)的侍筛,所以我們要調(diào)整布局屬性萤皂,在哪里調(diào)整,當(dāng)然是代理方法了勾笆,一個(gè)UICollectionViewFlowLayout的父類代理UICollectionViewLayout里面有l(wèi)ayoutAttributesForElementsInRect:(CGRect)rect這樣一個(gè)方法敌蚜,是這樣介紹的
//Implement -layoutAttributesForElementsInRect:
//to return layout attributes for for supplementary or decoration views, or to perform layout in an as-needed-on-screen fashion.
翻譯過來就是:返回 追加的 或者 裝飾視圖 布局屬性 或者去適應(yīng)屏幕上的布局。
還有一個(gè)這樣的方法:
-(UICollectionViewLayoutAttributes*)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath
很明顯是對(duì)每個(gè)具體cell的布局進(jìn)行調(diào)整
這里我們的需求其實(shí)是對(duì)兩邊cell的大小進(jìn)行統(tǒng)一的調(diào)整窝爪,其實(shí)也不用具體到張三弛车,李四cell這個(gè)具體的cell上,只要是在兩邊的就進(jìn)行縮放就好了蒲每,所以選擇第一個(gè)方法去實(shí)現(xiàn)

- (NSArray<UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect
{
    //這樣就拿到了所有的布局屬性
    NSArray<UICollectionViewLayoutAttributes *> *arr = [super layoutAttributesForElementsInRect:rect].copy;
    
    return arr;
}

這里同樣有個(gè)問題需要說明纷跛,就是蘋果規(guī)定,我們不能直接去拿系統(tǒng)生成這些原有的布局屬性邀杏,對(duì)這些原有的布局進(jìn)行更改贫奠,直接更改會(huì)報(bào)錯(cuò)(我們不展開去解釋這個(gè)問題)唬血,所以我用了.copy,其實(shí)這樣用也不好唤崭,在你運(yùn)行的時(shí)候拷恨,還是會(huì)給你一堆警告

Logging only once for UICollectionViewFlowLayout cache mismatched frame
UICollectionViewFlowLayout has cached frame mismatch for index path <NSIndexPath: 0xc000000000000016> {length = 2, path = 0 - 0} - cached value: {{82.666666666666686, 163.66667320702987}, {248.39999999999998, 408.88887580816248}}; expected value: {{82.666666666666671, 163.66666666666666}, {248.39999999999998, 408.88888888888891}}
This is likely occurring because the flow layout subclass CardFlowLayout is modifying attributes returned by UICollectionViewFlowLayout without copying them

就是告訴你這樣不好,但是通常好像也不會(huì)出錯(cuò)谢肾,但是為了避免這樣腕侄,我們可以干脆做一個(gè)拷貝的方法

- (NSArray *)getCopyOfAttributes:(NSArray *)attributes {
    NSMutableArray *copyArr = [NSMutableArray new];
    for (UICollectionViewLayoutAttributes *attribute in attributes) {
        [copyArr addObject:[attribute copy]];
    }
    return copyArr;
}

這樣就ok了。
接著寫我們的代碼芦疏,這里單獨(dú)說一點(diǎn)collectionView的位置不是屏幕大小的位置冕杠,它是內(nèi)部展開的位置

    //獲取屏幕中線
    CGFloat centerX = self.collectionView.contentOffset.x + self.collectionView.bounds.size.width / 2.0;
    //拿到每個(gè)屬性
    for (UICollectionViewLayoutAttributes *attr in arr) {
       
        //布局屬性與中線的距離
        CGFloat distance = fabs(attr.center.x - centerX);
        //距離與屏幕寬的比例(為了計(jì)算縮放的比例)
        CGFloat disScale = distance / self.collectionView.bounds.size.width;
        //確定縮放的大小
        CGFloat scale = fabs(cos(disScale * M_PI / 4));
        
        //對(duì)布局屬性進(jìn)行縮放變換
        //如果想要3D傾斜的變化,也可以在這里指定為3D變化
        attr.transform = CGAffineTransformMakeScale(1.0, scale);
        
        //同時(shí)也利用這個(gè)比例對(duì)透明度進(jìn)行一下更改酸茴,顯得自然
        attr.alpha = scale;
    
    }

但是這樣運(yùn)行以后我們又發(fā)現(xiàn)一個(gè)問題分预,就是他們好像是一順縮小的,越來越小薪捍,一看我們的代碼笼痹,是啊,我們?cè)O(shè)置的就是把屬性縮小了飘诗,縮小的屬性的后面的屬性就變得更小了与倡。所以我們要調(diào)整代碼,讓他們下次恢復(fù)之前的約束昆稿,然后再進(jìn)行變化纺座,剛好有這樣一個(gè)方法:- (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds
//判定為布局需要被無效化并重新計(jì)算的時(shí)候,布局對(duì)象會(huì)被詢問以提供新的布局
所以我們只需要在這里返回YES就好了。
這樣這篇文章就可以完了

3月-12-2018 17-00-40.gif

再下面就要對(duì)cell內(nèi)部進(jìn)行復(fù)雜操作了溉潭。净响。。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末喳瓣,一起剝皮案震驚了整個(gè)濱河市馋贤,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌畏陕,老刑警劉巖配乓,帶你破解...
    沈念sama閱讀 218,525評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異惠毁,居然都是意外死亡犹芹,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,203評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門鞠绰,熙熙樓的掌柜王于貴愁眉苦臉地迎上來腰埂,“玉大人,你說我怎么就攤上這事蜈膨∮炝” “怎么了牺荠?”我有些...
    開封第一講書人閱讀 164,862評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長驴一。 經(jīng)常有香客問我休雌,道長,這世上最難降的妖魔是什么蛔趴? 我笑而不...
    開封第一講書人閱讀 58,728評(píng)論 1 294
  • 正文 為了忘掉前任挑辆,我火速辦了婚禮,結(jié)果婚禮上孝情,老公的妹妹穿的比我還像新娘。我一直安慰自己洒嗤,他們只是感情好箫荡,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,743評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著渔隶,像睡著了一般羔挡。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上间唉,一...
    開封第一講書人閱讀 51,590評(píng)論 1 305
  • 那天绞灼,我揣著相機(jī)與錄音,去河邊找鬼呈野。 笑死低矮,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的被冒。 我是一名探鬼主播军掂,決...
    沈念sama閱讀 40,330評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼昨悼!你這毒婦竟也來了蝗锥?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,244評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤率触,失蹤者是張志新(化名)和其女友劉穎终议,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體葱蝗,經(jīng)...
    沈念sama閱讀 45,693評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡穴张,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,885評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了垒玲。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片陆馁。...
    茶點(diǎn)故事閱讀 40,001評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖合愈,靈堂內(nèi)的尸體忽然破棺而出叮贩,到底是詐尸還是另有隱情击狮,我是刑警寧澤,帶...
    沈念sama閱讀 35,723評(píng)論 5 346
  • 正文 年R本政府宣布益老,位于F島的核電站彪蓬,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏捺萌。R本人自食惡果不足惜档冬,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,343評(píng)論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望桃纯。 院中可真熱鬧酷誓,春花似錦、人聲如沸态坦。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,919評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽伞梯。三九已至玫氢,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間谜诫,已是汗流浹背漾峡。 一陣腳步聲響...
    開封第一講書人閱讀 33,042評(píng)論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留喻旷,地道東北人生逸。 一個(gè)月前我還...
    沈念sama閱讀 48,191評(píng)論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像掰邢,于是被迫代替她去往敵國和親牺陶。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,955評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

  • 問答題47 /72 常見瀏覽器兼容性問題與解決方案辣之? 參考答案 (1)瀏覽器兼容問題一:不同瀏覽器的標(biāo)簽?zāi)J(rèn)的外補(bǔ)...
    _Yfling閱讀 13,754評(píng)論 1 92
  • 在上篇文章 屬性動(dòng)畫(一) 中已經(jīng)對(duì)屬性動(dòng)畫有了基本的介紹掰伸,本篇文章將對(duì)屬性動(dòng)畫中稍微高級(jí)點(diǎn)的內(nèi)容進(jìn)行介紹,主要介...
    lijiankun24閱讀 357評(píng)論 0 0
  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,144評(píng)論 25 707
  • 1 懶加載 懶加載與OC中的懶加載的區(qū)別:懶加載的類一旦 設(shè)置為nil 后怀估, 懶加載就不會(huì)再次執(zhí)行狮鸭,與OC中不同,...
    JunShine閱讀 226評(píng)論 0 0
  • 2011年9月歧蕉,作為大一懵懂的小學(xué)妹,由著自己想作為志愿者的情愫康铭,過關(guān)斬將成為紅十字協(xié)會(huì)的一員惯退,便遇上了此生...
    傻子薛閱讀 194評(píng)論 0 1