Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Views added using addsubviews are not working inside SnackbarController #1273

Open
ahsanaasim opened this issue Oct 6, 2019 · 5 comments
Open

Comments

@ahsanaasim
Copy link

I am trying to use Snackbar in my app. I have tabBarController containing my viewControllers.
I have initiated the Snackbar Setup in the following way.

let homeNavigationController = UINavigationController()
        homeNavigationController.navigationBar.titleTextAttributes = textAttributes
        homeNavigationController.navigationBar.tintColor = Colors.wiseMagenta
        
        let dashboardController = HomeContainerController()
        homeNavigationController.viewControllers = [dashboardController]
        
        let homeSnackBarController = AppSnackbarController(rootViewController: homeNavigationController)
        homeSnackBarController.shouldExtend = false
        homeSnackBarController.tabBarItem = UITabBarItem(title: "Home".localized(), image: UIImage(named: "home"), tag: 0);

When I add homeNavigationController as my tabBarController viewcontroller item, Everything loads perfectly. This is how it looks when I add homeNavigationController directly

Expected Output

I have a UIPageViewController added inside the HomeContainerController which is not getting added when I use the AppSnackbarController as tabBarController viewController. But nothing is getting added as expected. This is how it looks when I use AppSnackbarController

Output I am getting

So there must be something wrong with AppSnackbarController or I am implementing this incorrectly.

My AppSnackbarController code:

import UIKit
import Material

class AppSnackbarController: SnackbarController {
    var shouldExtend = false
    
    open override func prepare() {
        super.prepare()
        delegate = self
    }
    
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        if shouldExtend {
            extendViews()
        }
    }
    
    override func viewWillLayoutSubviews() {
        super.viewWillLayoutSubviews()
    }
    
    override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()
    }
    
    func extendViews() {
        self.tabBarController?.tabBar.isHidden = true
        self.edgesForExtendedLayout = UIRectEdge.bottom
        self.extendedLayoutIncludesOpaqueBars = true
    }
}

extension AppSnackbarController: SnackbarControllerDelegate {
    func snackbarController(snackbarController: SnackbarController, willShow snackbar: Snackbar) {
        print("snackbarController will show")
    }
    
    func snackbarController(snackbarController: SnackbarController, willHide snackbar: Snackbar) {
        print("snackbarController will hide")
    }
    
    func snackbarController(snackbarController: SnackbarController, didShow snackbar: Snackbar) {
        print("snackbarController did show")
    }
    
    func snackbarController(snackbarController: SnackbarController, didHide snackbar: Snackbar) {
        print("snackbarController did hide")
    }
}

My HomeContainerController code

import UIKit
import Material

class HomeContainerController: UIViewController {

    @IBOutlet weak var topContainer: UIView!
    @IBOutlet weak var pagerContainer: UIView!
    
    let subTitleView: UILabel = {
        let leftLabel = UILabel(frame: .zero)
        leftLabel.font = UIFont.appSemiBoldFontWith(size: 14)
        leftLabel.numberOfLines = 1
        leftLabel.translatesAutoresizingMaskIntoConstraints = false
        leftLabel.numberOfLines = 1
        leftLabel.textAlignment = .center
        leftLabel.textColor = Colors.secondaryText!
        return leftLabel
    }()
    
    
    let tabBar = TabBar()
    var buttons = [TabItem]()
    @IBOutlet weak var topView: UIView!
    @IBOutlet weak var anotherview: UIView!
    
//    var topview: UIView!
//    var v: UIView = UIView()
    let homePagerController = HomeControllers(transitionStyle: .scroll, navigationOrientation: .horizontal, options: nil)
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        initTopPanel()
    }

    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        initDate()
        initNavBar()
    }
    
    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        self.navigationController?.setNavigationBarHidden(false, animated: true)
    }
    
    override func viewWillLayoutSubviews() {
        super.viewWillLayoutSubviews()
        
    }
    
    override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()
    }
    
    
    func initTopPanel() {
        DispatchQueue.main.async {
            self.prepareTopViews()
            self.preparTabViews()
        }
        
        self.homePagerController.tabBar = self.tabBar
        self.addChildViewController(self.homePagerController)
        self.homePagerController.view.translatesAutoresizingMaskIntoConstraints = false
        self.pagerContainer.addSubview(self.homePagerController.view)
        self.pagerContainer.backgroundColor = .red
        NSLayoutConstraint.activate([
            self.homePagerController.view.leadingAnchor.constraint(equalTo: self.pagerContainer.leadingAnchor),
            self.homePagerController.view.trailingAnchor.constraint(equalTo: self.pagerContainer.trailingAnchor),
            self.homePagerController.view.topAnchor.constraint(equalTo: self.pagerContainer.topAnchor),
            self.homePagerController.view.bottomAnchor.constraint(equalTo: self.pagerContainer.bottomAnchor)
            ])
        
        self.homePagerController.didMove(toParentViewController: self)
        
        //        Translator().defaultTranslation()
        for recognizer in self.homePagerController.gestureRecognizers {
            if recognizer is UITapGestureRecognizer {
                recognizer.isEnabled = false
            }
        }
    }
    
    func initNavBar() {
        self.navigationController?.setNavigationBarHidden(true, animated: false)
        if App.shouldToggleNightMode {
            self.toggleNavBarNightMode()
        }
    }
    
    func initDate() {
        let adjustment = UserDefaults.standard.integer(forKey: UserDefaultKeys.IslamicCalenderAdjstment)
        var date = Date()
        date = Calendar.current.date(byAdding: .day, value: adjustment, to: date)!
        subTitleView.text = Utils.shared.arabicDateInFormattedString(format: "d MMMM || yyyy", date: date)
    }
    
    func prepareTopViews() {
        let titleView: UILabel = {
            let leftLabel = UILabel(frame: .zero)
            leftLabel.font = UIFont.appBoldFontWith(size: 19)
            leftLabel.numberOfLines = 1
            leftLabel.translatesAutoresizingMaskIntoConstraints = false
            leftLabel.numberOfLines = 1
            leftLabel.textAlignment = .center
            leftLabel.textColor = Colors.wiseMagenta!
            return leftLabel
        }()
        
        titleView.text = "Quran Touch"
        
        let containerView = UIStackView()
        containerView.axis = .vertical
        containerView.distribution = .fillProportionally
        containerView.alignment = .center
        
        containerView.addArrangedSubview(titleView)
        containerView.addArrangedSubview(subTitleView)
        containerView.backgroundColor = .red
        
        self.topView.addSubview(containerView)
        
        containerView.translatesAutoresizingMaskIntoConstraints = false
        let leftConstraint = containerView.leftAnchor.constraint(equalTo: topView.leftAnchor)
        let rightConstraint = containerView.rightAnchor.constraint(equalTo: topView.rightAnchor)
        let horizontalConstraint = containerView.centerXAnchor.constraint(equalTo: topView.centerXAnchor)
        let verticalConstraint = containerView.centerYAnchor.constraint(equalTo: topView.centerYAnchor)
        NSLayoutConstraint.activate([leftConstraint, rightConstraint, horizontalConstraint, verticalConstraint])
        
        initBarButtons()
    }
    
    func initBarButtons() {
        let profileButton = CircularButton()
        profileButton.setImage(UIImage(named: "dash.settings")!.tint(with: Colors.wiseMagenta!) , for: .normal)
        
        profileButton.addTarget(self, action: #selector(openSettings(sender:)), for: .touchUpInside)
        topView.addSubview(profileButton)
        
        profileButton.translatesAutoresizingMaskIntoConstraints = false
        let heightConstraint = profileButton.heightAnchor.constraint(equalToConstant: 40)
        let widthConstraint = profileButton.widthAnchor.constraint(equalToConstant: 40)
        let rightConstraint = profileButton.rightAnchor.constraint(equalTo: topView.rightAnchor, constant: -16.0)
        let verticalConstraint = profileButton.centerYAnchor.constraint(equalTo: topView.centerYAnchor)
        NSLayoutConstraint.activate([heightConstraint, widthConstraint, rightConstraint, verticalConstraint])
        
        let freePremiumButton = UIButton()
        freePremiumButton.setImage(UIImage(named: "home_free_premium")! , for: .normal)
        topView.addSubview(freePremiumButton)
        
        freePremiumButton.translatesAutoresizingMaskIntoConstraints = false
        let heightConstraint2 = freePremiumButton.heightAnchor.constraint(equalToConstant: 30)
        let widthConstraint2 = freePremiumButton.widthAnchor.constraint(equalToConstant: 30)
        let rightConstraint2 = freePremiumButton.leftAnchor.constraint(equalTo: topView.leftAnchor, constant: 16.0)
        let verticalConstraint2 = freePremiumButton.centerYAnchor.constraint(equalTo: topView.centerYAnchor)
        NSLayoutConstraint.activate([heightConstraint2, widthConstraint2, rightConstraint2, verticalConstraint2])
        
    }
    
    func preparTabViews() {
        self.prepareButtons()
        self.prepareTabBar()
    }
    
    @objc func openSettings(sender: Any) {
        let vc = ProfileController()
        self.navigationController?.pushViewController(vc, animated: true)
    }

    /*
    // MARK: - Navigation

    // In a storyboard-based application, you will often want to do a little preparation before navigation
    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        // Get the new view controller using segue.destination.
        // Pass the selected object to the new view controller.
    }
    */

}


extension HomeContainerController {
    fileprivate func prepareButtons() {
        let btn1 = TabItem(title: "Dua", titleColor: Colors.wiseMagenta!)
        btn1.pulseAnimation = .centerRadialBeyondBounds
        btn1.tag = 0
        let attributes = [
            NSAttributedStringKey.font: UIFont.appRegularFontWith(size: 15),
            NSAttributedStringKey.foregroundColor: Colors.secondaryText!
        ]
        
        let selectedAttributes = [
            NSAttributedStringKey.font: UIFont.appSemiBoldFontWith(size: 15),
            NSAttributedStringKey.foregroundColor: Colors.wiseMagenta!
        ]
        
        btn1.setAttributedTitle(NSAttributedString(string: "Dashboard", attributes: attributes), for: .normal)
        btn1.setAttributedTitle(NSAttributedString(string: "Dashboard", attributes: selectedAttributes), for: .selected)
        buttons.append(btn1)
        
        let btn2 = TabItem(title: "Community", titleColor: Colors.wiseMagenta!)
        btn2.tag = 1
        btn2.setAttributedTitle(NSAttributedString(string: "Explore", attributes: attributes), for: .normal)
        btn2.setAttributedTitle(NSAttributedString(string: "Explore", attributes: selectedAttributes), for: .selected)
        btn2.pulseAnimation = .none
        
        buttons.append(btn2)
    }
    
    fileprivate func prepareTabBar() {
        
//        tabBar.delegate = self
        
        tabBar.dividerColor = Color.clear
        
        
        tabBar.lineColor = Colors.wiseMagenta!
        tabBar.lineAlignment = .bottom
        
        tabBar.backgroundColor = Color.clear
        tabBar.tabItems = buttons
        
        tabBar.tabBarLineStyle = .custom { tabItem in
            if tabItem.tag == 1 {
                return tabItem.bounds.width - 30
            }
            return tabItem.bounds.width
        }
        tabBar.lineHeight = 1
        tabBar.tabBarStyle = .nonScrollable
        tabBar.tabBarCenteringStyle = .never
        tabBar.tabItemsInterimSpace = 10
        
        //        tabBar.tabBarLineStyle = .auto
        tabBar.frame.size.width = 180
        tabBar.frame.size.height = 30
        
        anotherview.addSubview(tabBar)
        
        tabBar.translatesAutoresizingMaskIntoConstraints = false
        let horizontalConstraint = tabBar.centerXAnchor.constraint(equalTo: anotherview.centerXAnchor, constant: 5.0)
        let verticalConstraint = tabBar.centerYAnchor.constraint(equalTo: anotherview.centerYAnchor)
        NSLayoutConstraint.activate([horizontalConstraint, verticalConstraint])
    }
}

@ahsanaasim
Copy link
Author

Interestingly, when I came from background, everything gets added as expected when using AppSnackBarController.

@OrkhanAlikhanov
Copy link
Contributor

OrkhanAlikhanov commented Oct 6, 2019

Which controller is the parent of homeSnackBarController?


PRO TIP:
This:

self.topView.addSubview(containerView)
containerView.translatesAutoresizingMaskIntoConstraints = false
let leftConstraint = containerView.leftAnchor.constraint(equalTo: topView.leftAnchor)
let rightConstraint = containerView.rightAnchor.constraint(equalTo: topView.rightAnchor)
let horizontalConstraint = containerView.centerXAnchor.constraint(equalTo: topView.centerXAnchor)
let verticalConstraint = containerView.centerYAnchor.constraint(equalTo: topView.centerYAnchor)
NSLayoutConstraint.activate([leftConstraint, rightConstraint, horizontalConstraint, verticalConstraint])

Can be replaced by:

topView.layout(containerView)
  .leftRight() /// same as .left().right()
  .center() /// same as .centerX().centerY()

Learn more at #1185

@ahsanaasim
Copy link
Author

Thanks for the PRO TIP.

This is how I added homeSnackBarController inside my Tabbar.

let tabBarController = Tabber()
        // Do any additional setup after loading the view, typically from a nib.
        
        tabBarController.viewControllers = [homeSnackBarController, quranSnackBarController, prayerNavigationController, duaSnackBarController]

Tabber Class:

import UIKit

@objc class Tabber: UITabBarController {
    
    override func viewDidLoad() {
        super.viewDidLoad()
        delegate = self
    }
    
    @objc func set(selectedIndex index : Int) {
        _ = self.tabBarController(self, shouldSelect: self.viewControllers![index])
    }
}

extension Tabber: UITabBarControllerDelegate  {
    func tabBarController(_ tabBarController: UITabBarController, shouldSelect viewController: UIViewController) -> Bool {
        
        guard let fromView = selectedViewController?.view, let toView = viewController.view else {
            return false // Make sure you want this as false
        }
        
        if fromView != toView {
            UIView.transition(from: fromView, to: toView, duration: 0.1, options: [.transitionCrossDissolve], completion: nil)
        }
        
        return true
    }
}

@daniel-jonathan
Copy link
Member

@ahsanaasim @OrkhanAlikhanov is this still an issue?

@ahsanaasim
Copy link
Author

I solved using another navigation controller above appSnackbar which i think is a bad solution..Cuz in that case I have to use two navigationController.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Development

No branches or pull requests

4 participants
@daniel-jonathan @OrkhanAlikhanov @ahsanaasim and others