My ViewController WITH Large Navigation Bar Scrollers up automatically After loading WKWebView - ios

In my app, I am loading about the page in a view controller with a WebKit WebView, and Viewcontroller has a Large Navigation Controller. At time of view DidLoad Large navigation bar is shown fine.
At this point when I start loading my WebView with a local HTML file.
After loading this WebView, without any user interaction, ViewController automatically scrolls up such that navigation bar shrink to actual small-sized form.

Yes this is the default behaviour of navigation bar if you want to set large navigation bar all the time then you have to go with custom navigation bar. Create your own Navigation bar. Thanks

What will help you is the use of viewLayoutMarginsDidChange() .Using this you can check in everyview if the view size has changed and if so you can set your original navigation title size here , So instead of what i have added , parse your Navigation bar frame values below.
var didChange = false
override func viewLayoutMarginsDidChange() {
if didChange {
print("Height : - \
(self.navigationController?.navigationBar.frame.size.height)")
// set NavigationBar Height here
self.navigationController!.navigationBar.frame = CGRect(x: 0, y: 0, width:
UIScreen.main.bounds.width, height: 96.0)
didChange.toggle()
}
}

Try getting the scroll events of wkWebView.srollView in scrollViewDidScroll , see if something make it scroll.
Or , disable WKWebView.scrollView.scrollEnabled when loading the WebView and enable it back when load completes

Change the contentInsetAdjustmentBehavior property of the ScrollView of WebView to .never in your viewDidLoad method.
webView.scrollView.contentInsetAdjustmentBehavior = .never

You can try :
webView.scrollView.contentInsetAdjustmentBehaviour = .never

Related

Static/fixed Navigation Bar in iOS

I have a Navigation Controller and a Collection View under it inside my app. And there is a problem: I use large title inside my Navigation bar, so everything inside is not static. When I scroll the collection view cells, the title (I created it manually using UILabel() to move it as I want inside the navigation bar) and buttons move up and the navigation bar takes form of iOS 10 navigation bar, I mean its height. You can see it here:
The normal state of my Navigation Bar with "Prefer large titles" On:
It happens when I scroll my Collection View, everything goes up:
So the question is simple: how to make the force constant height for the navigation bar? I want it to become fixed even while scrolling. Are there any ideas? Is it possible?
And the second question, if the first is impossible: Another solution for my problem is to make the Navigation Bar with "Prefer large titles" Off bigger. I tried this code:
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
let height: CGFloat = 50 //whatever height you want to add to the existing height
let bounds = self.navigationController!.navigationBar.bounds
self.navigationController?.navigationBar.frame = CGRect(x: 0, y: 0, width: bounds.width, height: bounds.height + height)
}
but it worked only for large titles. So how can I make the navigation bar bigger?
Yes, you can make it fixed. It will not scroll if the very first view in the view hierarchy is not a CollectionView/TableView (ScrollView).
Using Storyboard/Xib:
Consider the following image where a tableView and button are added in scene. Here the navigation bar will collapse on scroll of tableView because tableView is the very first view in viewController's containerView hierarchy attached to the navigation bar.
Now to make the navigation bar fixed, if we just change the order of tableView and button as below, it will disable the collapsing of navigation bar.
To change the order of the view, you have to click, hold and move up/down.
If you have only CollectionView in this scene then you can add a placeholder view at the top and set its height to zero as below,
Programmatically:
If you are setting up view's programmatically then you just need to add a placeholder view at the top or add tableView/collection after adding other views.
e.g,
self.view.addSubview(UIView(frame: .zero))
self.view.addSubview(tableView) // or collectionView

add navigation controller to webview created programmatically swift 3

I have this code that creates a webView:
var webV:UIWebView = UIWebView(frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height))
I have the WebView did start like so:
func webView(webView: UIWebView, shouldStartLoadWithRequest request: NSURLRequest, navigationType: UIWebViewNavigationType) -> Bool {
return true
}
I have embedded a navigation controller on the view controller, which I didn't want to do, because I only want the navigation to show on the webview, but oh well.
The problem is that now the navigation conroller cuts off the top portion of the webview. I know I can adjust the webview down, but is that what I'm supposed to do? I feel like it should be easier to create a webview with a navigation controller.
Any help would be appreciated. Yes I have looking through stack overflow, however everyone else is using a viewcontroller to present the webview whereas I create the webview
You create the UIWebView with UIScreen.main.bounds width and height. That means that your web view will take up the entire screen in terms of size. However, you would have other elements on screen such as the status bar, the navigation bar (and, for example, if you have a tab bar, the tab bar at the bottom) which would take up some of the screen space.
So, what you should really do is set up layout constraints so that your web view makes use of the top and bottom layout guides so that your web view appears in the visible area.
If you are not sure of how to do autolayout constraints via code, this tutorial might help.
Alternatively, you can also take the bounds of the view to which you are adding your webview to set the size for your web view, but adjust the height (and the top position) to allow for the navigation bar.

Autolayout with Navigation Bar - Remove Specific Constraint

I'm building an application for iOS, which is using a navigation controller. I want to put a view in the titleView, and have it fill the whole width of the navigation bar.
I'm calling setupNavBar in viewDidLoad of the view controller that is embedded in the navigation controller. Here is how I do:
func setupNavBar() {
let navBar = navigationController?.navigationBar
// navBar!.translatesAutoresizingMaskIntoConstraints = false
// navBar!.frame.size.height = CGFloat(100)
let searchBar = UIView(frame: navBar!.frame)
searchBar.bounds = CGRectMake(0, 0, navBar!.frame.width, navBar!.frame.height)
searchBar.backgroundColor = UIColor.brownColor()
navigationItem.titleView = searchBar
}
But the view (brown - "searchBar"), doesn't cover the full navigation bar:
So I figured out that the problem was related to Autoresizing and Constraints, because if I call navBar!.translatesAutoresizingMaskIntoConstraints = false, I can freely set the sizes of views frame, so there must be some constraints that change the view's bounds. But I would like to keep as much of the autolayout behaviour as possible.
Is there a way to only change the contraints on the titleView?
I'm doing everything programmatically, I don't use the storyboard or xib's!
EDIT:
But it doesn't seem like there is any constraints on either navigationItem or navBar:
for someObject in navigationItem.titleView!.constraints {
print(someObject)
}
It doesn't print any constraints. neither if I use navBar.constraints!
EDIT 2:
I have a screenshot from "View UI Hierarchy" from the debug navigator:
It seems that the view(brown) alligns with the Navigation Bar Back Indicator View, maybe this is a clue to what causes the problem?
How come the view is resized?
Two different suggestions here:
1. You can try the
navigationItem.titleView.sizeToFit()
Otherwise you could set the background colour of the navbar to brown as it appears you wish the brown bar to cover the entire width of the navbar. If you want to add other views on top of that you then can.
You could also try to make an outlet to the title view and add an NSLayoutConstraint using
navigationItem.titleView.addConstraint(NSLayoutConstraint: NSLayoutConstraint)
I am not entirely sure whether that will work, however.

Content behind custom UINavigationBar?

I created a UINavigationController and a UIViewController. With this setup the view looks like this:
This is what I want. The content "Test Text" does not appear behind the status bar.
Now I created my own UINavigationBar in the UIViewControllers:
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
self.navigationController?.setNavigationBarHidden(true, animated: false)
let newNavBar:UINavigationBar = UINavigationBar(frame: CGRectMake(0, 0, CGRectGetWidth(self.view.bounds), 64))
newNavBar.tintColor = UIColor.whiteColor()
newNavBar.translucent = true
self.view.addSubview(newNavBar)
}
The result is the following:
The content is behind the new navigation bar.
How can I prevent the content from being behind the new navigation bar?
When you add Navigation Bar in view controller then NavigationBar will take 64pixel ( 20 pixel status bar and 44 pixel navigation bar ) so you need to start your layout after 64pixel from top.
If your content is a UIScrollView, use the contentInsets property to adjust where your content starts, this makes the scrollview be able to scroll the specified amount of pixels "too far", and thus show your content immediately below your custom UINavigationBar.
If your content is not a UIScrollview, then just offset the content with a constraint (you could link it to an IBOutlet, so you can change it if you dynamically change from the old to the new UINavigationBar).

Black bar flashes at top of UITableView when pushing to view with "Hides Bottom Bar When Pushed" in IB

This is a weird error that may just be an issue in Xcode for all I know. I have a tab bar controller where the first view is a UITableView with (obviously) a number of cells. When you select a cell, I've set up a segue on the MainStoryboard to go to a detail view controller. I want the tab bar to be hidden when I go to the detail view, so I went into the storyboard, chose my detail view, and clicked "Hides Bottom Bar on Push" in the editor screen that starts with "Simulated Metrics."
Everything works just fine, except that when I tap on a cell, a black bar flashes at the top of the UITableView screen, dropping the tableview cells down (as if the cells are falling down below the tab bar at the bottom), just before the screen pushes over to the detail view. The effect isn't harmful at all, but it's very disconcerting, and I'd like to smooth that out.
The only fix I've found is to uncheck the "Hides Bottom Bar when Pushed" option on the storyboard. That indeed does get rid of that black bar flash, but of course the tab bar stays on the screen when I go to the detail view, which is what I don't want.
Any ideas?
Just for completeness' sake, I went ahead and ran
[self.navigationController setToolbarHidden:YES animated: YES];
on the detail view controller's viewWillAppear method (and even tried it with the storyboard option both on and off), but there was no difference. The toolbar did indeed hide just fine, but I still got that black line at the top. So weird.
I know it is too late !!! I ran into same issue. It seems like the Auto resizing mask for the view was incorrect to be exact the UIViewAutoresizingFlexibleTopMargin. I checked this on in the xib file. If you are trying to do it in code make sure this flag -UIViewAutoresizingFlexibleTopMargin - is not included in the autoresizing mask.
Hope this will help some one in the future
I know it is a bit late, but I have same problem and I can't solve it with any of the previous answers. (I suppose this is the reason non was accepted).
The problem is that view size of the SecondViewController is same as view size of a previous ViewController, so too small to fit in a ViewController with Toolbar hidden. Thats why black background of a UITabBarController is visible at the top when transition is happening, and on a viewDidAppear view will stretch on right size.
For me it help to subclass root UITabBarController and set background color to same background color as SecondViewController has.
class RootViewController: UITabBarController {
override func viewDidLoad() {
super.viewDidLoad()
self.view.backgroundColor = Style.backgroundColor
}
}
Then you can leave checkbox checked inside storyboard and it will look ok.
P.S.
If you have some views, that is position on the bottom part of the view, you need to set bottom constraints so they are smaller by 49 (because this is the height of the toolbar), and then on viewDidAppear set the right constraint.
For example:
I have view that need to be position 44 px from bottom edge. Before, I have constraint set to 44 and I have some strange behaviour of that view. It was placed to height and then jump on the right place.
I fix this with setting constraint to -5 (44-49), and then in viewDidAppear set the constraint back to 44. Now I have normal behaviour of that view.
Wow I just had the same issue now, very painful, and no info on the net about it.
Anyway, a simple workaround for me was to change the current view's Frame moving the y coordinates up and making the height bigger by the height of the tab bar. This fixed the problem if done straight after pushing the new view onto the navigation controller. Also, there was no need to fix the Frame afterwards (it must be updated when the view is shown again).
MonoTouch code:
UIViewController viewControllerToPush = new MyViewController();
viewControllerToPush.HidesBottomBarWhenPushed = true; // I had this in the MyViewController's constructor, doesn't make any difference
this.NavigationController.PushViewController(viewControllerToPush, true);
float offset = this.TabBarController.TabBar.Frame.Height;
this.View.Frame = new System.Drawing.RectangleF(0, -offset, this.View.Frame.Width, this.View.Frame.Height + offset);
Objective C code (untested, just a translation of the monotouch code):
UIViewController *viewControllerToPush = [MyViewController new];
viewControllerToPush.hidesBottomBarWhenPushed = YES; viewControllerToPush.hidesBottomBarWhenPushed = YES;
float offset = self.tabBarController.tabBar.frame.size.height; float offset = self.tabBarController.tabBar.frame.size.height;
self.view.frame = CGRectMake(0, -offset, self.view.frame.width, self.view.frame.height + offset); self.view.frame = CGRectMake(0, -offset, self.view.frame.size.width, self.view.frame.size.height + offset);
Do this in viewWillAppear of detailViewController, it should work fine
subclass your navigation controller, or just find the navigation bar
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
let backdropEffectView = navigationBar.subviews[0].subviews[0].subviews[0] //_UIBackdropEffectView
let visualEffectView: UIVisualEffectView = UIVisualEffectView(effect: UIBlurEffect(style: .Light))
visualEffectView.frame = backdropEffectView.frame
backdropEffectView.superview?.insertSubview(visualEffectView, aboveSubview: backdropEffectView)
backdropEffectView.removeFromSuperview()
}

Resources