rechsteiner / Parchment

A paging view with a highly customizable menu ✨
MIT License
3.36k stars 418 forks source link

Weird Issue with Indexes #247

Closed Smiller193 closed 5 years ago

Smiller193 commented 6 years ago

Im not sure if this is an error or not but is the library supposed to load two indexes at a time? Everytime I select one it loads the index right next to it. For example if i select index 1 it loads the content for index 2. Is this library supposed to load so many times?

Sopheak0 commented 6 years ago

I was about to open a new issue too about this problem? I don't want it to load like that though! How can we achieve this?

rechsteiner commented 5 years ago

Yeah, this is the expected behaviour if you are talking about loading the next view controllers? This is the same way that UIPageViewController works. It's initializing the previous and next view controllers in order prevent any lag when the user starts swiping to the next item.

Smiller193 commented 5 years ago

@rechsteiner can i ask another question or do I have to open up a whole different issue

rechsteiner commented 5 years ago

No, feel free to ask here. What's up? 🙂

Smiller193 commented 5 years ago

@rechsteiner This is the current setup that i have for my menu items

class MainViewController: UIViewController,ContentViewControllerDelegate {
    fileprivate let items = [
        ImageItem(index: 1, title: "City", headerImage: UIImage(named: "city")!),
        ImageItem(index: 2, title: "Concert", headerImage: UIImage(named: "concert")!),
        ImageItem(index: 4, title: "Sports", headerImage: UIImage(named: "sports")!),
        ImageItem(index: 5, title: "University", headerImage: UIImage(named: "university")!)
    ]
    let pagingViewController = CustomPagingViewController()
    let customLeftBar = LocationManager()
    var placesClient = GMSPlacesClient()

    private let menuInsets = UIEdgeInsets(top: 12, left: 5, bottom: 12, right: 5)
    private let menuItemSize = CGSize(width: 85, height: 70)
    private var menuHeight: CGFloat {
        return menuItemSize.height + menuInsets.top + menuInsets.bottom
    }
    var savedLocation: CLLocation?
    var lastSelectedDate: Date?
    var finalCategoryEvents:[String:[Event]] = [:]
    var featuredEvents:[String:[Event]] = [:]
    let dateFormatter = DateFormatter()

    override func viewDidLoad() {
        super.viewDidLoad()
        setupViews()
        // Do any additional setup after loading the view.
    }

    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        self.tabBarController?.tabBar.isHidden = false

    }

    @objc func setupViews(){
        view.backgroundColor = .white
        setupBarButtonItems()
        setupPagingController()
        grabUserLocation()
    }

    private func calculateMenuHeight(for scrollView: UIScrollView) -> CGFloat {
        // Calculate the height of the menu view based on the scroll view
        // content offset.
        let maxChange: CGFloat = 30
        let offset = min(maxChange, scrollView.contentOffset.y + menuHeight) / maxChange
        let height = menuHeight - (offset * maxChange)
        return height
    }

    private func updateMenu(height: CGFloat) {
        guard let menuView = pagingViewController.view as? CustomPagingView else { return }

        // Update the height constraint of the menu view.
        menuView.menuHeightConstraint?.constant = height

        // Update the size of the menu items.
        pagingViewController.menuItemSize = .fixed(
            width: menuItemSize.width,
            height: height - menuInsets.top - menuInsets.bottom
        )

        // Invalidate the collection view layout and call layoutIfNeeded
        // to make sure the collection is updated.
        pagingViewController.collectionViewLayout.invalidateLayout()
        pagingViewController.collectionView.layoutIfNeeded()
    }

    /// Calculate the menu offset based on the content offset of the
    /// scroll view.
    private func menuOffset(for scrollView: UIScrollView) -> CGFloat {
        return min(pagingViewController.options.menuHeight, max(0, scrollView.contentOffset.y))
    }

    func contentViewControllerDidScroll(menuFeed : MenuFeedController) {
        if let menuView = pagingViewController.view as? CustomPagingView {
            menuView.menuTopConstraint?.constant = -menuOffset(for: menuFeed.collectionView)
        }
        let height = calculateMenuHeight(for: menuFeed.collectionView)
        updateMenu(height: height)
    }

    @objc func setupPagingController(){
        pagingViewController.menuItemSource =  .class(type: ImagePagingCell.self)
        pagingViewController.menuItemSize = .fixed(width: menuItemSize.width, height: menuItemSize.height)
        pagingViewController.menuItemSpacing = 8
        pagingViewController.menuInsets = menuInsets
        pagingViewController.borderColor = UIColor(white: 0, alpha: 0.1)
        pagingViewController.indicatorColor = UIColor.rgb(red: 44, green: 152, blue: 229)
        pagingViewController.contentInteraction = .none

        pagingViewController.indicatorOptions = .visible(
            height: 1,
            zIndex: Int.max,
            spacing: UIEdgeInsets.zero,
            insets: UIEdgeInsets.zero)

        pagingViewController.borderOptions = .visible(
            height: 1,
            zIndex: Int.max - 1,
            insets: UIEdgeInsets(top: 0, left: 18, bottom: 0, right: 18))

        addChildViewController(pagingViewController)
        view.addSubview(pagingViewController.view)
        pagingViewController.view.snp.makeConstraints { (make) in
            make.top.equalTo(view.safeAreaLayoutGuide.snp.top)
            make.left.right.equalTo(view.safeAreaLayoutGuide)
            make.bottom.equalTo(view.safeAreaLayoutGuide.snp.bottom)
        }

        pagingViewController.didMove(toParentViewController: self)

        // Set our custom data source.
        pagingViewController.dataSource = self
        pagingViewController.delegate = self

        // Set the first item as the selected paging item.
        pagingViewController.select(index: 0)
    }

    @objc func setupBarButtonItems(){
        let sideMenuButton = UIBarButtonItem(image: UIImage(named: "icons8-Menu-48")?.withRenderingMode(.alwaysOriginal), style: .plain, target: self, action: #selector(self.rightBarPressed))
        let calendarButton = UIBarButtonItem(image: UIImage(named: "icons8-calendar-50")?.withRenderingMode(.alwaysOriginal), style: .plain, target: self, action: #selector(self.presentCalendar))
        navigationItem.rightBarButtonItems = [sideMenuButton,calendarButton]
    }

    //will present the dropdown/side menu
    @objc func rightBarPressed(){
        print("right bar tapped")
        self.sideMenuController?.revealMenu(animated: true, completion: nil)
    }

    //will present search vc
    @objc func leftBarPressed(){
        print("left bar tapped")
        let searchController = PlacesSearchController()
        searchController.mainVC = self
        self.navigationController?.pushViewController(searchController, animated: false)
    }

    //will present the calendar
    @objc func presentCalendar(){
        print("calendar pressed")
        let calendar = CalendarViewController()
        if let lastDate = lastSelectedDate {
            calendar.passedDate = lastDate
        }
        calendar.mainVC = self
        calendar.savedLocation1 = self.savedLocation
          self.navigationController?.pushViewController(calendar, animated: false)
    }

}

extension MainViewController: PagingViewControllerDataSource {

    func pagingViewController<T>(_ pagingViewController: PagingViewController<T>, viewControllerForIndex index: Int) -> UIViewController {
        let menu = MenuFeedController()
        menu.featuredEvents = self.featuredEvents[items[index].title.lowercased()]
        menu.finalCategoryEvents = self.finalCategoryEvents[items[index].title.lowercased()]
        let menuHeight = pagingViewController.options.menuHeight
        let insets = UIEdgeInsets(top: menuHeight, left: 0, bottom: 0, right: 0)
        menu.collectionView.contentInset = insets
        menu.ContentViewControllerDelegate = self
        menu.collectionView.scrollIndicatorInsets = insets
        menu.rootRef = self
        return menu
    }

    func pagingViewController<T>(_ pagingViewController: PagingViewController<T>, pagingItemForIndex index: Int) -> T {
        return items[index] as! T
    }

    func numberOfViewControllers<T>(in: PagingViewController<T>) -> Int{
        return items.count
    }

}

It works good on phones with a smaller width like the iphone X, or the iphone 7 or iphone 8. However when I go to screens with a bigger width like the plus models it looks like this.

screen shot 2018-09-30 at 10 44 17 am

Is there anyway to get to adapt to the screen size so there isn't that random white space there. Other than that everything else is good.

rechsteiner commented 5 years ago

Yes, you can use sizeToFit as your menuItemSize. If you change this line:

pagingViewController.menuItemSize = .fixed(width: menuItemSize.width, height: menuItemSize.height)

To:

pagingViewController.menuItemSize = .sizeToFit(minWidth: menuItemSize.width, height: menuItemSize.height)

I'm pretty sure it should work 🙂

Smiller193 commented 5 years ago

nope still looks the same I changed it in the setupPagingController function @rechsteiner still has space to the right

Smiller193 commented 5 years ago

maybe it is due to the insets let me try to change that update: that didn't work

rechsteiner commented 5 years ago

Are you also using sizeToFit in your updateMenu function?

Smiller193 commented 5 years ago

no im not let me try that @rechsteiner

Smiller193 commented 5 years ago

that fixed it

rechsteiner commented 5 years ago

Awesome!