Создайте структуру Menu
с заголовком и массивом Menu
объектов.
struct Menu {
var title: String
var subMenus: [Menu]?
}
Вместо использования табличного представленияUIScrollView
и добавление вложенных UIStackView
// ViewController.swift
class ViewController: UIViewController {
var menus:[Menu] = []
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .white
let red1 = Menu(title: "SubCategory Red", subMenus: [Menu(title: "SubSubCategory X", subMenus: [Menu(title: "SubSubSubCategory", subMenus: nil)]),
Menu(title: "SubSubCategory Y", subMenus: nil)])
let blue1 = Menu(title: "SubCategory Blue", subMenus: nil)
let red2 = Menu(title: "SubCategory Red", subMenus: [Menu(title: "SubSubCategory X", subMenus: nil),
Menu(title: "SubSubCategory Y", subMenus: nil)])
let blue2 = Menu(title: "SubCategory Blue", subMenus: [Menu(title: "SubSubCategory X", subMenus: nil)])
let green2 = Menu(title: "SubCategory Green", subMenus: nil)
menus = [Menu(title: "MainCategory A", subMenus: [red1, blue1]), Menu(title: "MainCategory B", subMenus: [red2, blue2, green2])]
let scrollView = UIScrollView()
scrollView.backgroundColor = .white
scrollView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(scrollView)
let outerStackView = UIStackView()
outerStackView.axis = .vertical
outerStackView.alignment = .fill
outerStackView.distribution = .fillProportionally
outerStackView.translatesAutoresizingMaskIntoConstraints = false
scrollView.addSubview(outerStackView)
scrollView.topAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.topAnchor).isActive = true view.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:[scrollView]|", options: [], metrics: nil, views: ["scrollView": scrollView]))
view.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|[scrollView]|", options: [], metrics: nil, views: ["scrollView": scrollView]))
scrollView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|[outerStackView]|", options: [], metrics: nil, views: ["outerStackView": outerStackView]))
scrollView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|[outerStackView]|", options: [], metrics: nil, views: ["outerStackView": outerStackView]))
scrollView.widthAnchor.constraint(equalTo: outerStackView.widthAnchor).isActive = true
let height = scrollView.heightAnchor.constraint(equalTo: outerStackView.heightAnchor)
height.priority = .defaultLow
height.isActive = true
menus.forEach {
outerStackView.addArrangedSubview(MenuStackView(menu: $0, padding: 20))
}
}
}
// MenuStackView.swift
class MenuStackView: UIStackView {
convenience init(menu: Menu, padding: CGFloat) {
self.init()
axis = .vertical
alignment = .fill
distribution = .fillProportionally
let btn = UIButton(type: .custom)
btn.contentHorizontalAlignment = .left
btn.titleEdgeInsets = UIEdgeInsets(top: 0, left: padding, bottom: 0, right: 0)
btn.addTarget(self, action: #selector(toggle(_:)), for: .touchUpInside)
btn.setTitleColor(.black, for: .normal)
btn.setTitle(menu.title, for: .normal)
btn.translatesAutoresizingMaskIntoConstraints = false
btn.heightAnchor.constraint(equalToConstant: 40).isActive = true
addArrangedSubview(btn)
menu.subMenus?.forEach {
let stackView = MenuStackView(menu: $0, padding: padding+20)
stackView.isHidden = true
self.addArrangedSubview(stackView)
}
}
@objc func toggle(_ sender: UIButton) {
self.arrangedSubviews.forEach {
if $0 is MenuStackView {
$0.isHidden = !$0.isHidden
}
}
}
}