LeftBarButtonItem with UISearchBar is not visible on iOS 11 - ios

The title is pretty self explanatory, on iOS 10.3 using a UIBarButtonItem with a custom view (in this case UIStackView) assigned to a LeftBarButtonItem of a NavigationBar is not visible on iOS 11. I haven't figure out why it is not showed but when I type something with the keyboard my logic of the TextChanged event works! So the UISearchView is there but it is not visible:
Here is some code (It is coded with C# but it is using Objective C methods.):
var width = NavigationController.NavigationBar.Frame.Width;
var height = NavigationController.NavigationBar.Frame.Height;
_searchBarContainer = new UIStackView(new CGRect(0, 0, width * 0.75, height))
{
Alignment = UIStackViewAlignment.Center,
Axis = UILayoutConstraintAxis.Horizontal,
Spacing = 3
};
_uiSearchBar = new UISearchBar
{
BackgroundColor = UIColor.Clear,
BarTintColor = UIColor.Clear,
BackgroundImage = new UIImage(),
Placeholder = Strings.Search
};
_uiSearchBar.SizeToFit();
if (_iOS11)
{
_uiSearchBar.HeightAnchor.ConstraintEqualTo(44).Active = true;
}
_searchbarButtonItem = new UIBarButtonItem(_searchBarContainer);
NavigationItem.SetLeftBarButtonItem(_searchbarButtonItem, true);
ParentViewController.NavigationItem.LeftBarButtonItem = NavigationItem.LeftBarButtonItem;
Using the same code on iOS 10 this works.

Please try out setting up constraints to size properly your _searchBarContainer before setting it as the left bar button item. From iOS11 navigations bars use auto layout. Make sure you only add the constraints if iOS 11 is present, I was having problems in iOS 9 navigation bars otherwise.
Also checkout this thread in the Dev forum where it's explained how the bar items are wrapped inside stack views, maybe also helps with your particular issue.

Related

How to render a UIButton in Xamarin.iOS

How do I render a UIButton in Xamarin.iOS? See the current Code for the full list.
This is the code I'm using to create and add the button to the Xamarin.Forms.Platform.iOS.CellTableViewCell cell. I cannot get the button to display anything.
With the use of a Foundation.NSMutableAttributedString, it shows a cut-off section of text in the top left corner, regardless of anything I try (alignments, insets, bounds, various constraints, etc). I'm currently trying things from Xamarin.Forms.Platform.iOS.Renderers.ButtonRenderer, but still can't get anything to display at all, no text, no button, or its outline.
If you could fork the repo and fix it or post the solution here, I would be very grateful.
protected override void SetUpContentView()
{
var insets = new UIEdgeInsets(SVConstants.Cell.PADDING.Top.ToNFloat(), SVConstants.Cell.PADDING.Left.ToNFloat(), SVConstants.Cell.PADDING.Bottom.ToNFloat(), SVConstants.Cell.PADDING.Right.ToNFloat());
_Button = new UIButton(UIButtonType.RoundedRect)
{
AutoresizingMask = UIViewAutoresizing.All,
HorizontalAlignment = UIControlContentHorizontalAlignment.Center,
VerticalAlignment = UIControlContentVerticalAlignment.Center,
ContentEdgeInsets = insets,
// TitleEdgeInsets = insets
};
DefaultFontSize = _Button.TitleLabel.ContentScaleFactor;
DefaultTextColor = _Button.TitleLabel.TextColor;
_Recognizer = new UILongPressGestureRecognizer(RunLong);
_Button.TouchUpInside += OnClick; // https://stackoverflow.com/a/51593238/9530917
_Button.AddGestureRecognizer(_Recognizer); // https://stackoverflow.com/a/6179591/9530917
ContentView.AddSubview(_Button);
_Button.CenterXAnchor.ConstraintEqualTo(ContentView.CenterXAnchor).Active = true;
_Button.CenterYAnchor.ConstraintEqualTo(ContentView.CenterYAnchor).Active = true;
_Button.WidthAnchor.ConstraintEqualTo(ContentView.WidthAnchor).Active = true;
_Button.HeightAnchor.ConstraintEqualTo(ContentView.HeightAnchor).Active = true;
UpdateConstraintsIfNeeded();
LayoutIfNeeded();
}
Found out that you can't subclass it. Any button added to the view must be native (UIButton) or custom rendered, such as Xamarin.Forms.Platform.iOS.ButtonRenderer; It doesn't show up otherwise.

How to scale the fonts in a Button

I'm trying to complete my first app in Swift and I met with the problem.
I have some buttons with the tittles and background image. Running the simulation on different devices makes them scale, so the tittles goes out of buttons frame.
There is no "Dynamic Type Automatically Adjust Font" checkbox in my Xcode attributes inspector so I made the custom UIButton class and made the inspectable var
#IBInspectable var adjustFontSize : Bool {
set { titleLabel?.adjustsFontForContentSizeCategory = newValue }
get { return titleLabel!.adjustsFontForContentSizeCategory }
but this does't helps and I got "Automatically adjusts font requires using a dynamic type text style" warning
So how can I make my button title scale to fit the Button frame when the button changes size and proportions on different devices?
This worked for me.
btn.titleLabel?.minimumScaleFactor = 0.1
btn.titleLabel?.numberOfLines = 1
btn.titleLabel?.adjustsFontSizeToFitWidth = true
Try these
button.titleLabel!.numberOfLines = 1
button.titleLabel!.adjustsFontSizeToFitWidth = true
button.titleLabel!.baselineAdjustment = .alignCenters
but for them to work, you will have to set button width constraint either in storyboard or programatically.
This will then make the title size change based on the width of the button.

What is the top bar height of iPhone X?

I would like to know exact height of top bar of iPhone X.
Could you please mention the status bar and navigation bar height of iPhone X.
Please help me.
The display on iPhone X, however, is 145pt taller than a 4.7" display, resulting in roughly 20% additional vertical space for content.
for more information you get HIG for iphone X from apple documents and detail description in here1 and here2
status bar height
previously 20pt, now 44pt
Because of the sensors on top of the display, the new status bar is split in 2 parts. If your UI is doing something special with that space (previously 20pt high, now 44pt), because it will be taller on the iPhone X. Make sure that it can be dynamically changed in height. A great thing is that the height won’t be changed if a user makes a phone call or is using a navigation app, which was previously the case on other iPhones.
portrait
Navigation bar height as normal 88 and large title time 140
Standard title - 44pt (88pt with Status Bar)
Large title - 140pt
bottom bar - 34pt
Landscape
Standard title - 32pt
bottom bar - 21pt
Nav bar is 44pt as usual (when no large titles) and the status bar has increased from 20pt to 44pt. Here's what you can type in the debugger to verify it:
You can programmatically obtain the navigation bar's height by using safeAreaInsets on the view in the contained view controller:
let navBarHeight = view.safeAreaInsets.top
This will account for whether it's a large title navigation bar or not, and whether or not there's a search bar attached to it.
See the safeAreaInsets documentation for more information.
You can simply get it in the next way (Swift 3):
let barHeight = navigationController?.navigationBar.frame.maxY
To get correct value make sure that you call it after setting prefersLargeTitles
navigationController?.navigationBar.prefersLargeTitles = false
You can use the navigation bar's .frame property to figure out the overall height of the top bar area:
Swift 5.0:
let xBarHeight = (self.navigationController?.navigationBar.frame.size.height ?? 0.0) + (self.navigationController?.navigationBar.frame.origin.y ?? 0.0)
ObjC:
CGRect navbarFrame = self.navigationController.navigationBar.frame;
float topWidth = navbarFrame.size.width;
float topHeight = navbarFrame.size.height + navbarFrame.origin.y;
I suppose this is a bit of a cheat, but adding the navbar's height with its y origin seems to give the correct total height regardless of device.
There is no specification in Apple Docs
Apple Docs
According to Geoff Hackworth its 88
Navigation title types :
Standard title
Large title
Increasing navigation bar in iOS 11
navigationController?.navigationBar.prefersLargeTitles = true
If you're using a UIWindow and you need to know the top bar height you can use this:
// old way of getting keyWindow
//guard let keyWindow = UIApplication.shared.keyWindow else { return }
// new way of getting keyWindow
guard let keyWindow = UIApplication.shared.windows.first(where: { $0.isKeyWindow }) else { return }
let navBarHeight = keyWindow.safeAreaInsets.top
print("navBarHeight:" , navBarHeight)
I got the idea from #Paolo's answer
Use it if you want to know where need start content
extension UIViewController {
var navigationBarbarContentStart: CGFloat {
return self.navigationBarTopOffset + self.navigationBarHeight
}
var navigationBarTopOffset: CGFloat {
return self.navigationController?.navigationBar.frame.origin.y ?? 0
}
var navigationBarHeight: CGFloat {
return self.navigationController?.navigationBar.frame.height ?? 0
}
}

Navigation bar title and navigation buttons not appearing on iOS 11

Prior to iOS 11, the UINavigationBar buttons and title are being displayed correctly.
Yesterday I downloaded Xcode 9 with iOS 11 and, after building and running without doing changes, both navigation buttons and the title are not being displayed anymore. It shows the UINavigationBar with the correct color I am setting but nothing else.
I tried on different simulators and also I updated an iPhone 7 to iOS 11 beta 5 and the result is the same. Nothing being displayed.
Has someone faced the same problem? I have tried changing different parts of the code and storyboard but nothing affects...
EDIT with screenshots: http://imgur.com/a/Hy46c
Thanks in advance!
For Xcode 9, it appears that it is no longer enough to just set the frame of a custom view that is being injected into the navigationItem titleView. The intrinsic content size of your titleView now must be overriden and set as well.
Here's the code, adjust the width and height to suit your needs:
class NavigationBarTitleView: UIView {
override var intrinsicContentSize: CGSize {
return CGSize(width: bounds.width - 100, height: 50)
}
...
}
use sizeToFit()! ios 11 automatically sizes it, but ios 10 does not
I had the same issue and for me it was caused by subclassing UITabBarController
Did you set "window,rootViewController = ..." in your code ? Try remove it can fix your problem
I had the same problem in my project where the titles were missing from the navigation bars after updating to Xcode 9 and iOS 11. I solved it by going to the navigation bar of my navigation controller on the storyboard, keeping the Prefers Large Titles unchecked and changing the Title Font under Title Text attributes, which was set by default in Xcode 9 to System 0 to some other option like Caption 1 or Headline. I also changed its children viewcontrollers' navigation bar settings For Large Title to Never instead of Automatic or Always.
I found this code in some inherited codebase, commented it out and everything worked as it did before iOS 11.x.
if (appDelegate.window.rootViewController != self) {
appDelegate.window.rootViewController = self;
}
Try to use:
UINavigationBar.appearance().titleTextAttributes = [NSForegroundColorAttributeName: UIColor.white]
or without appearance proxy setting directly to the current navigationBar...It solves my problem, should Apple changed titleText to clear as default in iOS11...?
Also use this if you want the same look as iOS 10:
if #available(iOS 11, *) {
nav.navigationBar.prefersLargeTitles = false
}
Had the same issue with the navigationButton not displayed. I solved it by setting the renderingMode to .alwaysOriginal. (I didn't use templates)
Swift 3 code:
var img =R.image.smt()?.withRenderingMode(.alwaysOriginal)
I had that same issue and none of the above fixed.
Although, #Justin Vallely lead to me fix it.
All I did was to set a width on the titleView and everything worked just fine!
EDIT:
Every UIViewController has a navigationItem property, and every navigationItem has an optional titleView.
For reference: https://developer.apple.com/documentation/uikit/uinavigationitem/1624935-titleview
In my case, I was using a custom titleView and I think that's the cause of the problem, since Apple changed the API to support the new navigation bar layout.
Based on the Justin Vallely's comment I've reworked the code a little to ensure proper sizing of the view:
class NavigationBarTitleView: UIView {
private var width: CGFloat = 0.0
private var height: CGFloat = 0.0
override init(frame: CGRect) {
super.init(frame: frame)
width = frame.width
height = frame.height
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
override var intrinsicContentSize: CGSize {
return CGSize(width: width, height: height)
}
}
In my particular case I've used this view as a container to UISearchBar and now it is well sized and worked perfectly with Swift 4 & iOS 11, just as it used to work on previous iOS & Swift versions
We were facing the same issue where the navigation bar color is there but the title and the buttons are not showing up. We have double checked the bar was there by triggering a navigation bar background color change 2 seconds after the navigation controller showed up on the screen, so we know the navigation bar was there and we were adding buttons to the correct instance. Same as the OP, this issue only appears on iOS 11 and not iOS 10, and we are using Swift 3.2 running Xcode 9.1.
After hours of fiddling around, it turns out that presenting a navigation controller, then making it as the UIApplication.shared.delegate.window.rootViewController (after the present animation) caused the issue in our case.
If you just skip the present view controller and make the navigation controller as the root view controller, then everything works fine. Of course, you lose the present animation in the case.

Xcode shows labels, buttons, navigation bar & images as pixelated

As you can see in this screenshot:
The Navigation bar, buttons and the speaker image are pixeled.
I migth think that it has a connection to the View Hierarchy - this View is on top of the main View (The main view label and buttons looks good and not pixeled), written in Swift:
var navUser = UIViewController()
class ViewControllerMenu: UIViewController {
navUser = storyboard!.instantiateViewController(withIdentifier: "navUser")
addChildViewController(navUser)
navUser.view.frame = view.frame
view.addSubview(navUser.view)
navUser.didMove(toParentViewController: self)
navUser.view.alpha = 0
navUser.view.layer.shadowColor = UIColor.black.cgColor
navUser.view.layer.shadowOpacity = 1
navUser.view.layer.shadowOffset = CGSize.zero
navUser.view.layer.shadowRadius = 10
navUser.view.layer.shadowPath = UIBezierPath(rect: navUser.view.bounds).cgPath
navUser.view.layer.shouldRasterize = true
}
I'm adding the View Hierarchy of this view:
This happens in all the Xcode iPhone simulators and in my personal iPhone 7.
This seems to be an odd usage of .shouldRasterize ... that is normally used when re-displaying a complex view / layer multiple times (such as game animation).
Removing that line - navUser.view.layer.shouldRasterize = true - should fix the problem.

Resources