Texture中使用ASCollectionNode構(gòu)建瀑布流

本篇文章主要是針對如何在 ASCollectionNode中構(gòu)建瀑布流提供一種思路需忿,可以滿足大部分的產(chǎn)品需求刻诊。當(dāng)你看到這篇文章時矗烛,說明你對Texture的布局方式已經(jīng)熟悉趴泌,因此本篇文章對布局就不做說明告组。

先來一個效果圖

使用ASCollectionNode構(gòu)建瀑布流煤伟,可以真正的做到內(nèi)容自適應(yīng),不用去計(jì)算煩人的headerHeight木缝、footerHeight便锨、itemSize


image.png

第一步:新建一個類,命名為YHASCollectionLayoutInfo

image.png

注意:
1我碟、isEqualhash方法必須實(shí)現(xiàn)放案,具體原因接下來要講.
2、該類并沒有設(shè)置類似headerHeight和footerHeight的屬性矫俺,原因是:我希望headerHeight和footerHeight的高度由內(nèi)部子元素決定吱殉。

第二步:新建一個類,命名為YHASCollectionLayoutDelegate恳守,實(shí)現(xiàn) ASCollectionLayoutDelegateASCollectionViewLayoutInspecting協(xié)議

1考婴、初始化方法:

image.png

2、實(shí)現(xiàn)ASCollectionViewLayoutInspecting協(xié)議催烘,嚴(yán)格來說沥阱,該協(xié)議并不需要實(shí)現(xiàn),但是Texture框架本身卻要求必須實(shí)現(xiàn).引用其Demo中的注釋The below 2 methods are required by ASCollectionViewLayoutInspecting, but ASCollectionLayout and its layout delegate are the ones that really determine the size ranges and directions伊群,由此可知考杉,ASCollectionLayoutDelegate才是真正決定ASCollectionNode范圍和滑動方向的地方策精。

image.png

3、實(shí)現(xiàn)ASCollectionLayoutDelegate(這才是重頭戲)
第一步:設(shè)置滑動方向

image.png

第二步:返回布局信息
image.png

點(diǎn)擊進(jìn)入該方法的注釋崇棠,由此可知為什么必須實(shí)現(xiàn)isEqualhash方法
image.png

第三步:計(jì)算每個Item以及header和footer的位置(大部分參考了官方Demo咽袜,本人在其基礎(chǔ)上進(jìn)行了修改)

// 真正布局的地方.
+ (ASCollectionLayoutState *)calculateLayoutWithContext:(ASCollectionLayoutContext *)context{
    CGFloat layoutWidth = context.viewportSize.width;
    ASElementMap *elements = context.elements;
    CGFloat top = 0;
    YHASCollectionLayoutInfo *info = (YHASCollectionLayoutInfo *)context.additionalInfo;
    
    NSMapTable<ASCollectionElement *, UICollectionViewLayoutAttributes *> *attrsMap = [NSMapTable elementToLayoutAttributesTable];
    NSMutableArray *columnHeights = [NSMutableArray array];
    
    NSInteger numberOfSections = [elements numberOfSections];
    
    // 遍歷section.
    for (NSUInteger section = 0; section < numberOfSections; section++) {
        
        NSInteger numberOfItems = [elements numberOfItemsInSection:section];
        
        top += info.sectionInsets.top;
        
        NSIndexPath *indexPath = [NSIndexPath indexPathForItem:0 inSection:section];
        
        // header.
        ASCollectionElement *headerElement = [elements supplementaryElementOfKind:UICollectionElementKindSectionHeader atIndexPath:indexPath];
        if (headerElement) {
            UICollectionViewLayoutAttributes *attrs = [UICollectionViewLayoutAttributes layoutAttributesForSupplementaryViewOfKind:UICollectionElementKindSectionHeader
                                                                                                                     withIndexPath:indexPath];
            CGSize size = [headerElement.node layoutThatFits:ASSizeRangeUnconstrained].size;
            CGRect frame = CGRectMake(info.sectionInsets.left, top, size.width, size.height);
            attrs.frame = frame;
            [attrsMap setObject:attrs forKey:headerElement];
            top = CGRectGetMaxY(frame);
        }
        
        //
        [columnHeights addObject:[NSMutableArray array]];
        for (NSUInteger idx = 0; idx < info.numberOfColumns; idx++) {
            [columnHeights[section] addObject:@(top)];
        }
        
    
        // item.
        CGFloat columnWidth = [self _columnWidthForSection:section withLayoutWidth:layoutWidth info:info];
        
        for (NSUInteger idx = 0; idx < numberOfItems; idx++) {
            NSUInteger columnIndex = [self _shortestColumnIndexInSection:section withColumnHeights:columnHeights];
            NSIndexPath *indexPath = [NSIndexPath indexPathForItem:idx inSection:section];
            ASCollectionElement *element = [elements elementForItemAtIndexPath:indexPath];
            UICollectionViewLayoutAttributes *attrs = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath];
            
            ASSizeRange sizeRange = [self _sizeRangeForItem:element.node atIndexPath:indexPath withLayoutWidth:layoutWidth info:info];
            CGSize size = [element.node layoutThatFits:sizeRange].size;
            CGPoint position = CGPointMake(info.sectionInsets.left + (columnWidth + info.columnSpacing) * columnIndex,
                                           [columnHeights[section][columnIndex] floatValue]);
            CGRect frame = CGRectMake(position.x, position.y, size.width, size.height);
            
            attrs.frame = frame;
            [attrsMap setObject:attrs forKey:element];
            
            columnHeights[section][columnIndex] = @(CGRectGetMaxY(frame) + info.interItemSpacing);
        }
        
        NSUInteger columnIndex = [self _tallestColumnIndexInSection:section withColumnHeights:columnHeights];
        top = [columnHeights[section][columnIndex] floatValue] - info.interItemSpacing + info.sectionInsets.bottom;
        
        
        // footer.
        ASCollectionElement *footerElement = [elements supplementaryElementOfKind:UICollectionElementKindSectionFooter atIndexPath:indexPath];
        if (footerElement) {
            UICollectionViewLayoutAttributes *attrs = [UICollectionViewLayoutAttributes layoutAttributesForSupplementaryViewOfKind:UICollectionElementKindSectionFooter withIndexPath:indexPath];
            CGSize size = [footerElement.node layoutThatFits:ASSizeRangeUnconstrained].size;
            CGRect frame = CGRectMake(info.sectionInsets.left, top, size.width, size.height);
            attrs.frame = frame;
            [attrsMap setObject:attrs forKey:footerElement];
            top = CGRectGetMaxY(frame);
        }
        
        //
        for (NSUInteger idx = 0; idx < [columnHeights[section] count]; idx++) {
            columnHeights[section][idx] = @(top);
        }
    }
    
    CGFloat contentHeight = [[[columnHeights lastObject] firstObject] floatValue];
    CGSize contentSize = CGSizeMake(layoutWidth, contentHeight);
    return [[ASCollectionLayoutState alloc] initWithContext:context contentSize:contentSize elementToLayoutAttributesTable:attrsMap];
}



+ (CGFloat)_columnWidthForSection:(NSUInteger)section withLayoutWidth:(CGFloat)layoutWidth info:(YHASCollectionLayoutInfo *)info{
    return ([self _widthForSection:section withLayoutWidth:layoutWidth info:info] - ((info.numberOfColumns - 1) * info.columnSpacing)) / info.numberOfColumns;
}

+ (CGFloat)_widthForSection:(NSUInteger)section withLayoutWidth:(CGFloat)layoutWidth info:(YHASCollectionLayoutInfo *)info{
    return layoutWidth - info.sectionInsets.left - info.sectionInsets.right;
}

+ (NSUInteger)_shortestColumnIndexInSection:(NSUInteger)section withColumnHeights:(NSArray *)columnHeights{
    __block NSUInteger index = 0;
    __block CGFloat shortestHeight = CGFLOAT_MAX;
    [columnHeights[section] enumerateObjectsUsingBlock:^(NSNumber *height, NSUInteger idx, BOOL *stop) {
        if (height.floatValue < shortestHeight) {
            index = idx;
            shortestHeight = height.floatValue;
        }
    }];
    return index;
}

+ (ASSizeRange)_sizeRangeForItem:(ASCellNode *)item atIndexPath:(NSIndexPath *)indexPath withLayoutWidth:(CGFloat)layoutWidth info:(YHASCollectionLayoutInfo *)info {
    CGFloat itemWidth = [self _columnWidthForSection:indexPath.section withLayoutWidth:layoutWidth info:info];
    return ASSizeRangeMake(CGSizeMake(itemWidth, 0), CGSizeMake(itemWidth, CGFLOAT_MAX));
}

+ (NSUInteger)_tallestColumnIndexInSection:(NSUInteger)section withColumnHeights:(NSArray *)columnHeights{
    __block NSUInteger index = 0;
    __block CGFloat tallestHeight = 0;
    [columnHeights[section] enumerateObjectsUsingBlock:^(NSNumber *height, NSUInteger idx, BOOL *stop) {
        if (height.floatValue > tallestHeight) {
            index = idx;
            tallestHeight = height.floatValue;
        }
    }];
    return index;
}


第三步:接下來,就可以開始使用了

image.png

image.png

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末枕稀,一起剝皮案震驚了整個濱河市询刹,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌萎坷,老刑警劉巖凹联,帶你破解...
    沈念sama閱讀 212,686評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異哆档,居然都是意外死亡蔽挠,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,668評論 3 385
  • 文/潘曉璐 我一進(jìn)店門瓜浸,熙熙樓的掌柜王于貴愁眉苦臉地迎上來澳淑,“玉大人,你說我怎么就攤上這事插佛「苎玻” “怎么了?”我有些...
    開封第一講書人閱讀 158,160評論 0 348
  • 文/不壞的土叔 我叫張陵朗涩,是天一觀的道長忽孽。 經(jīng)常有香客問我,道長谢床,這世上最難降的妖魔是什么兄一? 我笑而不...
    開封第一講書人閱讀 56,736評論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮识腿,結(jié)果婚禮上出革,老公的妹妹穿的比我還像新娘。我一直安慰自己渡讼,他們只是感情好骂束,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,847評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著成箫,像睡著了一般展箱。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上蹬昌,一...
    開封第一講書人閱讀 50,043評論 1 291
  • 那天混驰,我揣著相機(jī)與錄音,去河邊找鬼。 笑死栖榨,一個胖子當(dāng)著我的面吹牛昆汹,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播婴栽,決...
    沈念sama閱讀 39,129評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼满粗,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了愚争?” 一聲冷哼從身側(cè)響起映皆,我...
    開封第一講書人閱讀 37,872評論 0 268
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎轰枝,沒想到半個月后劫扒,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,318評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡狸膏,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,645評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了添怔。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片湾戳。...
    茶點(diǎn)故事閱讀 38,777評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖广料,靈堂內(nèi)的尸體忽然破棺而出砾脑,到底是詐尸還是另有隱情,我是刑警寧澤艾杏,帶...
    沈念sama閱讀 34,470評論 4 333
  • 正文 年R本政府宣布韧衣,位于F島的核電站,受9級特大地震影響购桑,放射性物質(zhì)發(fā)生泄漏畅铭。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,126評論 3 317
  • 文/蒙蒙 一勃蜘、第九天 我趴在偏房一處隱蔽的房頂上張望硕噩。 院中可真熱鬧,春花似錦缭贡、人聲如沸炉擅。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,861評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽谍失。三九已至,卻和暖如春莹汤,著一層夾襖步出監(jiān)牢的瞬間快鱼,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,095評論 1 267
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留攒巍,地道東北人嗽仪。 一個月前我還...
    沈念sama閱讀 46,589評論 2 362
  • 正文 我出身青樓,卻偏偏與公主長得像柒莉,于是被迫代替她去往敵國和親闻坚。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,687評論 2 351

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