I can't figure out how to extend the popup bar past the safe insets. I tried looking through other issues but didn't understand your proposed solution of adding a new view to dock to. Any help would be awesome!
Hello,
Could please describe in more detail what you are trying to accomplish?
As a general rule, one should always present the bar on the deepest view controller in the hierarchy, usually a tab bar controller or a navigation controller.
If you have a mere view controller, and would like to have the bar extend below the safe area, you can accomplish this by adding a visual effect view under the safe area, use the provided API to return that visual effect view as the bottom docking view, and return the correct frame.
Thanks for the quick response! I've been trying to figure out how to add a visual effect view under the safe area like you said. But being rusty with iOS development, I'm not exactly sure how to do that. Am I supposed to add it programmatically to the view controller passed to presentPopupBar?
I vaguely understand I want a UIVisualEffectsView, but not sure where to create it and how to place it under the safe area.
You need to add the visual effect view as a sub view of your controller鈥檚 view, and position it under the bottom safe area. I think there is an issue with using autolayout (constraints), so I recommend positioning this view in your controller鈥檚 viewDidLayoutSubviews. This might be enough for you, or you can go an extra step to make it even better. Implement the two property getters linked above, one returning the visual effect as the bottom docking view, and the other returning the position of the view when the popup bar is closed (it should be the same frame as you set the view in viewDidLayoutSubviews).
If you are not familiar with Objective C when reading the header files, you can look at the generated Swift interface in Xcode.
Does this seem correct for setting up the visual effect:
var bottomView = UIVisualEffectView(effect: UIBlurEffect(style: .regular))
...
override func viewWillLayoutSubviews() {
if #available(iOS 11.0, *) {
self.bottomView.bounds.size.height = self.view.safeAreaInsets.bottom
self.bottomView.bottomAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.bottomAnchor).isActive = true
self.view.addSubview(self.bottomView)
}
}
And thanks so much for your help with this-- I def needed a lot of help with this one :)
As I said, you shouldn鈥檛 use constraints. Just set the frame of the view directly.
Also, creating constraints in this method is a bad idea, as it is called multiple times.
To match the visual effect blur style to that of the popup, use the chrome material.
Ok I'm trying to set the view position using frame.origin.y but it's still not displaying. I'm adding this in the popupContentView, which may not be correct since that view is only visible when the popup bar is clicked?
You should be adding this to the view of the controller which presents the popup bar, not the content view.
Oh so one weird thing about my implementation is that I'm presenting the popup bar via a navigation view controller that isn't directly tied to any child views or have any view of its own. Will adding a subview still work?
Are you able to subclass the navigation controller? If so, there shouldn鈥檛 be a problem adding a view.
Sorry, I think it can't work because the visual effect view will stay at the bottom when opening the popup content view, and its behavior will be like a bottom bar, as it is not attached to the popup bar.
@iDevelopper That's not true. If you implement bottomDockingViewForPopupBar and return the visual effect view, that will become the bottom bar of the popup bar.
I did implement it in your demo project. the visual effect view become the bottom bar as I said and behave like a bottom bar. But returning another view, not the visual effect view because in this case the popup bar itself is not displayed.
If I do not implement bottomDockingViewForPopupBar, the visual effect view acte like a bottom bar too.
Here is a quick implementation that works well:
import UIKit
import LNPopupController
class MyNavViewController: UINavigationController {
private let visualEffectView = UIVisualEffectView(effect: UIBlurEffect(style: .systemChromeMaterial))
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(visualEffectView)
presentPopupBar(withContentViewController: UIViewController(), animated: true, completion: nil)
}
override func viewWillLayoutSubviews() {
visualEffectView.frame = defaultFrameForBottomDockingView
view.bringSubviewToFront(visualEffectView)
super.viewWillLayoutSubviews()
}
override var bottomDockingViewForPopupBar: UIView? {
return visualEffectView
}
override var defaultFrameForBottomDockingView: CGRect {
return CGRect(x: 0, y: view.bounds.height - view.safeAreaInsets.bottom, width: view.bounds.width, height: view.safeAreaInsets.bottom)
}
override var insetsForBottomDockingView: UIEdgeInsets {
return .zero
}
}
@nfiacco See above. This behaves exactly as you expect.
Yes that did it for me, thank you so much!!!
Behave like a bottom bar, and not working on UIViewController (without navigation controller).
Why not? It should be the same.
Yes! Got it. Sorry.
Need to set the defaultFrameForBottomDockingView with the bottom inset of the superview in this case, if not the visualEffectView height becomes equal to 98 when the popup bar is presented (34 + 64).
- (CGRect)defaultFrameForBottomDockingView
{
UIViewController *targetVC = [self _targetVCForPopup];
UIEdgeInsets insets = targetVC.view.superview.safeAreaInsets;
CGRect frame = CGRectMake(0, targetVC.view.bounds.size.height - insets.bottom, targetVC.view.bounds.size.width, insets.bottom);
return frame;
}
That's odd.
I've found another issue. Do not use the visual effect view at all, neither the bottom docking view.
Just set the navigation controller toolbar hidden.
- (UIViewController*)_targetVCForPopup
{
UIViewController* targetVC = self.navigationController == nil ? self.splitViewController != self.view.window.rootViewController ? self.splitViewController : nil : nil;
if(targetVC == nil)
{
targetVC = self.tabBarController;
if(targetVC == nil)
{
targetVC = self.navigationController;
if(targetVC == nil)
{
targetVC = self;
}
else {
[self.navigationController setToolbarHidden:YES];
}
}
}
return targetVC;
}
The toolbar is not completely hidden.
And test with the drag option to open the popup content view.
If you find a bug, open a new issue please.
Ok, I will open and another issue but this bug has a lot to do with this one.
I'm working on implementing this natively. Already have it working for UIViewController and UINavigationController. Will have support for UITabBarController soon, as well as final polishing. It will be on by default, with the ability of the user to disable.