[ios] add tabs to bookmarks screen

This commit is contained in:
Aleksey Belousov 2018-06-07 14:11:09 +03:00 committed by Vlad Mihaylenko
parent 46c0547c58
commit a1bcf63b5a
6 changed files with 328 additions and 3 deletions

View file

@ -35,7 +35,6 @@ final class BMCViewController: MWMViewController {
override func viewDidLoad() {
super.viewDidLoad()
title = L("bookmarks")
viewModel = BMCDefaultViewModel()
}
@ -101,7 +100,8 @@ final class BMCViewController: MWMViewController {
private func openCategory(category: BMCCategory) {
let bmViewController = BookmarksVC(category: category.identifier)!
navigationController!.pushViewController(bmViewController, animated: true)
MapViewController.topViewController().navigationController?.pushViewController(bmViewController,
animated: true)
}
private func signup(anchor: UIView, onComplete: @escaping (Bool) -> Void) {

View file

@ -0,0 +1,256 @@
fileprivate class ContentCell: UICollectionViewCell {
var view: UIView? {
didSet {
oldValue?.removeFromSuperview()
if let view = view {
contentView.addSubview(view)
}
}
}
override func prepareForReuse() {
super.prepareForReuse()
view?.removeFromSuperview()
}
override func layoutSubviews() {
super.layoutSubviews()
if let view = view {
view.frame = contentView.bounds
}
}
}
fileprivate class HeaderCell: UICollectionViewCell {
private let label = UILabel()
override init(frame: CGRect) {
super.init(frame: frame)
contentView.addSubview(label)
label.textAlignment = .center
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
contentView.addSubview(label)
label.textAlignment = .center
}
var attributedText: NSAttributedString? {
didSet {
label.attributedText = attributedText
}
}
override func prepareForReuse() {
super.prepareForReuse()
attributedText = nil
}
override func layoutSubviews() {
super.layoutSubviews()
label.frame = contentView.bounds
}
}
protocol TabViewDataSource: AnyObject {
func numberOfPages(in tabView: TabView) -> Int
func tabView(_ tabView: TabView, viewAt index: Int) -> UIView
func tabView(_ tabView: TabView, titleAt index: Int) -> String?
}
@objcMembers
@objc(MWMTabView)
class TabView: UIView {
private enum CellId {
static let content = "contentCell"
static let header = "headerCell"
}
private let tabsLayout = UICollectionViewFlowLayout()
private let tabsContentLayout = UICollectionViewFlowLayout()
private let tabsCollectionView: UICollectionView
private let tabsContentCollectionView: UICollectionView
private let headerView = UIView()
private let slidingView = UIView()
private var slidingViewLeft: NSLayoutConstraint!
private var slidingViewWidth: NSLayoutConstraint!
private var pageCount = 0
weak var dataSource: TabViewDataSource?
var barTintColor = UIColor.white {
didSet {
headerView.backgroundColor = barTintColor
}
}
var headerTextAttributes: [NSAttributedStringKey : Any] = [
.foregroundColor : UIColor.white,
.font : UIFont.systemFont(ofSize: 14, weight: .semibold)
] {
didSet {
tabsCollectionView.reloadData()
}
}
override var tintColor: UIColor! {
didSet {
slidingView.backgroundColor = tintColor
}
}
override init(frame: CGRect) {
tabsCollectionView = UICollectionView(frame: .zero, collectionViewLayout: tabsLayout)
tabsContentCollectionView = UICollectionView(frame: .zero, collectionViewLayout: tabsContentLayout)
super.init(frame: frame)
configure()
}
required init?(coder aDecoder: NSCoder) {
tabsCollectionView = UICollectionView(frame: .zero, collectionViewLayout: tabsLayout)
tabsContentCollectionView = UICollectionView(frame: .zero, collectionViewLayout: tabsContentLayout)
super.init(coder: aDecoder)
configure()
}
private func configure() {
backgroundColor = .white
configureHeader()
configureContent()
addSubview(tabsContentCollectionView)
addSubview(headerView)
configureLayoutContraints()
}
private func configureHeader() {
tabsLayout.scrollDirection = .horizontal
tabsLayout.minimumLineSpacing = 0
tabsLayout.minimumInteritemSpacing = 0
tabsCollectionView.register(HeaderCell.self, forCellWithReuseIdentifier: CellId.header)
tabsCollectionView.dataSource = self
tabsCollectionView.delegate = self
tabsCollectionView.backgroundColor = .clear
slidingView.backgroundColor = tintColor
headerView.layer.shadowOffset = CGSize(width: 0, height: 2)
headerView.layer.shadowColor = UIColor(white: 0, alpha: 1).cgColor
headerView.layer.shadowOpacity = 0.12
headerView.layer.shadowRadius = 2
headerView.layer.masksToBounds = false
headerView.backgroundColor = barTintColor
headerView.addSubview(tabsCollectionView)
headerView.addSubview(slidingView)
}
private func configureContent() {
tabsContentLayout.scrollDirection = .horizontal
tabsContentLayout.minimumLineSpacing = 0
tabsContentLayout.minimumInteritemSpacing = 0
tabsContentCollectionView.register(ContentCell.self, forCellWithReuseIdentifier: CellId.content)
tabsContentCollectionView.dataSource = self
tabsContentCollectionView.delegate = self
tabsContentCollectionView.isPagingEnabled = true
tabsContentCollectionView.bounces = false
tabsContentCollectionView.showsVerticalScrollIndicator = false
tabsContentCollectionView.showsHorizontalScrollIndicator = false
tabsContentCollectionView.backgroundColor = .clear
}
private func configureLayoutContraints() {
tabsCollectionView.translatesAutoresizingMaskIntoConstraints = false;
tabsContentCollectionView.translatesAutoresizingMaskIntoConstraints = false
headerView.translatesAutoresizingMaskIntoConstraints = false
slidingView.translatesAutoresizingMaskIntoConstraints = false
let views = ["header": headerView, "content": tabsContentCollectionView]
addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|[header]|",
options: [], metrics: [:], views: views))
addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|[content]|",
options: [], metrics: [:], views: views))
addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|[header(46)][content]|",
options: [], metrics: [:], views: views))
let headerViews = ["tabs": tabsCollectionView, "slider": slidingView]
headerView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|[tabs]|",
options: [], metrics: [:], views: headerViews))
headerView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|[tabs][slider(3)]|",
options: [], metrics: [:], views: headerViews))
slidingViewLeft = NSLayoutConstraint(item: slidingView, attribute: .left, relatedBy: .equal,
toItem: headerView, attribute: .left, multiplier: 1, constant: 0)
headerView.addConstraint(slidingViewLeft)
slidingViewWidth = NSLayoutConstraint(item: slidingView, attribute: .width, relatedBy: .equal,
toItem: nil, attribute: .notAnAttribute, multiplier: 1, constant: 0)
slidingView.addConstraint(slidingViewWidth)
}
override func willMove(toSuperview newSuperview: UIView?) {
super.willMove(toSuperview: newSuperview)
pageCount = dataSource?.numberOfPages(in: self) ?? 0
}
override func layoutSubviews() {
super.layoutSubviews()
slidingViewWidth.constant = bounds.width / CGFloat(pageCount)
tabsLayout.invalidateLayout()
tabsContentLayout.invalidateLayout()
}
}
extension TabView : UICollectionViewDataSource {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return pageCount
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
var cell = UICollectionViewCell()
if collectionView == tabsContentCollectionView {
cell = collectionView.dequeueReusableCell(withReuseIdentifier: CellId.content, for: indexPath)
if let contentCell = cell as? ContentCell {
contentCell.view = dataSource?.tabView(self, viewAt: indexPath.item)
}
}
if collectionView == tabsCollectionView {
cell = collectionView.dequeueReusableCell(withReuseIdentifier: CellId.header, for: indexPath)
if let headerCell = cell as? HeaderCell {
let title = dataSource?.tabView(self, titleAt: indexPath.item) ?? ""
headerCell.attributedText = NSAttributedString(string: title.uppercased(), attributes: headerTextAttributes)
}
}
return cell
}
}
extension TabView : UICollectionViewDelegateFlowLayout {
func scrollViewDidScroll(_ scrollView: UIScrollView) {
let scrollOffset = scrollView.contentOffset.x / scrollView.contentSize.width
slidingViewLeft.constant = scrollOffset * bounds.width
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
if (collectionView == tabsCollectionView) {
tabsContentCollectionView.scrollToItem(at: indexPath, at: .left, animated: true)
}
}
func collectionView(_ collectionView: UICollectionView,
layout collectionViewLayout: UICollectionViewLayout,
sizeForItemAt indexPath: IndexPath) -> CGSize {
if collectionView == tabsContentCollectionView {
return collectionView.bounds.size
} else {
return CGSize(width: collectionView.bounds.width / CGFloat(pageCount),
height: collectionView.bounds.height)
}
}
}

View file

@ -0,0 +1,40 @@
@objcMembers
@objc(MWMTabViewController)
class TabViewController: MWMViewController {
var viewControllers: [UIViewController] = []
var selectedIndex = 0
var tabView: TabView {
get {
return view as! TabView
}
}
override func loadView() {
let v = TabView()
v.dataSource = self
view = v
}
override func viewDidLoad() {
super.viewDidLoad()
viewControllers.forEach { (vc) in
self.addChildViewController(vc)
vc.didMove(toParentViewController: self)
}
}
}
extension TabViewController: TabViewDataSource {
func numberOfPages(in tabView: TabView) -> Int {
return viewControllers.count
}
func tabView(_ tabView: TabView, viewAt index: Int) -> UIView {
return viewControllers[index].view
}
func tabView(_ tabView: TabView, titleAt index: Int) -> String? {
return viewControllers[index].title
}
}

View file

@ -358,7 +358,19 @@ BOOL gIsFirstMyPositionMode = YES;
- (void)openMigration { [self performSegueWithIdentifier:kMigrationSegue sender:self]; }
- (void)openBookmarks
{
[self.navigationController pushViewController:[[BMCViewController alloc] init] animated:YES];
BMCViewController * bookmarks = [[BMCViewController alloc] init];
MWMViewController * catalog = [[MWMViewController alloc] init];
bookmarks.title = L(@"bookmarks_page_my");
catalog.title = L(@"bookmarks_page_downloaded");
MWMTabViewController * tvc = [[MWMTabViewController alloc] init];
tvc.title = L(@"bookmarks");
tvc.tabView.barTintColor = [UIColor primary];
tvc.tabView.tintColor = [UIColor white];
tvc.tabView.headerTextAttributes = @{NSForegroundColorAttributeName: [UIColor whitePrimaryText],
NSFontAttributeName: [UIFont medium14]};
tvc.viewControllers = @[bookmarks, catalog];
[self.navigationController pushViewController:tvc animated:YES];
}
- (void)openMapsDownloader:(MWMMapDownloaderMode)mode

View file

@ -641,6 +641,7 @@ using namespace osm_auth_ios;
navigationBar.barTintColor = [UIColor primary];
navigationBar.titleTextAttributes = [self navigationBarTextAttributes];
navigationBar.translucent = NO;
navigationBar.shadowImage = [UIImage new];
}
+ (void)customizeAppearance

View file

@ -349,6 +349,8 @@
4767CDC120B477BA00BD8166 /* WelcomeViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4767CDC020B477BA00BD8166 /* WelcomeViewController.swift */; };
47800D1D20BEEE2E00072F42 /* TermsOfUseController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 47800D1C20BEEE2E00072F42 /* TermsOfUseController.swift */; };
47800D2520C05E3200072F42 /* libFlurry_8.6.1.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 47800D2420C05E3200072F42 /* libFlurry_8.6.1.a */; };
47F86CFF20C936FC00FEE291 /* TabView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 47F86CFE20C936FC00FEE291 /* TabView.swift */; };
47F86D0120C93D8D00FEE291 /* TabViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 47F86D0020C93D8D00FEE291 /* TabViewController.swift */; };
4A300ED51C6DCFD400140018 /* countries-strings in Resources */ = {isa = PBXBuildFile; fileRef = 4A300ED31C6DCFD400140018 /* countries-strings */; };
56C74C391C74A3BC00B71B9F /* MWMInputEmailValidator.mm in Sources */ = {isa = PBXBuildFile; fileRef = 34ABA62F1C2D58F300FE1BEC /* MWMInputEmailValidator.mm */; };
56EE14D11FE804550036F20C /* libtransit.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 56EE14D21FE804550036F20C /* libtransit.a */; };
@ -1281,6 +1283,8 @@
47800D1C20BEEE2E00072F42 /* TermsOfUseController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TermsOfUseController.swift; sourceTree = "<group>"; };
47800D2420C05E3200072F42 /* libFlurry_8.6.1.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libFlurry_8.6.1.a; sourceTree = "<group>"; };
47800D2620C05E8700072F42 /* FlurryConsent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FlurryConsent.h; sourceTree = "<group>"; };
47F86CFE20C936FC00FEE291 /* TabView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TabView.swift; sourceTree = "<group>"; };
47F86D0020C93D8D00FEE291 /* TabViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TabViewController.swift; sourceTree = "<group>"; };
4A00DBDE1AB704C400113624 /* drules_proto_dark.bin */ = {isa = PBXFileReference; lastKnownFileType = archive.macbinary; name = drules_proto_dark.bin; path = ../../data/drules_proto_dark.bin; sourceTree = "<group>"; };
4A23D1561B8B4DD700D4EB6F /* drules_proto_clear.bin */ = {isa = PBXFileReference; lastKnownFileType = archive.macbinary; name = drules_proto_clear.bin; path = ../../data/drules_proto_clear.bin; sourceTree = "<group>"; };
4A23D1571B8B4DD700D4EB6F /* resources-6plus_clear */ = {isa = PBXFileReference; lastKnownFileType = folder; name = "resources-6plus_clear"; path = "../../data/resources-6plus_clear"; sourceTree = "<group>"; };
@ -2536,6 +2540,7 @@
346EDAD81B9F0E15004F8DB5 /* Components */ = {
isa = PBXGroup;
children = (
47F86CFD20C936B300FEE291 /* TabView */,
F653CE131C71F5DC00A453F1 /* AddPlace NavigationBar */,
3470402E1EA6470700038379 /* BorderedButton.swift */,
340708761F2B5D6C00029ECC /* DimBackground.swift */,
@ -3051,6 +3056,15 @@
path = Widgets;
sourceTree = "<group>";
};
47F86CFD20C936B300FEE291 /* TabView */ = {
isa = PBXGroup;
children = (
47F86CFE20C936FC00FEE291 /* TabView.swift */,
47F86D0020C93D8D00FEE291 /* TabViewController.swift */,
);
path = TabView;
sourceTree = "<group>";
};
97B4E9271851DAB300BEC5D7 /* Custom Views */ = {
isa = PBXGroup;
children = (
@ -4383,6 +4397,7 @@
F6E2FF541E097BA00083EBEC /* MWMHelpController.mm in Sources */,
349FC5481F680DAE00968C9F /* ExpandableTextView.swift in Sources */,
F6E2FF5A1E097BA00083EBEC /* MWMNightModeController.mm in Sources */,
47F86D0120C93D8D00FEE291 /* TabViewController.swift in Sources */,
6741A9A51BF340DE002C974C /* MWMShareActivityItem.mm in Sources */,
3408963F1F83CEDE00BC7117 /* MWMAuthorizationViewModel.mm in Sources */,
F6E2FE1F1E097BA00083EBEC /* MWMOpeningHoursCommon.mm in Sources */,
@ -4526,6 +4541,7 @@
34D3B0361E389D05004100F9 /* MWMEditorSelectTableViewCell.mm in Sources */,
F6E2FD711E097BA00083EBEC /* MWMMapDownloaderTableViewCell.mm in Sources */,
F6E2FE4F1E097BA00083EBEC /* MWMActionBarButton.mm in Sources */,
47F86CFF20C936FC00FEE291 /* TabView.swift in Sources */,
34AB66741FC5AA330078E451 /* BaseRoutePreviewStatus.swift in Sources */,
340475531E081A4600C92850 /* MWMCustomFacebookEvents.mm in Sources */,
349D1CE41E3F836900A878FD /* UIViewController+Hierarchy.swift in Sources */,