如何在UITableView中创建仿Android NavigationDrawer的单行分隔符
嘿,我完全get到你的需求了——就是想在UITableView做的菜单里,加一条简单的单行分隔线,把两组菜单选项分开,就像Android NavigationDrawer里的那种效果,对吧?其实iOS里完全支持这个,而且实现起来一点不复杂,不用去看那些复杂的展开式菜单教程,下面给你两种最常用的实现方式:
首先得说,iOS里这种分隔线没有一个统一的专属称谓,一般就叫「table view 分隔行」或者直接说「分组分隔线」就行,你搜这个关键词也能找到相关的实现示例。
方法一:用Section拆分数据源(更规范的做法)
如果你的菜单本来就可以分成两组,最规范的方式是把数据源拆成两个Section,然后在Section之间加一条分隔线:
拆分你的字符串数组:
比如原来的数组是["首页", "我的收藏", "设置", "关于我们", "隐私政策"],把它拆成两组:let group1 = ["首页", "我的收藏", "设置"] let group2 = ["关于我们", "隐私政策"] let menuSections = [group1, group2]实现UITableView的数据源方法:
告诉tableView有两个Section,每个Section对应一组数据:func numberOfSections(in tableView: UITableView) -> Int { return menuSections.count } func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return menuSections[section].count } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "MenuCell", for: indexPath) cell.textLabel?.text = menuSections[indexPath.section][indexPath.row] return cell }添加Section之间的分隔线:
我们可以把第二个Section的Header做成一条1pt高的分隔线:func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? { // 只在第二组的顶部加分隔线 guard section == 1 else { return nil } let separatorView = UIView() separatorView.backgroundColor = UIColor.lightGray // 设置分隔线高度为1pt(注意iOS里的pt和像素的区别) separatorView.heightAnchor.constraint(equalToConstant: 1).isActive = true return separatorView } func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat { return section == 1 ? 1 : 0 }
这样两组菜单之间就会出现一条干净的分隔线,和Android的效果完全一致。
方法二:插入专门的分隔行(适合不想用Section的情况)
如果不想拆分Section,也可以直接在数据源里插入一个「分隔标记」,然后在创建cell的时候判断,返回一个专门的分隔行:
定义带分隔标记的数据源:
用枚举来区分正常菜单和分隔线,避免用特殊字符串容易出错:enum MenuItem { case normal(String) case separator } let menuItems: [MenuItem] = [ .normal("首页"), .normal("我的收藏"), .normal("设置"), .separator, // 这里插入分隔标记 .normal("关于我们"), .normal("隐私政策") ]实现数据源方法:
根据类型返回不同的cell,分隔行设置成高度1pt,并且禁止点击:func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return menuItems.count } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let item = menuItems[indexPath.row] switch item { case .normal(let title): let cell = tableView.dequeueReusableCell(withIdentifier: "MenuCell", for: indexPath) cell.textLabel?.text = title return cell case .separator: let cell = tableView.dequeueReusableCell(withIdentifier: "SeparatorCell", for: indexPath) // 创建分隔线视图 let separatorView = UIView(frame: CGRect(x: 0, y: 0, width: tableView.bounds.width, height: 1)) separatorView.backgroundColor = .lightGray cell.contentView.addSubview(separatorView) // 禁止分隔行被点击 cell.selectionStyle = .none return cell } } // 设置分隔行的高度 func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { switch menuItems[indexPath.row] { case .separator: return 1 default: return 44 // 正常菜单行的高度,你可以改成自己需要的数值 } }
两种方法都能实现你要的效果,看你更习惯哪种写法就行。其实这种需求在iOS里很常见,不用找那些复杂的菜单框架,自己几行代码就能搞定~
内容的提问来源于stack exchange,提问作者AND4011002849

