Как я могу добиться следующего макета в iOS? - PullRequest
0 голосов
/ 03 июня 2019

У меня есть следующий макет для разработки приложений для iOS. Mock up

Макет содержит следующие части:

  1. Свертывающаяся панель инструментов : эта view должна работать как в Android, т.е. прокрутка должна быть свернута.
  2. Меню вкладок : Это меню вкладок. При смахивании tableview необходимо обновить в соответствии с выбранным меню. На scrolling вкладка меню должна быть зафиксирована сверху.
  3. Просмотр таблицы : Это просто tableview содержит данные в соответствии с меню, выбранным в меню вкладки.
  4. Нижняя вкладка : Это UITabbarMenu.

Я попробовал следующий подход:

enter image description here

Я использовал Pagingkit библиотека для меню вкладок. Я создал высоту vProductList (родительский вид tabbar и tableview) до высоты экрана устройства.

Проблема появилась, когда просмотр таблицы был внутри scrollview. Проблема была в tableview и scrollview по-разному действует при прокрутке. Поэтому, чтобы удалить это, я сначала отключаю прокрутку tableview и включаю в методе viewDidScroll при условии, что представление меню вкладок находится в точке (0,0) экрана. Но чтобы получить эффект, нужно дважды прокрутить. Это было глючно. Как мне добиться плавной прокрутки с помощью этого подхода? Есть ли библиотека, которая может решить эту проблему?

1 Ответ

4 голосов
/ 03 июня 2019

Вот как это можно сделать.

Просмотр иерархии:

enter image description here

Вы можетеиспользуйте UICollectionView для создания Tabbar.A UITableView для обработки данных, когда tab равно selected.Для обработки данных в UICollectionView и UITableView создайте 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, который идентифицирует types of tabs в collectionViewи данные, которые должны быть представлены в tableView.
  2. a class ViewModel, который обрабатывает dataSource для collectionView и tableView.

Давайтесоздать UIViewController с некоторыми outlets, то есть

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()
    }
}

UICollectionViewDataSource и UICollectionViewDelegate методов

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()
    }
}

Для обработки collapsing view на tableView scroll, реализуйте метод scrollViewDidScroll(_:) и обрабатывайте collapse and expand на основе lastContentOffset tableView, то есть

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

...