iOS开发使用UITableView制作N级下拉菜单的示例

2020-01-21 04:20:41王振洲

在一开始, 先清空 latestShowMenuItems 中的数据, 然后添加第一层数据

在添加第一层数据的时候, 对每一个数据进行判断, 判断是否能展开, 并且是否已经展开

如果展开, 添加子类到数组, 这里用递归层层递进, 最后将每一层子类展开的数据全部添加到 latestShowMenuItems 中, 同时设置了每一层数据的层级属性 index

此时 - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath 方法, 需要做如下修改


- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
  // 取出点击的选项
  LTMenuItem *menuItem = self.latestShowMenuItems[indexPath.row];
  // 判断是否能够展开, 不能展开立即返回, 不错任何处理
  if (!menuItem.isCanUnfold) return;
  // 设置展开闭合
  menuItem.isUnfold = !menuItem.isUnfold;
  // 修改latestShowMenuItems中数据
  [self setupRowCount];
  // 刷新列表
  [self.tableView reloadData];
}

这时, 我们已经可以看到界面上有如下效果

 

 
iOS,N级下拉菜单,下拉菜单,制作下拉菜单,UITableView 

 

第七步, 添加展开闭合的伸缩动画效果

首先添加一个属性 oldShowMenuItems , 用来记录改变前 latestShowMenuItems 中的数据


@interface LTMenuItemViewController ()
/** 菜单项 */
@property (nonatomic, strong) NSMutableArray<LTMenuItem *> *menuItems;
/** 当前需要展示的数据 */
@property (nonatomic, strong) NSMutableArray<LTMenuItem *> *latestShowMenuItems;
/** 以前需要展示的数据 */
@property (nonatomic, strong) NSMutableArray<LTMenuItem *> *oldShowMenuItems;
@end

修改 - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath 方法, 添加展开动画效果


- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
  LTMenuItem *menuItem = self.latestShowMenuItems[indexPath.row];
  if (!menuItem.isCanUnfold) return;
  
  // 记录改变之前的数据
  self.oldShowMenuItems = [NSMutableArray arrayWithArray:self.latestShowMenuItems];
  
  // 设置展开闭合
  menuItem.isUnfold = !menuItem.isUnfold;
  // 更新被点击cell的箭头指向
  [self.tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:(UITableViewRowAnimationAutomatic)];
  
  // 设置需要展开的新数据
  [self setupRowCount];
  
  // 判断老数据和新数据的数量, 来进行展开和闭合动画
  // 定义一个数组, 用于存放需要展开闭合的indexPath
  NSMutableArray<NSIndexPath *> *indexPaths = @[].mutableCopy;
  
  // 如果 老数据 比 新数据 多, 那么就需要进行闭合操作
  if (self.oldShowMenuItems.count > self.latestShowMenuItems.count) {
    // 遍历oldShowMenuItems, 找出多余的老数据对应的indexPath
    for (int i = 0; i < self.oldShowMenuItems.count; i++) {
      // 当新数据中 没有对应的item时
      if (![self.latestShowMenuItems containsObject:self.oldShowMenuItems[i]]) {
        NSIndexPath *subIndexPath = [NSIndexPath indexPathForRow:i inSection:indexPath.section];
        [indexPaths addObject:subIndexPath];
      }
    }
    // 移除找到的多余indexPath
    [self.tableView deleteRowsAtIndexPaths:indexPaths withRowAnimation:(UITableViewRowAnimationTop)];
  }else {
    // 此时 新数据 比 老数据 多, 进行展开操作
    // 遍历 latestShowMenuItems, 找出 oldShowMenuItems 中没有的选项, 就是需要新增的indexPath
    for (int i = 0; i < self.latestShowMenuItems.count; i++) {
      if (![self.oldShowMenuItems containsObject:self.latestShowMenuItems[i]]) {
        NSIndexPath *subIndexPath = [NSIndexPath indexPathForRow:i inSection:indexPath.section];
        [indexPaths addObject:subIndexPath];
      }
    }
    // 插入找到新添加的indexPath
    [self.tableView insertRowsAtIndexPaths:indexPaths withRowAnimation:(UITableViewRowAnimationTop)];
  }
}