I have added a collectionView on top of a UITabBar but its touch is not working.The screeshot for the tabBar and collectionView
The code is attached below, I want the collectionView to be touchable. Here quickAccessView is the UIView that contains the collectionView. For constraints I'm using snapKit
override func viewWillLayoutSubviews() {
super.viewWillLayoutSubviews()
self.tabBar.bringSubviewToFront(quickAccessView)
}
private func setupQuickAccessView(){
print("this is tabBar's height", self.tabBar.frame.size.height)
self.tabBar.frame.size.height = 150
print("this is new tabBar's height", self.tabBar.frame.size.height)
self.tabBar.addSubview(quickAccessView)
quickAccessView.clipsToBounds = true
}
private func addQuickAccessViewConstraints(){
quickAccessView.snp.makeConstraints { make in
make.right.left.equalTo(self.tabBar.safeAreaLayoutGuide)
make.height.equalTo(76)
make.bottom.equalTo(self.tabBar.snp.bottom).offset(-80)
}
}
this is after modification that Aman told The UITabBarController
final class MainTabBarController: UITabBarController {
private lazy var quickAccessView: QuickAccessView = .fromNib()
var quickAccessSupportedTabBar: QuickAccessSupportedTabBar {
self.tabBar as! QuickAccessSupportedTabBar // Even code is crashing here
}
// Even code is crashing here
override func viewDidLoad() {
super.viewDidLoad()
self.tabBar.backgroundColor = .white
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
self.view.frame = self.quickAccessView.bounds
setupUI()
}
}
extension MainTabBarController{
private func setupUI(){
setupQuickAcessView()
addQuickAcessViewConstraints()
}
}
// MARK: - Setting Up Quick Access view
extension MainTabBarController {
private func setupQuickAcessView(){
self.quickAccessSupportedTabBar.addSubview(quickAccessView)
}
private func addQuickAcessViewConstraints(){
quickAccessView.snp.makeConstraints { make in
make.left.right.equalTo(self.quickAccessSupportedTabBar.safeAreaLayoutGuide)
make.height.equalTo(66)
make.bottom.equalTo(self.quickAccessSupportedTabBar.snp.top)
}
}
}
the UItabBar and here it is throwing error and I too am confuse that how to access it and convert it to points
class QuickAccessSupportedTabBar: UITabBar {
override public func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
// if `quickAccessView` is visible, then convert `point` to its coordinate-system
// and check if it is within its bounds; if it is, then ask `quickAccessView`
// to perform the hit-test; you may skip the `isHidden` check, in-case this view
// is always present in your app; I'm assuming based on your screenshot that
// the user can dismiss / hide the `quickAccessView` using the cross icon
if !quickAccessView.isHidden {
// Convert the point to the target view's coordinate system.
// The target view isn't necessarily the immediate subview
let targetPoint = quickAccessView.convert(point, from: self)
if quickAccessView.bounds.contains(targetPoint) {
// The target view may have its view hierarchy, so call its
// hitTest method to return the right hit-test view
return quickAccessView.hitTest(targetPoint, with: event)
}
}
// else execute tabbar's default implementation
return super.hitTest(point, with: event)
}
}
I think what may be happening here is that since you've added quickAccessView
as tab bar's subview, it is not accepting touches. This would be so because the tabbar's hist test will fail in this scenario.
To get around this, instead of using a UITabBar, subclass UITabBar, let us call it ToastyTabBar
for reference. See the code below:
class ToastyTabBar: UITabBar {
override public func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
// if `quickAccessView` is visible, then convert `point` to its coordinate-system
// and check if it is within its bounds; if it is, then ask `quickAccessView`
// to perform the hit-test; you may skip the `isHidden` check, in-case this view
// is always present in your app; I'm assuming based on your screenshot that
// the user can dismiss / hide the `quickAccessView` using the cross icon
if !quickAccessView.isHidden {
// Convert the point to the target view's coordinate system.
// The target view isn't necessarily the immediate subview
let targetPoint = quickAccessView.convert(point, from: self)
if quickAccessView.bounds.contains(targetPoint) {
// The target view may have its view hierarchy, so call its
// hitTest method to return the right hit-test view
return quickAccessView.hitTest(targetPoint, with: event)
}
}
// else execute tabbar's default implementation
return super.hitTest(point, with: event)
}
}
Set this as the class of your tabBar
(both in the storyboard and the swift file), and then see if that solves it for you.
You'll have to figure out a way to make quickAccessView
accessible to the tabbar for the hit test check. I haven't advised on that above because I'm not familiar with your class hierarchy, and how and where you set stuff up, but this should be trivial.
If this solves it for you, please consider marking this as the answer, and if it does not then please share a little more info here about where you're having the problem.
Edit (for someone using a UITabBarController
):
In response to your comment about "how to access UITabBar class from UITabBarController" here's how I would go about it.
I'm assuming you have a storyboard with the UITabBarController
.
The first step (ignore this step if you already have a UITabBarController
custom subclass) is that you need to subclass UITabBarController
. Let us call this class ToastyTabBarController
for reference. Set this class on the UITabBarController
in your storyboard using the identity inspector pane in xcode.
The second step is to set the class of the UITabBar
in your storyboard as ToastyTabBar
(feel free to name it something more 'professional' 😊).
This is to be done in the same storyboard, in your UITabBarController
scene itself. It will show the tabBar under your UITabBarController
, and you can set the custom class on it using the identity inspector pane just like earlier.
The next step is to expose a computed property on your custom UITabBarController
class, as shown below.
var toastyTabBar: ToastyTabBar {
self.tabBar as! ToastyTabBar
}
And that's it. Now you have a property on your UITabBarController subclass which is of ToastyTabBar
type and you can use this new property, toastyTabBar
, however you require.
Hope this helps.