Как я могу добиться следующего макета в iOS?
У меня есть следующий макет для разработки приложений для iOS.
Макет содержит следующие части:
- Свертывающаяся панель инструментов: эта
view
должен работать как в андроиде т.е. при прокрутке он должен быть свернут. - Меню вкладок: это меню вкладок. При смахивании
tableview
должен быть обновлен в соответствии с выбранным меню. Наscrolling
Вкладка меню должна быть зафиксирована сверху. - Tableview: это просто
tableview
содержит данные в соответствии с меню, выбранным в меню вкладок. - Нижняя вкладка: это
UITabbarMenu
,
Я попытался со следующим подходом:
Я использовал библиотеку Pagingkit для меню вкладок. Я создал высоту vProductList (родительский вид tabbar
а также tableview
) к высоте экрана устройства.
Проблема появилась, когда просмотр таблицы был внутри scrollview
, Проблема была tableview
а также scrollview
действует по-разному при прокрутке. Таким образом, чтобы удалить это я отключаю прокрутку tableview
сначала и включен в viewDidScroll
метод при условии, что представление меню вкладок находится в точке (0,0) экрана. Но нужно дважды прокрутить, чтобы получить эффект. Это было глючно. Как мне добиться плавной прокрутки с помощью этого подхода? Есть ли библиотека, которая может решить эту проблему?
1 ответ
Вот как вы можете решить это.
Посмотреть иерархию:
Вы можете использовать UICollectionView
создать Tabbar
, 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]
}
}
}
В приведенном выше коде я создал
-
enum ListType
который идентифицируетtypes of tabs
вcollectionView
и данные, которые должны быть представлены вtableView
, -
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
}
}
}