MMDrawerController
MMDrawerController copied to clipboard
Left/Right drawer content view jumps on initial opening (since iOS 8)
Hey,
first of all thank you for providing this great code as open source. I have an issue that only occurs since iOS 8.
I am using the drawer controller as follows:
MMDrawerController *drawerController = [[MMDrawerController alloc] initWithCenterViewController:[menuViewController.viewControllers objectAtIndex:0] leftDrawerViewController:menuNavigationController];
drawerController.showsShadow = NO;
drawerController.openDrawerGestureModeMask = MMOpenDrawerGestureModeAll;
drawerController.closeDrawerGestureModeMask = MMCloseDrawerGestureModeAll;
drawerController.maximumLeftDrawerWidth = 268.0;
[drawerController setDrawerVisualStateBlock:[MMDrawerVisualState parallaxVisualStateBlockWithParallaxFactor:2.0]];
drawerController.animationVelocity = 1260.0;
"menuNavigationController" is simply a UINavigationController object with a UITableViewController as its root view controller.
Then, in the center view I have another UINavigationController containing a UITableViewController. In this center view, I use the drawer bar button item to toggle the drawer position with this statement:
[self.mm_drawerController toggleDrawerSide:MMDrawerSideLeft animated:YES completion:nil];
When I do this in iOS 8 for the first time after launch the UITableView cells in the left view first start under the navigation bar (so the first cell is not fully visible) and when the toggle animation is completed they drop down to start below the navigation bar without animation. It looks as if the view controller notices after the view did appear that it has a navigation bar and the content view must start below it.
This does not occur in iOS 7 and it does not occur when the drawer is toggled using a gesture instead of a button or when the drawer is toggled with a button after the initial time.
Any help will be much appreciated.
I can confirm this behavior as well. iOS 8 GM, XCode 6.0.1.
I confirm as well. Same behavior.
same here.
Same behavior.
Happens here too.
I have the same issue, has anyone figured out how to fix that?
Seeing it too.. and investigating..
I'm seeing this too. Does anybody know what's happening? My first thought was that it was being offset by the height of the status bar (which I remove) but I haven't looked properly yet.
"ostatnicky" posted a solution about turning off the navigation bar´s translucency. I received a mail notification, but it is strangely enough not visible in the thread. Anyway, it works for me too...
self.navigationController.navigationBar.translucent = NO;
I removed that because in my project it doesn't work. But I have there ViewDeck, maybe for MMDrawerController it will work. For demo it does.
self.navigationController.navigationBar.translucent = NO;
works for me too. Thanks for posting it guys!
However, this is rather a workaround as you might want a translucent nav bar. So it would be better to find a complete fix in the future.
self.navigationController.navigationBar.translucent = NO; This solution is works for me too.
Thanks, This only solves the problem when the navigation bar is set to visible. Try setting
[self.navigationController.navigationBar setHidden:TRUE];
The menu still pops down after the animation completes. Any other ideas?
Not sure if others were having exactly the same problem as me. However I can report that I fixed my issue by setting the self.showsStatusBarBackgroundView
property to true
, and also modifying my custom navigation bar to work differently. My custom navigation bar originally altered its height dependent on the status bar (which can appear or disappear dependent on the child drawers) in order that it always remained the same height with or without the status bar - I ended up requiring a negative status bar height offset if the former property was true.
@sebinsua Okay, thanks for your input. To clarify: I and I think most of the others here just use the default setup with a navigation controller with a content table view controller on the left drawer side without modifying the status bar behaviour, in my case it is always visible. So on the left side I have a status bar, nav bar and table view, very similar to the sample project I think. And the problem is that our table view jumps from below the status bar to below the nav bar after the toggle animation is completed while it should already be there in the first place.
To clarify at all: self.navigationController.navigationBar.translucent = NO;
works only if you have top bar in side view controller. I don't have it there and view still jumps :(
If I set the setShowsStatusBarBackgroundView
to YES
it works as expected. But I can't use this because I want a transparent status bar.
After digging a bit into the method code of setShowsStatusBarBackgroundView
the line that fixes this issue is frame.size.height = CGRectGetHeight(self.view.bounds)-20;
So setting the frame height on the childControllerContainerView
does influence this. I hope this research helps a bit.
I have the navigation bars hidden in my left & right drawers and also had this issue with the drawers jumping down in iOS8
Worked around this issue by changing the following during the set up of my drawers
self.leftDrawerViewController.navigationController.navigationBar.navigationBarHidden = NO; // used to be YES
Then in leftDrawerViewController's viewWillAppear: method, setting:
self.navigationController.navigationBarHidden = YES;
Just tested my work around with translucent navigation bars and it also works
Set leftSideNavController.navigationBar.translucent = NO;
during initialisation
Then in leftDrawerViewController's viewWillAppear: method set:
self.navigationController.navigationBar.translucent = YES;
@fraserscottmorrison Your workaround pointed me to a solution that works for me as well.
I set self.navigationController.navigationBar.translucent = NO;
in my leftDrawerViewController's viewDidLoad
method.
Then I set it back to self.navigationController.navigationBar.translucent = YES;
in the viewWillAppear
of the same leftDrawerViewController.
I have two navigation controllers (centre and right). Unfortunately none of the above solutions seem to work.
Setting setShowsStatusBarBackgroundView to YES on iOS7 causes the initial view to jump upwards when it first gets displayed. Whereas it's fine on iOS8.
Or if I try the self.navigationController.navigationBar.translucent = YES | NO approach it still behaves the same as that described by the initial poster of this issue.
Any suggestions?
I had the same issue. MMDrawerController manually forwards appearance callbacks and in iOS8 it causes some issues. I fixed this by the following code in MMDrawerController:
-(void)openDrawerSide:(MMDrawerSide)drawerSide animated:(BOOL)animated velocity:(CGFloat)velocity animationOptions:(UIViewAnimationOptions)options completion:(void (^)(BOOL))completion{
NSParameterAssert(drawerSide != MMDrawerSideNone);
UIViewController * sideDrawerViewController = [self sideDrawerViewControllerForSide:drawerSide];
CGRect visibleRect = CGRectIntersection(self.view.bounds,sideDrawerViewController.view.frame);
BOOL drawerFullyCovered = (CGRectContainsRect(self.centerContainerView.frame, visibleRect) ||
CGRectIsNull(visibleRect));
BOOL is8Workaround = [[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0;
if(drawerFullyCovered)
{
[self prepareToPresentDrawer:drawerSide animated:animated];
if (is8Workaround)
{
[sideDrawerViewController endAppearanceTransition];
[sideDrawerViewController beginAppearanceTransition:YES animated:animated];
}
}
if(sideDrawerViewController){
CGRect newFrame;
CGRect oldFrame = self.centerContainerView.frame;
if(drawerSide == MMDrawerSideLeft){
newFrame = self.centerContainerView.frame;
newFrame.origin.x = self.maximumLeftDrawerWidth;
}
else {
newFrame = self.centerContainerView.frame;
newFrame.origin.x = 0-self.maximumRightDrawerWidth;
}
CGFloat distance = ABS(CGRectGetMinX(oldFrame)-newFrame.origin.x);
NSTimeInterval duration = MAX(distance/ABS(velocity),MMDrawerMinimumAnimationDuration);
[UIView
animateWithDuration:(animated?duration:0.0)
delay:0.0
options:options
animations:^{
[self.centerContainerView setFrame:newFrame];
[self updateDrawerVisualStateForDrawerSide:drawerSide percentVisible:1.0];
}
completion:^(BOOL finished) {
//End the appearance transition if it already wasn't open.
if(drawerSide != self.openSide)
{
[sideDrawerViewController endAppearanceTransition];
}
[self setOpenSide:drawerSide];
[self resetDrawerVisualStateForDrawerSide:drawerSide];
if(completion){
completion(finished);
}
}];
}
}
Still suffering from the same issue. Do not have a navigation controller in my left drawer. Have a SearchBar + UITableView which jumps down on iOS 8 whenever i click on the Search bar or dropdown Header of my tableview. Strangely it does not jump down when I select any of the normal cells.
If only I could find out what is getting called when the Search bar or dropdown Header is being clicked, maybe I could do the same when the in the viewWillAppear section of the Left drawer View Controller.
I'm also facing a similar issue. Same as @vijaytholpadi, I have a SearchBar and UITableView but my issue is when I first open the drawer, my table cells flicker and the width of the cell extends (sort of snaps into place) as the drawer is sliding. This also only happens during the first time it the drawer is opened.
just an update, I think this happens because of the parallax effect. is anyone using that and seeing the same table cell shift?
@huangc10 I am using the parallax effect as well. I remove the effect but the shift still occurs.
For my particular case, it seems to happen when the left/right side controller contains a Top Layout Guide, somehow the guid screws up the layout. Moving the side controller view outside of my storyboard into a dedicated nib fixed the problem.
Ps. XCode 7.0.1
I found a solution which works if you want a "transparent" status bar and you have a search bar in your sideController.
Just add 2 lines of code after drawerController declaration:
drawerController.showsStatusBarBackgroundView = YES;
drawerController.statusBarViewBackgroundColor = /* UIColor of sideController background */;
Works fine for me.
I have the same isue in Xcode 7.2. Had someone a solution for Swift - iOS 9.2?? :(
I was having the same issue without a navigation controller and the status bar didn't help me out. @andyzaharia said that the top layout guide was messing it up, so what I did was make sure my constraints were not relative to the top margin but to the top itself. That fixed it in my case.