ios - 如何在 iOS 中实现以下布局?

标签 ios swift xcode uiscrollview tabmenu

我有一个用于 iOS 应用程序开发的布局如下。 Mock up

布局包含以下部分:

  1. 折叠工具栏:此 View 应该像在 android 中一样工作,即 滚动它必须折叠。
  2. 标签菜单:这是标签菜单。滑动时,tableview 必须根据所选菜单进行更新。在 scrolling 选项卡菜单必须固定在顶部。
  3. Tableview:这只是一个tableview,包含选项卡菜单中所选菜单的数据。
  4. 底部标签:这是UITabbarMenu

我尝试了以下方法:

enter image description here

我用了Pagingkit选项卡菜单库。我将 vProductList(tabbartableview 的父 View )的高度创建为设备屏幕的高度。

当 tableview 在 scrollview 中时出现问题。问题是 tableviewscrollview 在滚动时的行为不同。因此,要删除它,我首先禁用 tableview 的滚动,并在选项卡菜单 View 位于屏幕的 (0,0) 点的条件下在 viewDidScroll 方法中启用。但是,必须滚动两次才能获得效果。这感觉有点问题。如何使用这种方法实现平滑滚动?有没有可以解决这个问题的库?

最佳答案

这就是解决这个问题的方法。

查看层次结构:

enter image description here

您可以使用 UICollectionView 来创建 TabbarUITableView 用于在选项卡选择时处理数据。 要同时处理 UICollectionViewUITableView 中的数据,请创建一个 ViewModel。这是您可以如何做到的示例,

enum ListType: Int {
    case fruits, animals, vegetables
}

class ViewModel {
    let tabs: [ListType] = [.fruits, .animals, .vegetables]

    let fruits = ["Apple", "Banana", "Grapes", "Papaya", "Apple", "Banana", "Grapes", "Papaya", "Apple", "Banana", "Grapes", "Papaya"]
    let animals = ["Rabbit", "Monkey", "Bear", "Deer", "Rabbit", "Monkey", "Bear", "Deer", "Rabbit", "Monkey", "Bear", "Deer"]
    let vegetables = ["Carrot", "Potato", "Cucumber", "Spinach", "Carrot", "Potato", "Cucumber", "Spinach", "Carrot", "Potato", "Cucumber", "Spinach"]

    func numberOfTabs() -> Int {
        return self.tabs.count
    }

    func tab(at index: Int) -> ListType {
        return self.tabs[index]
    }

    func numberOfRows(for listType: ListType) -> Int {
        switch listType {
        case .fruits: return fruits.count
        case .animals: return animals.count
        case .vegetables: return vegetables.count
        }
    }

    func element(at index: Int, for listType: ListType) -> String? {
        switch listType {
        case .fruits: return fruits[index]
        case .animals: return animals[index]
        case .vegetables: return vegetables[index]
        }
    }
}

在上面的代码中,我创建了

  1. 一个 enum ListType,它标识 collectionView 中的 tab 类型 以及要在 tableView< 中显示的数据
  2. 一个 class ViewModel,它处理 collectionViewtableViewdataSource

让我们创建一个带有一些outletsUIViewController,即

class ViewController: UIViewController {
    @IBOutlet weak var tableView: UITableView!
    @IBOutlet weak var collectionView: UICollectionView!
    @IBOutlet weak var collapsingViewHeightConstraint: NSLayoutConstraint!

    private let viewModel = ViewModel()
    private var lastContentOffset: CGFloat = 0.0

    override func viewDidLoad() {
        super.viewDidLoad()
        self.collectionView.selectItem(at: IndexPath(row: 0, section: 0), animated: false, scrollPosition: .left)
    }
}

UITableViewDataSource 添加方法

extension ViewController: UITableViewDataSource {
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        if let selectedIndex = self.collectionView.indexPathsForSelectedItems?.first?.row, let listType = ListType(rawValue: selectedIndex) {
            return self.viewModel.numberOfRows(for: listType)
        }
        return 0
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        if let selectedIndex = self.collectionView.indexPathsForSelectedItems?.first?.row, let listType = ListType(rawValue: selectedIndex) {
            let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
            cell.textLabel?.text = self.viewModel.element(at: indexPath.row, for: listType)
            return cell
        }
        return UITableViewCell()
    }
}

UICollectionViewDataSourceUICollectionViewDelegate 方法

extension ViewController: UICollectionViewDataSource, UICollectionViewDelegate {
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return self.viewModel.numberOfTabs()
    }

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! CustomCollectionCell
        cell.textLabel.text = String(describing: self.viewModel.tab(at: indexPath.row)).capitalized
        return cell
    }

    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
        collectionView.scrollToItem(at: indexPath, at: .centeredHorizontally, animated: true)
        self.tableView.reloadData()
    }
}

要处理 tableView scroll 上的collapsing view,实现 scrollViewDidScroll(_:) 方法并处理collapse and expand基于tableViewlastContentOffset,即

extension ViewController: UITableViewDelegate {
    func scrollViewDidScroll(_ scrollView: UIScrollView) {
        if scrollView == self.tableView {
            if (scrollView.contentOffset.y >= (scrollView.contentSize.height - scrollView.frame.size.height)) {
                //Scrolled to bottom
                UIView.animate(withDuration: 0.3) {
                    self.collapsingViewHeightConstraint.constant = 0.0
                    self.view.layoutIfNeeded()
                }
            }
            else if (scrollView.contentOffset.y < self.lastContentOffset || scrollView.contentOffset.y <= 0) && (self.collapsingViewHeightConstraint.constant != 150.0)  {
                //Scrolling up, scrolled to top
                UIView.animate(withDuration: 0.3) {
                    self.collapsingViewHeightConstraint.constant = 150.0
                    self.view.layoutIfNeeded()
                }
            }
            else if (scrollView.contentOffset.y > self.lastContentOffset) && self.collapsingViewHeightConstraint.constant != 0.0 {
                //Scrolling down
                UIView.animate(withDuration: 0.3) {
                    self.collapsingViewHeightConstraint.constant = 0.0
                    self.view.layoutIfNeeded()
                }
            }
            self.lastContentOffset = scrollView.contentOffset.y
        }
    }
}

enter image description here

关于ios - 如何在 iOS 中实现以下布局?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56422384/

相关文章:

ios - 在 UITextField 中的每种类型之后替换字符?

ios - 通过按钮操作进行 segue

xcode - 使应用程序启动时的大小和位置与关闭时相同

跨应用程序的 iOS 自定义 Unicode 字体

ios - swift - 如何在定制的 View 单元格中显示两个不同的图像

swift - 使用 setCollectionViewLayout 导致崩溃,说找不到 layoutAttributesForItemAtIndexPath

ios - 原型(prototype)单元中的约束

swift - tvOS AVPlayerItem 外部艺术品元数据大小

android - 是否可以在应用程序中判断它是在模拟器上运行还是在真实设备上运行

iOS:是否可以调整 Twitter 和/或 Facebook 登录按钮的大小?