最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

iOS基于UITableView實(shí)現(xiàn)多層展開(kāi)與收起

 更新時(shí)間:2017年03月01日 11:27:35   作者:34碼的小孩子  
這篇文章主要為大家詳細(xì)介紹了iOS基于UITableView實(shí)現(xiàn)多層展開(kāi)與收起的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下

本文實(shí)例為大家分享了bleView多層展開(kāi)與收起的具體代碼,供大家參考,具體內(nèi)容如下

規(guī)則要求:

  • tableview 有多層,類似于xcode文件目錄的層級(jí)關(guān)系,每一個(gè)最開(kāi)始展示的層姑且稱之為根目錄吧,并且,每個(gè)根目錄下的層數(shù)不定。
  • 與文件目錄類似,每個(gè)目錄下可以有不同層級(jí)的目錄同時(shí)展開(kāi),但是同一層次中只有一層是展開(kāi)的,即要展開(kāi)B層次的某一層,則需要收起B(yǎng)層次所有其他的層級(jí)。
  • 最底層是一個(gè)個(gè)文件,不能再展開(kāi)(這里在業(yè)務(wù)邏輯上用處是:跳轉(zhuǎn)到不同的頁(yè)面)。

想法:

  • 整個(gè)界面是一個(gè)tableview,層級(jí)關(guān)系用cell中的label的位置展現(xiàn),而tableview的數(shù)據(jù)源是一個(gè)一維數(shù)組_resultArray,其中,展開(kāi)是在特定位置插入數(shù)據(jù),收起是在特定位置刪除數(shù)據(jù)。
  • 每一層目錄存儲(chǔ)著下一層的引用,就是包含了下一層的全部數(shù)據(jù)。展開(kāi)該層的時(shí)候就是將下一層的數(shù)據(jù)加入_resultArray,收起該層時(shí),是將該層的所有下層的數(shù)據(jù)從_resultArray中刪除。

數(shù)據(jù)存儲(chǔ)

//每個(gè)目錄的數(shù)據(jù)結(jié)構(gòu)如下:
@interface OpenTest : NSObject
@property (copy, nonatomic) NSString *title;  //非首層展示的標(biāo)題
@property (assign, nonatomic) NSInteger level; //決定偏移量大小
@property (copy, nonatomic) NSString *openUrl; //最后一層跳轉(zhuǎn)的規(guī)則
@property (copy, nonatomic) NSMutableArray *detailArray; //下一層的數(shù)據(jù)
@property (assign, nonatomic) BOOL isOpen;    //是否要展開(kāi)
@property (copy, nonatomic) NSString *imageName; //首層的圖片
@end 

其中,因?yàn)閐etailArray中存儲(chǔ)的對(duì)象也應(yīng)該是OpenTest, 所以需要在OpenTest.m中借助MJExtension (在github上下載并加入到項(xiàng)目中)進(jìn)行顯式轉(zhuǎn)化。

#import "OpenTest.h"
@implementation OpenTest
- (instancetype)init {
  self = [super init];
  if (self) {
    [OpenTest mj_setupObjectClassInArray:^NSDictionary *{
      return @{
           @"detailArray" : [OpenTest class]
           };
    }];
  }
  return self;
}
@end

數(shù)據(jù)處理

開(kāi)始建造源數(shù)據(jù)dataArray,該數(shù)組可明確層級(jí)關(guān)系,并且得到展示數(shù)組_resultArray。建造過(guò)程如下:

- (void)initData {
_dataArray = [NSMutableArray new];
_resultArray = [NSMutableArray new];

NSMutableArray *secondArray1 = [NSMutableArray new];
NSMutableArray *threeArray1 = [NSMutableArray new];
NSMutableArray *fourArray1 = [NSMutableArray new];

NSArray *FirstTitleArray = @[@"FirstTitle1", @"FirstTitle2", @"FirstTitle3", @"FirstTitle4", @"FirstTitle5", @"FirstTitle6", @"FirstTitle7", @"FirstTitle8", @"FirstTitle9", @"FirstTitle10"];
NSArray *SecondTitleArray = @[@"SecondTitle1", @"SecondTitle2", @"SecondTitle3"];
NSArray *ThreeTitleArray = @[@"ThreeTitle1", @"ThreeTitle2", @"ThreeTitle3", @"ThreeTitle4"];
NSArray *FourTitleArray = @[@"FourTitle1", @"FourTitle2", @"FourTitle3"];
NSArray *imageArray = @[@"scroller1", @"scroller2", @"scroller3", @"scroller4", @"scroller5", @"scroller6", @"scroller7", @"scroller8", @"scroller9", @"scroller10"];

//第四層數(shù)據(jù)
for (int i = 0; i < FourTitleArray.count; i++) {
  OpenTest *model = [[OpenTest alloc] init];
  model.title = FourTitleArray[i];
  model.level = 3;
  model.isOpen = NO;

  [fourArray1 addObject:model];
}

//第三層數(shù)據(jù)
for (int i = 0; i < ThreeTitleArray.count; i++) {
  OpenTest *model = [[OpenTest alloc] init];
  model.title = ThreeTitleArray[i];
  model.level = 2;
  model.isOpen = NO;
  model.detailArray = fourArray1;

  [threeArray1 addObject:model];
}

//第二層數(shù)據(jù)
for (int i = 0; i < SecondTitleArray.count; i++) {
  OpenTest *model = [[OpenTest alloc] init];
  model.title = SecondTitleArray[i];
  model.level = 1;
  model.isOpen = NO;
  model.detailArray = [threeArray1 mutableCopy];

  [secondArray1 addObject:model];
}

//第一層數(shù)據(jù)
for (int i = 0; i < FirstTitleArray.count; i++) {
  OpenTest *model = [[OpenTest alloc] init];
  model.title = FirstTitleArray[i];
  model.level = 0;
  model.isOpen = NO;
  model.detailArray = [secondArray1 mutableCopy];
  model.imageName = imageArray[i];

  [_dataArray addObject:model];
}

//處理源數(shù)據(jù),獲得展示數(shù)組_resultArray
[self dealWithDataArray:_dataArray];
}

/**
 將源數(shù)據(jù)數(shù)組處理成要展示的一維數(shù)組,最開(kāi)始是展示首層的所有的數(shù)據(jù)
 @param dataArray 源數(shù)據(jù)數(shù)組
 */
- (void)dealWithDataArray:(NSMutableArray *)dataArray {
for (OpenTest *model in dataArray) {
  [_resultArray addObject:model];

  if (model.isOpen && model.detailArray.count > 0) {
    [self dealWithDataArray:model.detailArray];
  }
}
}

當(dāng)首層沒(méi)有展開(kāi)數(shù)據(jù)時(shí),點(diǎn)擊首層展開(kāi)第二層數(shù)據(jù),比較容易實(shí)現(xiàn),即在_resultArray添加下一層數(shù)據(jù)。添加數(shù)據(jù)方法如下:

/**
 在指定位置插入要展示的數(shù)據(jù)
 @param dataArray 數(shù)據(jù)數(shù)組
 @param row    需要插入的數(shù)組下標(biāo)
 */
- (void)addObjectWithDataArray:(NSMutableArray *)dataArray row:(NSInteger)row {
for (int i = 0; i < dataArray.count; i++) {
  OpenTest *model = dataArray[i];
  model.isOpen = NO;
  [_resultArray insertObject:model atIndex:row];
  row += 1;
}
}

收起方法實(shí)現(xiàn)如下:

/**
 刪除要收起的數(shù)據(jù)
 @param dataArray 數(shù)據(jù)
 @param count   統(tǒng)計(jì)刪除數(shù)據(jù)的個(gè)數(shù)
 @return 刪除數(shù)據(jù)的個(gè)數(shù)
 */
- (CGFloat)deleteObjectWithDataArray:(NSMutableArray *)dataArray count:(NSInteger)count {
for (OpenTest *model in dataArray) {
  count += 1;

  if (model.isOpen && model.detailArray.count > 0) {
    count = [self deleteObjectWithDataArray:model.detailArray count:count];
  }

  model.isOpen = NO;

  [_resultArray removeObject:model];
}

return count;
}

在已經(jīng)展開(kāi)的時(shí)候點(diǎn)擊另外一個(gè)目錄,要先收起再展開(kāi)。因?yàn)槊總€(gè)層次只有一個(gè)目錄是展開(kāi)的,所以收起的時(shí)候,只需要跟同層次的目錄數(shù)據(jù)比較,如果是已經(jīng)打開(kāi)的,則刪除打開(kāi)目錄的所有子層。方法如下:

/**
 與點(diǎn)擊同一層的數(shù)據(jù)比較,然后刪除要收起的數(shù)據(jù)和插入要展開(kāi)的數(shù)據(jù)
 @param model 點(diǎn)擊的cell對(duì)應(yīng)的model
 @param row  點(diǎn)擊的在tableview的indexPath.row,也對(duì)應(yīng)_resultArray的下標(biāo)
 */
- (void)compareSameLevelWithModel:(OpenTest *)model row:(NSInteger)row {
NSInteger count = 0;
NSInteger index = 0;  //需要收起的起始位置
//如果直接用_resultArray,在for循環(huán)為完成之前,_resultArray會(huì)發(fā)生改變,使程序崩潰。
NSMutableArray *copyArray = [_resultArray mutableCopy];

for (int i = 0; i < copyArray.count; i++) {
  OpenTest *openModel = copyArray[i];
  if (openModel.level == model.level) {
    //同一個(gè)層次的比較
    if (openModel.isOpen) {
      //刪除openModel所有的下一層
      count = [self deleteObjectWithDataArray:openModel.detailArray count:count];
      index = i;
      openModel.isOpen = NO;
      break;
    }
  }
}

//插入的位置在刪除的位置的后面,則需要減去刪除的數(shù)量。
if (row > index && row > count) {
  row -= count;
}

[self addObjectWithDataArray:model.detailArray row:row + 1];
}

界面

系統(tǒng)的tableviewcell 無(wú)法修改textLabel的位置,需要修改偏移量有兩種方法。
1、繼承UITableViewCell, 然后重寫父類的方法 - layoutSubviews, 在該方法中修改textLabel的frame。
2、在cell.contentView 中添加一個(gè)label。

我這里使用的是第二種方法:

UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell"];

  if (cell == nil) {
    cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"Cell"];
    cell.selectionStyle = UITableViewCellSelectionStyleNone;

    UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(15, 0, UI_SCREEN_WIDTH / 2, 32)];
    label.font = [UIFont systemFontOfSize:14];
    label.tag = LabelTag;

    [cell.contentView addSubview:label];
  }

  for (UIView *view in cell.contentView.subviews) {
    if (view.tag == LabelTag) {
      ((UILabel *)view).text = model.title;
      ((UILabel *)view).frame = CGRectMake(15 + (model.level - 1) * SpaceWidth , 0, UI_SCREEN_WIDTH / 2, 32);
    }
  }

最后在didSelectRowAtIndexPath方法中實(shí)現(xiàn)點(diǎn)擊展開(kāi)與收起,方法如下:

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSInteger row = indexPath.row;
OpenTest *model = _resultArray[row];

if (model.isOpen) {
  //原來(lái)是展開(kāi)的,現(xiàn)在要收起,則刪除model.detailArray存儲(chǔ)的數(shù)據(jù)
  [self deleteObjectWithDataArray:model.detailArray count:0];
}
else {
  if (model.detailArray.count > 0) {
    //原來(lái)是收起的,現(xiàn)在要展開(kāi),則需要將同層次展開(kāi)的收起,然后再展開(kāi)
    [self compareSameLevelWithModel:model row:row];
  }
  else {
    //點(diǎn)擊的是最后一層數(shù)據(jù),跳轉(zhuǎn)到別的界面
    NSLog(@"最后一層");
  }
}

model.isOpen = !model.isOpen;

//滑動(dòng)到屏幕頂部
for (int i = 0; i < _resultArray.count; i++) {
  OpenTest *openModel = _resultArray[i];

  if (openModel.isOpen && openModel.level == 0) {
    //將點(diǎn)擊的cell滑動(dòng)到屏幕頂部
    NSIndexPath *selectedPath = [NSIndexPath indexPathForRow:i inSection:0];
    [tableView scrollToRowAtIndexPath:selectedPath atScrollPosition:UITableViewScrollPositionTop animated:YES];
  }
}

[tableView reloadData];
}


效果

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • iOS自定義UITabBar中間按鈕

    iOS自定義UITabBar中間按鈕

    這篇文章主要為大家詳細(xì)介紹了iOS自定義UITabBar中間按鈕,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-05-05
  • iOS用兩行代碼完美解決數(shù)據(jù)持久化

    iOS用兩行代碼完美解決數(shù)據(jù)持久化

    所謂的持久化,就是將數(shù)據(jù)保存到硬盤中,使得在應(yīng)用程序或機(jī)器重啟后可以繼續(xù)訪問(wèn)之前保存的數(shù)據(jù)。在iOS開(kāi)發(fā)中,有很多數(shù)據(jù)持久化的方案,接下來(lái)我將嘗試著介紹一種巧妙的方法,用兩行代碼解決這個(gè)問(wèn)題,一起來(lái)學(xué)習(xí)下。
    2016-08-08
  • ios 11和iphone x的相關(guān)適配問(wèn)題及解決方法

    ios 11和iphone x的相關(guān)適配問(wèn)題及解決方法

    這篇文章主要介紹了ios 11和iphone x的相關(guān)適配,文中給大家提到了在ios 11中,tableView會(huì)莫名偏移問(wèn)題的解決方法,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下
    2017-11-11
  • iOS 對(duì)view進(jìn)行截圖的示例代碼

    iOS 對(duì)view進(jìn)行截圖的示例代碼

    本篇文章主要介紹了iOS 對(duì)view進(jìn)行截圖的示例代碼,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2018-07-07
  • iOS基礎(chǔ)知識(shí)之@property 和 Ivar 的區(qū)別

    iOS基礎(chǔ)知識(shí)之@property 和 Ivar 的區(qū)別

    這篇文章主要介紹了iOS基礎(chǔ)知識(shí)之@property 和 Ivar 的區(qū)別介紹,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下
    2016-08-08
  • 詳解2016 cocoapods的安裝和使用以及版本升級(jí)遇到的問(wèn)題

    詳解2016 cocoapods的安裝和使用以及版本升級(jí)遇到的問(wèn)題

    CocoaPods是一個(gè)負(fù)責(zé)管理iOS項(xiàng)目中第三方開(kāi)源庫(kù)的工具。這篇文章主要介紹了2016 cocoapods的安裝和使用以及版本升級(jí)遇到的問(wèn)題,有需要的可以了解一下。
    2016-12-12
  • IOS中MMDrawerController第三方抽屜效果的基本使用示例

    IOS中MMDrawerController第三方抽屜效果的基本使用示例

    這篇文章主要介紹了IOS中MMDrawerController第三方抽屜效果的基本使用示例,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下。
    2017-02-02
  • iOS時(shí)鐘開(kāi)發(fā)案例分享

    iOS時(shí)鐘開(kāi)發(fā)案例分享

    這篇文章主要為大家分享了iOS時(shí)鐘開(kāi)發(fā)案例,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2016-04-04
  • iOS Gif圖片展示N種方式(原生+第三方)

    iOS Gif圖片展示N種方式(原生+第三方)

    這篇文章主要介紹了iOS Gif圖片展示N種方式,包括原生、第三方方式展示,感興趣的小伙伴們可以參考一下
    2016-03-03
  • iOS 獲取公歷、農(nóng)歷日期的年月日的實(shí)例代碼

    iOS 獲取公歷、農(nóng)歷日期的年月日的實(shí)例代碼

    本篇文章主要介紹了iOS 獲取公歷、農(nóng)歷日期的年月日的實(shí)例代碼,主要介紹了三種方法,具有一定的參考價(jià)值,有興趣的可以了解一下。
    2017-02-02

最新評(píng)論

如皋市| 徐汇区| 郑州市| 新野县| 色达县| 报价| 陈巴尔虎旗| 时尚| 沙河市| 建宁县| 利川市| 宜川县| 唐河县| 肇源县| 怀柔区| 贡觉县| 樟树市| 扎赉特旗| 高邮市| 通道| 宜宾县| 溧阳市| 麻江县| 讷河市| 千阳县| 密山市| 黄浦区| 牡丹江市| 思南县| 上虞市| 方正县| 孟连| 招远市| 特克斯县| 常州市| 西盟| 托克逊县| 甘泉县| 开江县| 甘肃省| 尚义县|