I am using a button as a title view for my UITableViewController which opens a dropdown list of categories. Selecting a category filters content of the table view by the selected category.
The button shows the name of the selected category plus a small arrow, similar to how iBooks used to look (or maybe still looks? I haven't used it in a while). I would therefore like it to have the same behaviour as a standard title and have it be large at first and collapse when the table view is scrolled.
Is there a way to do this?
Thanks
It seems because of the new large titles, IOS11 requires the constraints on the custom view in the navigationItem.titleView to be set.
Do this for example:
customView.widthAnchor.constraint(equalToConstant: 200).isActive = true
customView.heightAnchor.constraint(equalToConstant: 44).isActive = true
self.navigationItem.titleView = customView
Note this must be done for both width and height.
It should work. No need to add a button, at least in my case...
This was suggested by Apple to ensure that you don't have zero-size custom views. See slide 33 in https://developer.apple.com/videos/play/wwdc2017/204/
Looks like touches are broken for navigationItem.titleView. Gestures, tap events and buttons - nothing works
Seems like a bug in iOS 11: https://forums.developer.apple.com/thread/82466
I provisionally implemented this workaround:
private lazy var navBarActionButtonIOS11: UIButton = {
button.addTarget(self.navTitleView, action: #selector(self.navTitleView.didTapView), for: .touchUpInside)
return button
}()
[...]
navigationItem.titleView = navTitleView
if #available(iOS 11.0, *), let navBar = navigationController?.navigationBar {
navBarActionButtonIOS11.removeFromSuperview()
navBar.addSubview(navBarActionButtonIOS11)
navBarActionButtonIOS11.center.x = navBar.center.x
}
Another solution could be to just assign a UIButton to navigationItem.titleView directly.
I hope Apple fixes this soon!
Well, I had same problem. I have UIButtons in UINavigationItem.titleView and those were not reacting to touches at all. Problem is that the view where those buttons are where of size (0,0) because of auto layout. So to fix this problem you need to add additional view into your custom view, lets call it "contentView" and put all your controls inside that contentView. Also, contentView must have defined size with constraints. Quick test is to add width and height constraint to contentView. And all works again.
Hope that this helps someone.
Related
I have a VC that has a UITableView all over the screen, except the first 66px from the top. There, I have a custom UIView I call "Toolbar" which contains a title and a button.
It looks like this:
I'm trying to add a shadow to the "Toolbar" that will be visible on top of the UITableView. I'm adding it like this:
For some reason, I don't see any shadow when I run the app.
What am I doing wrong? Does anybody know?
Thank you!
Shadow needs some spaces to be shown, you have to add some vertical spaces between your top view(toolbar) and the Table view.
for having a result like the following:
you need to add some space:
ans I also use the following code for adding the shadow:
toolbar.layer.shadowColor = UIColor.black.cgColor
toolbar.layer.shadowOpacity = 1
toolbar.layer.shadowOffset = CGSize.zero
toolbar.layer.shadowRadius = 10
toolbar.layer.masksToBounds = false
As titled, I'm using a UIButton as the titleView in the navbar. Is there a way for me to make the UIButton larger along with the navbar? When I set self.navigationController?.navigationBar.prefersLargeTitles = true, what I got is this,
I can't find any documentation on this, so I played a bit. It seems in iOS 11, you won't be able to get that title to be a button and display large at the left.
Also, I ttied playing with the frame size of the button (added below). I was unable to increase the button size, no matter what I set the frame to.
To recreate, I set up a Single View project. I embedded the view controller in a navigation controller.
In ViewController.swift's viewDidLoad, I added this code:
let titleButton = UIButton(type: .roundedRect)
titleButton.setTitle("Hello Button!", for: UIControlState.normal)
let navController = parent as! UINavigationController
navController.navigationBar.topItem!.title = "Hello???"
navController.navigationBar.topItem!.titleView = titleButton
navController.navigationBar.prefersLargeTitles = true
This ends up looking something like your example.
IF I:
set .title to empty string, or remark the line out: navbar is stretched, and no title text shows (or title text set in Interface Builder shows)
remark out .prefersLargeTitles, or set it to false: the navbar is the normal height, the button displays, but no title text displays.
remark out the titleView line, AND:
leave the .prefersLargeTitles set to true: the title text displays large at the left, and the navbar's height is stretched.
set the .prefersLargeTitles to false: the title text displays in the top center, and the navbar is normal height.
I have a UISplitViewController in my application (MvvmCross / Xamarin iOS) and for some reason I cannot get the content to respect the dimensions of the available view areas.
In the situation shown in the screenshot the master view is hosting a UIViewController with a TableView inside. All the layouts are done with constraints and work fine on their own when running in an iPhone emulator.
As soon as I switching to running on an iPad some custom code I have in my presenter shows this same view in the master panel of a UISplitViewController but in this situation the constraints seem to be ignored and I end up with a view that looks like this:
As you can see the right hand side of the table cell is now way off the viewable area of the master panel of the UISplitViewController.
Both the UITableView and the UITableCell both use View.Frame as their initial size (I've tried View.Bounds as well).
How can I get the cells and / or table to respect the bounds of the UISplitViewController available space?
Thanks to Cheesebarons question I found my solution (cause).
I have a set of methods in a helper class that I use to generate my "default" UIViews.
One of these methods creates my default UITableView:
public static UITableView CreateDefaultTableView(CGRect rect, UITableViewStyle style)
{
var tv = new UITableView(rect, style)
{
AutoresizingMask = UIViewAutoresizing.FlexibleHeight,
SeparatorStyle = UITableViewCellSeparatorStyle.SingleLine,
SeparatorColor = IosConstants.DefaultTableSeparatorColor,
BackgroundColor = IosConstants.DefaultViewBackgroundColor
};
return tv;
}
Changing:
AutoresizingMask = UIViewAutoresizing.FlexibleHeight,
To:
AutoresizingMask = UIViewAutoresizing.All,
Schoolboy error!
i would ask if it is possible to change to base modal window to look like my image? (only layout test)
I can easiliy set up an image with:
var barButtonImage:UIImage = UIImage(named: "header_test.png")
var barButtonImageView = UIImageView(image: barButtonImage)
self.navigationItem.titleView = barButtonImageView
But i am not able to set it outside the view - is that possible? And if, how?
EDIT:
Thanks for the info about using clipsToBounds. I set it to titleview and bar to false, but the image is not outside the modal (but it is over the top of my UITableView in the modal window)
self.navigationItem.titleView.clipsToBounds = false
self.navigationController.navigationBar.clipsToBounds = false
You're going to have to embed your visual stuff inside another view, with that view's background set to transparent.
Or, you could play around with the "clips subviews" property of your view, to allow the round graphic to not get clipped at the edges of the superview that contains it.
I'm took the Tabbar viewcontroller in this ,I added the 5 item and .I given the image insects is (24,0,0,6).
All button images are added in xib [under the Bar item -->image]Please help.
Thanks.
Adding to a similar answer here:
iOS Tab Bar icons keep getting larger
Not sure if this is an iOS7 bug but I've noticed that image insets need to be balanced.
You have specified insets for top and right but:
if you set a top inset, in order to balance it, you need to set the negative of it to the bottom inset
if you set a right inset, in order to balance it, you need to set the negative of it to the left inset
So, instead of having image insets like (24,0,0,6), use balanced image insets such as UIEdgeInsetsMake(24,-6,-24,6)
Doing so should protect your tabBarItem image from getting whacked on every tap.
If this doesn't suit your requirements, then redesign your tabBarItem image so you can have balance insets or... no insets at all.
Here's the workaround for a bug I've encountered with UITabBarController's UITabBar. If I tap a UITabBarItem once after it's selected, the icon shrinks. What I'd like to do is disable touches. UITabBarItem only has a setting for isEnabled, which grays it out if I set it to false...not what I was looking for.
I used a derivative of this answer to figure it out. With a UITabBarController with 3 tabs, printing tabBarController.subviews, I saw 3 UITabBarButtons and a UIBarBackground. The origin of UIBarBackground's frame was always (0, 0), putting it at the front of the sorted array, so I really don't need to know what the subview is, just "where it is" and whether it will always be there. The UIBarBackground is always going to be at the front of an array of tabBarController.subviews sorted by frame.minX, so I just need to remove it from the front.
Solution
Here's what the extension looks like:
extension UITabBarController {
var buttonViews: [UIView] {
var tabBarButtons = tabBar.subviews.sorted(by: {$0.frame.minX < $1.frame.minX})
tabBarButtons.removeFirst()
return tabBarButtons
}
}
I also created a struct in my Constants file, so I don't have to remember tab names:
struct TabBarItem {
static let firstTab = 0
static let secondTab = 1
static let thirdTab = 2
}
...and finally, where to use it:
In viewDidAppear (NOT viewDidLoad), add the following line to disable the UITabBarItem that you don't want to disable, but not gray out:
tabBarController?.buttonViews[TabBarItem.firstTab].isUserInteractionEnabled = false
In viewWillDisappear, re-enable the tab, as follows:
tabBarController?.buttonViews[TabBarItem.firstTab].isUserInteractionEnabled = true