UI glitch (black flicker) on right side of navbar during transition - ios

I have an app that has a uipageviewcontroller that is presented on initial launch of the app. On the last page of the uipageviewcontroller I present the main navigation controller with a TransitionCrossDissolve animation.
While the animation is ongoing I get a tiny black background flicker on the right side of the navigation bar like this:
In the beginning I had the black flicker on the whole navigation bar, but after calling
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
self.navigationController?.navigationBar.layer.removeAllAnimations()
}
the problem almost went away.
Her is a gif of the problem before calling removeAllAnimations():
This i how I call for the animation on the last page of the uipageviewcontroller:
let appDelegate = UIApplication.sharedApplication().delegate as AppDelegate
UIView.transitionWithView(appDelegate.window!, duration: 0.5, options: UIViewAnimationOptions.TransitionCrossDissolve , animations: { () in
appDelegate.window!.rootViewController = appDelegate.mainNavigationController
}, completion: nil)
It may be important to not that I am using a procedure to remove the hairline at the bottom of the navbar. May this be the reason for all of this?
Ref:
How to hide iOS7 UINavigationBar 1px bottom line
I would greatly appreciate any feedback on the issue.
Brgds

I was able to remove the black UI glitch by removing the animation on all subviews of the navigationbar. I think the problem was with the right UINavigationItem.
Here is the code I used:
let subviews = (self.navigationController?.navigationBar.subviews as [UIView])
for subview: UIView in subviews {
subview.layer.removeAllAnimations()
}

Related

IOS Tab Bar Sliding

I'm trying to make tab bar with sliding (or may be swipe is right word?) effect of changing ViewControllers.
I create two ViewControllers with TableView on whole screen, but with restrictions - top edge of table not overlap top layout guide.
I link this ViewControllers with TabBarController and when I use default animation - it's OK, work fine. But I want sliding animation and do something like (swift3):
func tabBarController(_ tabBarController: UITabBarController, shouldSelect viewController: UIViewController) -> Bool {
animateSliding(fromController: selectedViewController, toController: viewController)
return true
}
func animateSliding(fromController: UIViewController?, toController: UIViewController?) {
let fromView: UIView = fromController!.view;
let toView: UIView = toController!.view;
fromView.superview?.addSubview(toView);
toView.frame.origin.x = UIScreen.main.bounds.size.width;
UIView.animate(withDuration: 0.3,
animations: {
toView.frame.origin.x = 0;
fromView.frame.origin.x -= UIScreen.main.bounds.size.width;
},
completion: nil);
}
(it's not complete animation, just sample)
Now I have animation I wanted but second's ViewController's table overlap top guide when appear (when slide over first viewController). If I change position ViewControllers in TabBar (first became second and second became first) situation change - not first controller's table overlap top guide (when appear)
Have you tried XLPagerTabStrip? I believe that it is pretty similar to what you want to achive.
If not, you can base your code in that implementation.

Black screen at bottom in landscape mode when dismiss keyboard IQKeyboardManager

I am using the IQKeyboardManagerSwift latest version I am having issue black screen at bottom --> When I tap on text field in landscape mode of device keyboard comes up and view of controller and background image goes up black screen of window can be seen at bottom View does not come back to original position after keyboard dismiss.
I want to move container view of the text field up, not the view of the controller and background image, the container view is horizontally and vertically center in auto layout. I tried to add IQLayoutGuideConstraint to container view but no luck. it would be great if you can provide some information to achieve it. please seen storyboard screenshot below
try to remove your firstResponder from viewDidLoad, and put it in viewDidAppear instead, like this
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(true)
yourTextField.becomeFirstResponder()
}
P.S. Do not set your textfield as firstResponder in your viewController.
For ex:- (in ViewDidLoad Method)
[self.yourTextField becomeFirstResponder];
If you have above set up. Please comment(Delete) this line and then try.
All the best.
Have you tried to update your pods?
pod IQKeyboardManagerSwift
workround, place in your VC viewillappear:
override func viewWillAppear(_ animated: Bool) {
if let window = (UIApplication.shared.delegate?.window)! as UIWindow? {
window.backgroundColor = UIColor.white
}
}

hide NavigationBar without lifting up the View

hiding my NavigationBar with this :
func hideAndShow(){
if self.navigationController?.navigationBar.hidden == true {
self.navigationController?.setNavigationBarHidden(false, animated: true)
}else {
self.navigationController?.setNavigationBarHidden(true, animated: true)
}
}
but its also lifting up my View (maybe because View is below the Navigation), how can i hide it without lifting up my View
see the below image for better understanding
as you can see that my image in my view also get shifted up while hiding the NavigationBar any idea how can i fix this ??
can we just show the view below the layer of navigation bar ???
Two steps are required to solve your problem:
Add self.edgesForExtendedLayout = UIRectEdge.All to viewWillAppear. As a result your view will start at the top of the screen instead of below the NavigationBar. You can read more about edgesForExtendedLayout here: https://stackoverflow.com/a/19585104/1447641
Add a top constraint of {navigationbarheight} to your ImageView.
After that the position of the ImageView shouldn't be effected by the NavigationBar anymore.

Make UINavigationBar transparent animated during transition

I can do translucent UINavigationBar transparent using this code:
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
navigationController!.navigationBar.setBackgroundImage(UIImage(), forBarMetrics: .Default)
navigationController!.navigationBar.shadowImage = UIImage()
}
But if you try this, you'll notice bad effect during push animation transition. Navigation bar becomes transparent immediately, before left screen completely disappears.
But on the other side, if you try this code....
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
navigationController!.setNavigationBarHidden(true: animated: animated)
}
... animation will be perfect: navigation bar disappears only on the right screen, so transition animation looks good.
Is there any way to make UINavigationBar transparent like in the first snippet with animation effect like in the second snippet?
yes, you need to make a method in your code which makes a delay for how many seconds your app is opened for example: [self performSelector:#selector(delay) withObject:nil afterDelay:5.0]; this would make when your app opens, after 5 seconds it will run everything you put in the delay method. So, I would find the second or mess around when you want the UINavigationBar to be transparent and you could easily find the code to make the UINavigationBar transparent but I don't know it off the top of my head.

Toolbar incorrectly positioned during push animation with hidesBottomBarWhenPushed

I have an App using a Tabbar for basic Navigation. From one of the screens of the Tabbar I want to enter another one that shows a toolbar instead of the Tabbar and a back navigation item on the top.
What is the best way to do this? If I use "Hide Bottom Bar on Push" (aka hidesBottomBarWhenPushed) and add a Toolbar to the screen I can see an animation removing the Tabbar before the Toolbar is placed at the bottom of the screen.
Solution for UITableViewController with toolbar (requires code)
Using code from this answer, I was able to achieve the same effect, but with the toolbar at the bottom of a table view.
Add this to your table view controller:
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[self.navigationController setToolbarHidden:NO animated:YES];
}
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
[self.navigationController setToolbarHidden:YES animated:YES];
}
Important note: placing these calls in viewWillAppear and viewWillDisappear instead of viewDidLoad makes this easier to handle, as it will work reliably even for multiple pushes and pops of the same view controller, and you won't have to clean up after it in the previous view controller.
And configure it like this in the storyboard:
Also, enable Hides bottom bar when pushed in the storyboard, or in your code, for the view controller being pushed.
Then you can add toolbar buttons to the toolbar in the storyboard.
Build and run, and you get this effect:
Here's a complete sample project demonstrating this.
Problem Example
Here is my solution,
In the first view controller that has the tabbar do this
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "someSegue" {
if let secondVC = segue.destinationViewController as? InfoTableViewController {
secondVC.hidesBottomBarWhenPushed = true
}
}
}
I also needed this, as my toolbar would re appear in the first VC.
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
navigationController?.toolbarHidden = true
}
To stop the fade up animation of the toolbar, so its just there i used this in the second VC
override func viewDidLoad() {
super.viewDidLoad()
navigationController?.toolbarHidden = false
}
Pure storyboard solution
If you're referring to the issue of the toolbar appearing above the tab bar during the push transition animation, I was able to fix this by adjusting the auto layout constraints on the toolbar in the storyboard (add it manually to your view controller; see my other answer if you're using a UITableViewController or UICollectionViewController and can't do this):
Add a constraint to set the distance to the bottom layout guide to zero:
Double click that constraint to edit it, and set the first item to Bottom (it will be Top by default).
All done! This will result in an effect like this:
Here's my sample project that demonstrates this working as expected. Note that I didn't change any of the code, everything is in the storyboard.
As of Xcode 7, the pure Storyboard solution doesn't work anymore because Xcode wouldn't let you assign the Bottom attribute to the Bottom Layout Guide anymore.
For my project, I used the following setup:
A UITabBarController as initial view controller, going into a
UINavigationController, with root vc set to...
UIRegularViewController, which should behave normally, but spawn a...
UISpecialViewController, which should hide the tab bar and instead display a toolbar. Also, it should hide the status bar, the navigation bar and the tool bar on tap.
Here is what I did to achieve this:
In the storyboard
UITabBarController: set Tab Bar Translucency to NO
UISpecialViewController: Set Simulated Metrics like so
Status Bar: None
Top Bar: Opaque Nav Bar
Bottom Bar: Opaque Toolbar
Set Extended Edges like this:
Under Top Bars: NO
Under Bottom Bars: YES
Under Opaque Bars: YES
Do not drag a UIToolBar into UISpecialViewController !
In the Implementations
// in UISpecialViewController.m
- (void)viewWillAppear:(BOOL)animated {
self.navigationController.toolbarHidden = NO;
self.navigationController.hidesBarsOnTap = YES;
}
- (void)viewWillDisappear:(BOOL)animated {
self.navigationController.toolbarHidden = YES;
self.navigationController.hidesBarsOnTap = NO;
}
- (BOOL)prefersStatusBarHidden {
return self.navigationController.navigationBarHidden;
}
Here is the Demo Code.
This is the result:
In fact, UIKit has already configured how Toolbar and Tabbar change in the page switching animation.
I also have this situation with you today, and the final solution surprised me.
For example, page A to page B, page A displays Tabbar, not Toolbar, page B does not display Toolbar, and does not display Tabbar.
At this time, B needs to set hidesBottomBarWhenPushed to true, which is necessary.
Then, in the declaration cycle of the two ViewControllers, in the viewWillDisappear of A and the viewWillAppear of B, if you set the navigation controller setToolbarHidden, this animation problem will occur.
If you set it in viewDidDisappear of A and viewDidAppear of B, the problem is solved. Although the toolbar will have a delayed animation, it is always better than the wrong animation.
Finally add:
The order of A and B life cycle function calls is:
A - viewWillDisappear
B - viewWillAppear
A - viewDidDisappear
B - viewDidAppear
These four methods are interleaved.
Using Xcode 12.4 iOS 14.4
for those who struggle with this issue and try solutions above with no luck.
let's say A is with tabBar only, B is only showing toolbar
remember to set hidesBottomBarWhenPushed = true in B's init
override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
hidesBottomBarWhenPushed = true
}
implement these below in B. (no need to do anything in A)
override func viewDidLoad() {
super.viewDidLoad()
navigationController?.setToolbarHidden(true, animated: false)
}
override func viewWillLayoutSubviews() {
super.viewWillLayoutSubviews()
navigationController?.setToolbarHidden(false, animated: false)
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
navigationController?.setToolbarHidden(true, animated: true)
}
that's it!!
p.s. if you want to remove the toolbar animation from bottom up then add this
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
navigationController?.toolbar.layer.removeAnimation(forKey: "position")
}

Resources