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

Extend popup bar past safe insets #392

Closed
nfiacco opened this issue Aug 8, 2020 · 27 comments
Closed

Extend popup bar past safe insets #392

nfiacco opened this issue Aug 8, 2020 · 27 comments
Labels

Comments

@nfiacco
Copy link

nfiacco commented Aug 8, 2020

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!

@LeoNatan
Copy link
Owner

LeoNatan commented Aug 9, 2020

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.

@LeoNatan
Copy link
Owner

LeoNatan commented Aug 9, 2020

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.

@property (nullable, nonatomic, strong, readonly) __kindof UIView* bottomDockingViewForPopupBar;

@nfiacco
Copy link
Author

nfiacco commented Aug 9, 2020

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.

@LeoNatan
Copy link
Owner

LeoNatan commented Aug 9, 2020

You need to add the visual effect view as a sub view of your controller’s 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’s 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).

@LeoNatan
Copy link
Owner

LeoNatan commented Aug 9, 2020

If you are not familiar with Objective C when reading the header files, you can look at the generated Swift interface in Xcode.

@nfiacco
Copy link
Author

nfiacco commented Aug 9, 2020

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 :)

@LeoNatan
Copy link
Owner

LeoNatan commented Aug 9, 2020

As I said, you shouldn’t 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.

@LeoNatan
Copy link
Owner

LeoNatan commented Aug 9, 2020

To match the visual effect blur style to that of the popup, use the chrome material.

@nfiacco
Copy link
Author

nfiacco commented Aug 9, 2020

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?

@LeoNatan
Copy link
Owner

LeoNatan commented Aug 9, 2020

You should be adding this to the view of the controller which presents the popup bar, not the content view.

@nfiacco
Copy link
Author

nfiacco commented Aug 9, 2020

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?

@LeoNatan
Copy link
Owner

LeoNatan commented Aug 9, 2020

Are you able to subclass the navigation controller? If so, there shouldn’t be a problem adding a view.

@iDevelopper
Copy link
Contributor

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.

@LeoNatan
Copy link
Owner

LeoNatan commented Aug 9, 2020

@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.

@iDevelopper
Copy link
Contributor

iDevelopper commented Aug 9, 2020

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.

@iDevelopper
Copy link
Contributor

If I do not implement bottomDockingViewForPopupBar, the visual effect view acte like a bottom bar too.

@LeoNatan
Copy link
Owner

LeoNatan commented Aug 9, 2020

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
	}
}

@LeoNatan LeoNatan closed this as completed Aug 9, 2020
@LeoNatan
Copy link
Owner

LeoNatan commented Aug 9, 2020

@nfiacco See above. This behaves exactly as you expect.

@nfiacco
Copy link
Author

nfiacco commented Aug 9, 2020

Yes that did it for me, thank you so much!!!

@iDevelopper
Copy link
Contributor

Behave like a bottom bar, and not working on UIViewController (without navigation controller).

@LeoNatan
Copy link
Owner

Why not? It should be the same.

@iDevelopper
Copy link
Contributor

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;
}

@LeoNatan
Copy link
Owner

That's odd.

@iDevelopper
Copy link
Contributor

iDevelopper commented Aug 10, 2020

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.

@LeoNatan
Copy link
Owner

If you find a bug, open a new issue please.

@iDevelopper
Copy link
Contributor

Ok, I will open and another issue but this bug has a lot to do with this one.

@LeoNatan
Copy link
Owner

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.

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

No branches or pull requests

3 participants