亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 系統 > iOS > 正文

IOS封裝自定義布局的方法

2020-07-26 03:29:46
字體:
來源:轉載
供稿:網友

一、概述
1、對于經常使用的控件或類,通常將其分裝為一個單獨的類來供外界使用,以此達到事半功倍的效果
2、由于分裝的類不依賴于其他的類,所以若要使用該類,可直接將該類拖進項目文件即可
3、在進行分裝的時候,通常需要用到代理設計模式
二、代理設計模式
1、代理設計模式的組成
客戶類(通常作為代理):通常委托這是角色來完成業務邏輯
真實角色:將客戶類的業務邏輯轉化為方法列表,即代理協議
代理協議:

  • 定義了需要實現的業務邏輯
  • 定義了一組方法列表,包括必須實現的方法或選擇實現的方法
  • 代理協議是代理對象所要遵循一組規則

代理角色

  • 若要作為代理,需要遵守代理協議,并且實現必須實現的代理方法
  • 代理角色可以通過調用代理協議中的方法完成業務邏輯,也可以附加自己的操作

文字描述通常是抽象的,一下通過圖示來闡述代理設計模式

三、自定義布局類的封裝
1、業務邏輯
如圖

2、布局每個cell的業務邏輯
由于設置每個cell的布局屬性的業務邏輯較復雜,特附上如下思維導圖

3、封裝思路封裝需要根據客戶類業務邏輯需求來提供接口
1)、通過代理協議的可選實現的方法獲取的屬性值的屬性,需要設置默認值
2)、未提供默認值的且必須使用的屬性,需要通過必須實現的方法來獲得
3)、自定義布局提供的接口可選

  • 列數
  • 列之間的間距
  • 行之間的間距
  • 內邊距

4)、自定義布局提供的接口必選
每個元素的高度,寬度可以通過列數和列間距計算得到
四、封裝步驟
設置代理協議,提供接口

//聲明LYPWaterFlowLayout為一個類@class LYPWaterFlowLayout;@protocol LYPWaterFlowLayoutDelegate <NSObject>//必須實現的方法@required/**獲取瀑布流每個元素的高度*/- (CGFloat)waterFlowLayout:(LYPWaterFlowLayout *)waterFlowLayout heightForItemAtIndex:(NSInteger)index itemWith:(CGFloat)itemWith;//可選實現的方法@optional/**獲取瀑布流的列數*/- (NSInteger)columnCountInWaterFlowLayout:(LYPWaterFlowLayout *)waterFlowLayout;/**獲取瀑布流列間距*/- (CGFloat)columnMarginInWaterFlowLayout:(LYPWaterFlowLayout *)waterFlowLayout;/**獲取瀑布流的行間距*/- (CGFloat)rowMarginInWaterFlowLayout:(LYPWaterFlowLayout *)waterFlowLayout;/**獲取瀑布流的內邊距*/- (UIEdgeInsets)edgeInsetsInWaterFlowLayout:(LYPWaterFlowLayout *)waterFlowLayout;@end

設置代理屬性

@interface LYPWaterFlowLayout : UICollectionViewLayout/**代理*/@property (nonatomic, weak) id<LYPWaterFlowLayoutDelegate> delegate;@end

設置通過可選代理方法獲取屬性值的屬性的默認值

/**默認的列數*/static const NSInteger LYPDefaultColumnCount = 3;/**默認每一列之間的間距*/static const CGFloat LYPDefaultColumMargin = 10;/**默認每一行之間的間距*/static const CGFloat LYPDefaultRowMargin = 10;/**默認邊緣間距*/static const UIEdgeInsets LYPDefaultEdgeInsets = {10, 10, 10, 10};

設置通過可選代理方法獲取屬性值的屬性的訪問方式若代理提供屬性值,則忽略默認值

- (NSInteger)columnCount{  //判斷代理是否實現了獲取列數的可選方法  if ([self.delegate respondsToSelector:@selector(columnCountInWaterFlowLayout:)])  {    //實現,返回通過代理設置的列數    return [self.delegate columnCountInWaterFlowLayout:self];  }  else  {    //為實現,返回默認的列數    return LYPDefaultColumnCount;  }}

注:其他屬性值的獲取與上述方法幾乎完全相同,不再贅述
設置布局
1)、設置需要的成員屬性

/**所有cell的布局屬性*/@property (nonatomic, strong) NSMutableArray *attrsArray;/**所有列的當前高度*/@property (nonatomic, strong) NSMutableArray *columnHeights;

2)、通過懶加載的方式初始化成員屬性

/**--attrsArray--懶加載*/- (NSMutableArray *)attrsArray{  if (_attrsArray == nil)  {    _attrsArray = [NSMutableArray array];  }  return _attrsArray;}/**--columnHeights--懶加載*/- (NSMutableArray *)columnHeights{  if (_columnHeights == nil)  {    _columnHeights = [NSMutableArray array];  }  return _columnHeights;}

3)、初始化布局

- (void)prepareLayout{  [super prepareLayout];  /**清除之前跟布局相關的所有屬性,重新設置新的布局*/  //清除之前計算的所有列的高度  [self.columnHeights removeAllObjects];  //設置所有列的初始高度  for (NSInteger i = 0; i<self.columnCount; i++)  {    self.columnHeights[i] = @(self.edgeInsets.top);  }  //清除之前所有的布局屬性  [self.attrsArray removeAllObjects];  /**開始創建每一個cell對應的布局屬性*/  NSInteger count = [self.collectionView numberOfItemsInSection:0];  for (NSInteger i = 0; i<count; i++)  {    NSIndexPath *indexPath = [NSIndexPath indexPathForItem:i inSection:0];    //獲取indexPath位置cell對應的布局屬性    UICollectionViewLayoutAttributes *attrs = [self layoutAttributesForItemAtIndexPath:indexPath];    //將indexPath位置的cell的布局屬性添加到所有cell的布局屬性數組中    [self.attrsArray addObject:attrs];  }}

4)、返回包含所有cell的布局屬性的數組

- (nullable NSArray<UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect{  return self.attrsArray;}設置每一個cell的布局屬性- (nullable UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(nonnull NSIndexPath *)indexPath{  //獲取indexPath位置的布局屬性  UICollectionViewLayoutAttributes *attrs = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath];  /**設置cell布局屬性的frame*/  /***確定cell的尺寸***/  //獲取collectionView的寬度  CGFloat collectionViewWidth = self.collectionView.frame.size.width;  //cell寬度  CGFloat width = ((collectionViewWidth - self.edgeInsets.left - self.edgeInsets.right - (self.columnCount - 1) * self.columMargin)) / self.columnCount;  //cell高度  CGFloat height = [self.delegate waterFlowLayout:self heightForItemAtIndex:indexPath.item itemWith:width];  /***設置cell的位置***/  NSInteger destColumn = 0;  CGFloat minColumnHeight = [self.columnHeights[0] doubleValue];  for (NSInteger i = 1; i<self.columnCount; i++)  {    CGFloat columnHeight = [self.columnHeights[i] doubleValue];    if (minColumnHeight > columnHeight)    {      minColumnHeight = columnHeight;      destColumn = i;    }  }  //計算cell的位置  CGFloat x = self.edgeInsets.left + destColumn * (width + self.columMargin);  CGFloat y = minColumnHeight;  //判斷是不是第一行  if (y != self.edgeInsets.top)  {    //若不是第一行,需要加上行間距    y += self.rowMargin;  }  /**給cell的布局屬性的frame賦值*/  attrs.frame = CGRectMake(x, y, width, height);  //更新最短那列的高度  self.columnHeights[destColumn] = @(CGRectGetMaxY(attrs.frame));  /**返回indexPath位置的cell的布局屬性*/  return attrs;}

5)、設置collectionView內容的尺寸

- (CGSize)collectionViewContentSize{  //獲取最高的那一列的高度  CGFloat maxColumnHeight = [self.columnHeights[0] doubleValue];  for (NSInteger i = 1; i<self.columnCount; i++)  {    CGFloat columnHeight = [self.columnHeights[i] doubleValue];    if (maxColumnHeight < columnHeight)    {      maxColumnHeight = columnHeight;    }  }  //返回collectionView的contentSize,高度為最高的高度加上一個行間距  return CGSizeMake(0, maxColumnHeight + self.rowMargin);}

以上就是本文的全部內容,希望對大家的學習有所幫助。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
日韩免费在线免费观看| 国产亚洲人成网站在线观看| 国产a级全部精品| 国产精品极品美女粉嫩高清在线| 久久av.com| 国产精品福利在线观看网址| 日韩精品在线免费观看视频| 日韩在线中文字| 亚洲国产女人aaa毛片在线| 91国偷自产一区二区三区的观看方式| 日本三级韩国三级久久| www.久久撸.com| 久久久电影免费观看完整版| 国产精品美女午夜av| 日韩大陆欧美高清视频区| 91干在线观看| 日韩欧美国产一区二区| 日韩av中文字幕在线播放| 亚洲天堂第二页| 亚洲的天堂在线中文字幕| 日韩精品久久久久久久玫瑰园| 国产深夜精品福利| 精品久久久久久中文字幕大豆网| 国产精品日韩欧美| 性欧美xxxx交| 欧美一级电影免费在线观看| 久久男人的天堂| 亚洲欧美日韩天堂一区二区| 精品国产91乱高清在线观看| 国产综合在线观看视频| 日韩中文综合网| 欧美激情videos| 精品在线小视频| 狠狠躁夜夜躁人人爽超碰91| 欧美日韩精品在线视频| 亚洲国产日韩欧美综合久久| 91香蕉嫩草神马影院在线观看| 97视频人免费观看| 欧美中文在线观看国产| 国产精品永久免费| 精品视频9999| 午夜精品久久久久久久久久久久久| 亚洲在线第一页| 国产日韩中文字幕在线| 国产婷婷成人久久av免费高清| 欧美成人免费全部| 日韩欧美中文第一页| 欧美亚洲一级片| 97香蕉超级碰碰久久免费软件| 亚洲色图美腿丝袜| 亚洲成人久久电影| 精品亚洲男同gayvideo网站| 国外成人在线视频| 在线视频亚洲欧美| 国产精品第1页| 福利二区91精品bt7086| 成人淫片在线看| 亚洲在线免费观看| 日韩禁在线播放| 久久免费精品日本久久中文字幕| 成人免费自拍视频| 日韩av有码在线| 国产亚洲精品va在线观看| 色99之美女主播在线视频| 国产精品成人免费电影| 日本高清视频一区| 最新国产精品拍自在线播放| www.色综合| 久久69精品久久久久久久电影好| 欧美国产日产韩国视频| 性金发美女69hd大尺寸| 亚洲精品wwwww| 一本色道久久88综合亚洲精品ⅰ| 久久精品夜夜夜夜夜久久| 91在线网站视频| 欧美成人精品三级在线观看| 国产精品夫妻激情| 国产91精品黑色丝袜高跟鞋| 91久热免费在线视频| 亚洲free性xxxx护士hd| 欧美性高潮在线| 亚洲精品国偷自产在线99热| 国产精品69av| 亚洲美女激情视频| 日韩电影中文 亚洲精品乱码| xxav国产精品美女主播| 亚洲精品丝袜日韩| 亚洲激情第一页| 97视频在线观看亚洲| 久久久免费精品视频| 欧美性极品少妇精品网站| 97精品国产97久久久久久春色| 亚洲欧洲日产国码av系列天堂| 亚洲xxxx3d| 国产成人综合精品| 亚洲tv在线观看| 久久久噜噜噜久久| 国产精品视频自拍| 中文字幕精品久久久久| 日韩av网站电影| 日韩美女av在线免费观看| 亚洲欧美日韩中文视频| 日韩成人在线视频| 亚洲欧美日韩中文在线制服| 欧美激情区在线播放| 日本乱人伦a精品| 国产精品 欧美在线| 国产精品91一区| 久久久之久亚州精品露出| 欧美性理论片在线观看片免费| 欧美电影免费观看大全| 久久久久久久色| 日韩在线视频播放| 欧美另类高清videos| 日韩精品视频在线观看网址| 九九热最新视频//这里只有精品| 国产精品美女久久久免费| 欧美亚洲国产日本| 蜜月aⅴ免费一区二区三区| 日韩视频在线免费| 国产精品高潮在线| 国产精品免费久久久| 欧美亚洲成人xxx| 国产精品久久久久久久久久东京| 日日噜噜噜夜夜爽亚洲精品| 欧美另类极品videosbest最新版本| 亚洲va欧美va国产综合剧情| 亚洲高清免费观看高清完整版| 懂色aⅴ精品一区二区三区蜜月| 日韩av网站在线| 日韩成人黄色av| 久久视频免费在线播放| 97av在线视频免费播放| 影音先锋欧美在线资源| 亚洲精品永久免费精品| 成人亲热视频网站| 欧美视频在线看| 亚洲国语精品自产拍在线观看| 成人免费福利在线| 午夜精品三级视频福利| 国产一区二区三区视频在线观看| 国产精品va在线播放我和闺蜜| 日本国产欧美一区二区三区| 色偷偷888欧美精品久久久| 国产欧美日韩精品在线观看| 性色av香蕉一区二区| 热草久综合在线| 欧美日韩在线影院| 久久久久久久国产精品视频| 精品一区二区亚洲| 欧美国产精品人人做人人爱| 亚洲a级在线观看| 久久久久久av| 热久久这里只有精品| 日韩美女视频免费在线观看| 国产成人精品一区二区在线| 亚洲国产精品大全| 国产成人精品久久二区二区| 欧美一级视频在线观看| 欧美亚洲成人免费| 91色视频在线观看| 欧美在线观看网址综合| 午夜精品福利视频| 深夜成人在线观看|