Views added using addsubviews are not working inside SnackbarController
ahsanaasim opened this issue · 5 comments
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
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
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])
}
}
Interestingly, when I came from background, everything gets added as expected when using AppSnackBarController.
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
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
}
}
@ahsanaasim @OrkhanAlikhanov is this still an issue?
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.