rechsteiner / Parchment

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

add to parent ScrollView #336

Closed pbreah closed 5 years ago

pbreah commented 5 years ago

First of all congrats for such amazing work. This is an implementation question I have been attempting for several days without success.

I have a parent UIViewController that I'm using to implement the paging menu. It works in the sense that I see the menu and the child controllers load and I can see the content of one of the child controllers partially.

On the child view controller I have an UILabel with text content of 4 paragraphs. The problem is I need the content to scroll once added to the parent view controller onto the scrollView. What it does now is the content gets truncated to the screen's bottom edge. Even if I try to force the scrollview content size to be much larger, the text of the UILabel of the child view controller is still truncated - I just get to scroll the truncated content.

Below is the code I'm using. The child view controllers are all setup on the storyboard and the text of the UILabel is static (for now) - as I'm testing until I can get this to work.

I have looked at the examples you have for Scrolling, Header and Storyboard on the repo, and you may see the code very familiar - after mixing and matching all your examples, I still can't get this to work - to allow the entire parent view to scroll and not truncate the text of the child view controller.

Here is how it looks before scrolling:

before-scrolling

And here after scrolling the parent view controller:

after-scrolling

Here is the code:

import UIKit
import Parchment

class MyDetailsViewController: UIViewController {
    var menuItems = [
        "Option 1",
        "Option 2"
    ]
    private var pagingViewController: CustomPagingViewController!

    @IBOutlet weak var mainImage: UIImageView!
    @IBOutlet weak var topLabel: UILabel!
    @IBOutlet weak var bottomLabel: UILabel!
   // this scrollView is pinned to all edges of it's superview in IB
    @IBOutlet weak var scrollView: UIScrollView! 

    override func viewDidLoad() {
        super.viewDidLoad()
        pagingViewController = CustomPagingViewController(scrollView: self.scrollView)
        pagingViewController.dataSource = self
        pagingViewController.delegate = self
        addChild(pagingViewController)
        pagingViewController.didMove(toParent: self)

        configureView()
    }

    override func viewWillAppear(_ animated: Bool) {
    }

    override func viewDidAppear(_ animated: Bool) {
       /* I'm forcing the scrollView content size, but this code shouldn't be here
      as I would like the content of the child view controller to expand on the 
     parent view controller and allow to scroll on the parent to view all the child's content */
        scrollView.contentSize = CGSize(width: CGFloat(375), height: CGFloat(3000))
    }

    // MARK: - UI Config

    func configureView() {
        // Customize the menu styling.
        pagingViewController.selectedTextColor = .black
        pagingViewController.indicatorColor = .black
        pagingViewController.indicatorOptions = .visible(
            height: 1,
            zIndex: Int.max,
            spacing: .zero,
            insets: .zero
        )
        // bottom menu hiding & top bar styling
        self.tabBarController?.tabBar.isHidden = true
        if #available(iOS 11.0, *) {
            self.navigationController?.navigationBar.prefersLargeTitles = false
        } else {
            // Fallback on earlier versions
            self.navigationController?.navigationBar.barStyle = .default
        }
        // Constrain the paging view to all edges.
        NSLayoutConstraint.activate([
            pagingViewController.view.topAnchor.constraint(equalTo: scrollView.topAnchor),
            pagingViewController.view.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor),
            pagingViewController.view.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor),
            pagingViewController.view.trailingAnchor.constraint(equalTo: scrollView.trailingAnchor)
        ])
    }

    func getViewController<T: UIViewController>(sbName: String, vcNmae: String) -> T? {
        if let vc = storyboard?.instantiateViewController(withIdentifier: sbName) as? T {
            return vc
        }
        return nil
    }
}

extension TourDetailsViewController: PagingViewControllerDataSource {
    func numberOfViewControllers<T>(in pagingViewController: PagingViewController<T>) -> Int where T : PagingItem, T : Comparable, T : Hashable {
        return menuItems.count
    }

    func pagingViewController<T>(_ pagingViewController: PagingViewController<T>, viewControllerForIndex index: Int) -> UIViewController where T : PagingItem, T : Comparable, T : Hashable {
        if let thisViewController = getViewController(sbName: menuItems[index], vcNmae: menuItems[index]) {
            return thisViewController
        }

        return UIViewController(nibName: nil, bundle: nil)
    }

    func pagingViewController<T>(_ pagingViewController: PagingViewController<T>, pagingItemForIndex index: Int) -> T where T : PagingItem, T : Comparable, T : Hashable {
        return PagingIndexItem(index: index, title: menuItems[index]) as! T
    }
}

extension TourDetailsViewController: PagingViewControllerDelegate {
    func pagingViewController<T>(_ pagingViewController: PagingViewController<T>, didScrollToItem pagingItem: T, startingViewController: UIViewController?, destinationViewController: UIViewController, transitionSuccessful: Bool) {
    }

    func pagingViewController<T>(_ pagingViewController: PagingViewController<T>, willScrollToItem pagingItem: T, startingViewController: UIViewController, destinationViewController: UIViewController) {
        print("hey \(pagingItem)")
    }
}

// MARK: - Custom Paging View

class CustomPagingView: PagingView {
    static let HeaderHeight: CGFloat = 380
    var scrollView: UIScrollView?

    init(options: PagingOptions, collectionView: UICollectionView, pageView: UIView, scrollView: UIScrollView) {
        self.scrollView = scrollView
        super.init(options: options, collectionView: collectionView, pageView: pageView)
    }

    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    override func setupConstraints() {
        guard let activeScrollView = scrollView else {
            print("no active scrollView")
            return
        }

        pageView.translatesAutoresizingMaskIntoConstraints = false
        collectionView.translatesAutoresizingMaskIntoConstraints = false

        NSLayoutConstraint.activate([
            collectionView.leadingAnchor.constraint(equalTo: activeScrollView.leadingAnchor),
            collectionView.trailingAnchor.constraint(equalTo: activeScrollView.trailingAnchor),
            collectionView.heightAnchor.constraint(equalToConstant: options.menuHeight),
            collectionView.topAnchor.constraint(equalTo: activeScrollView.topAnchor, constant: 330),

            pageView.leadingAnchor.constraint(equalTo: activeScrollView.leadingAnchor),
            pageView.trailingAnchor.constraint(equalTo: activeScrollView.trailingAnchor),
            pageView.bottomAnchor.constraint(equalTo: activeScrollView.bottomAnchor),
            pageView.topAnchor.constraint(equalTo: activeScrollView.topAnchor, constant: 350),
        ])
    }
}

class CustomPagingViewController: PagingViewController<PagingIndexItem> {
    var scrollView: UIScrollView?

    init(scrollView: UIScrollView) {
        self.scrollView = scrollView
        super.init()
    }

    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    override func loadView() {
        view = CustomPagingView(
            options: options,
            collectionView: collectionView,
            pageView: pageViewController.view,
            scrollView: scrollView!
        )
        scrollView?.addSubview(view)
    }
}
rechsteiner commented 5 years ago

Hi @pbreah! That you for the detailed report. It's a bit hard to say without being able to debug your application, but it looks a bit like you just need to set the contentInset of you scroll view to account of the header view. For instance, in the HeaderExample we do this: https://github.com/rechsteiner/Parchment/blob/master/HeaderExample/ViewController.swift#L112

Does that fix the issue?

rechsteiner commented 5 years ago

@pbreah did you manage to get this working?