I'd like to create a UIToolbar with a right-aligned done button and a left-aligned title/label.
My current solution works fine for short labels but overlaps with long ones
With autolayout I'd set the horizontal spacing to 0 and make sure my done text has higher compression resistance than the title text. But using the UIToolbar api I'm unsure how to accomplish this.
Here's the code that generates this:
lazy var pickerToolbar: UIToolbar = {
let toolbar = UIToolbar(frame: CGRect(x: 0, y: 0, width: 0, height: 33))
let leftTitle = UIBarButtonItem(title: "One and only one with lots of choices", style: UIBarButtonItemStyle.Plain, target: nil, action: nil)
leftTitle.tintColor = UIColor.blackColor()
let space = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.FlexibleSpace, target: nil, action: nil)
let closeBtn = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.Done, target: self, action: "onTapClose")
toolbar.setItems([
leftTitle,
space,
closeBtn
], animated: false)
return toolbar
}()
// ...later
textField.inputAccessoryView = pickerToolbar
Related
I am trying to add two bar buttons to toolbar in iOS [Cancel] & [Save] on right and left side accordingly.
I used a third bar button [Spacer] and set it to be [.flexiblewidth] Otherwise, when adding it only the left button appears [Cancel] and the [Spacer] & and [Save] which have to be next disappearing ?
the screen shot is in the link:
https://ibb.co/cZsaVV
let pickerView = UIPickerView()
override func viewDidLoad() {
pickerView.addSubview(self.setToolBar())
}
func setToolBar() -> UIToolbar {
let toolBar = UIToolbar()
toolBar.isTranslucent = true
toolBar.backgroundColor = UIColor.clear
let barButtonAttr = [NSAttributedString.Key.font : UIFont.systemFont(ofSize: 15),
NSAttributedString.Key.foregroundColor : UIColor.black]
// [Save] BarButtonItem
let saveBarButtonItem = UIBarButtonItem(barButtonSystemItem: UIBarButtonItem.SystemItem.save, target: self, action: nil)
saveBarButtonItem.setTitleTextAttributes(barButtonAttr, for: .normal)
// [Cancel] BarButtonItem
let cancelBarButtonItem = UIBarButtonItem(barButtonSystemItem: UIBarButtonItem.SystemItem.cancel, target: self, action: nil)
cancelBarButtonItem.setTitleTextAttributes(barButtonAttr, for: .normal)
let spacerBarButtonItem = UIBarButtonItem(barButtonSystemItem: UIBarButtonItem.SystemItem.flexibleSpace ,
target: self, action: nil)
spacerBarButtonItem.setTitleTextAttributes(barButtonAttr, for: .normal)
// add BarButtonItems to toolBar
toolBar.items = [cancelBarButtonItem,spacerBarButtonItem,saveBarButtonItem]
toolBar.sizeToFit()
return toolBar
}
func createAccessoryViewWithTarget(_ target: AnyObject, width: CGFloat) -> UIView {
// Previous button
let previousButton = UIBarButtonItem(title: "Previous", style: .plain, target: target, action: #selector(self.moveToPreviousTextField))
previousButton.tintColor = UIColor.white
//Next button
let nextButton = UIBarButtonItem(title: "Next", style: .plain, target: target, action: #selector(self.moveToNextTextField))
nextButton.tintColor = UIColor.white
// Dismiss/close/done button
let doneButton = UIBarButtonItem(title: "Done", style: .done, target: target, action: #selector(self.keyboardDoneButtonTapped))
doneButton.tintColor = UIColor.white
let keyboardToolbar: UIToolbar = UIToolbar(frame: CGRect(x: 0, y: 0, width: width, height: 44))
keyboardToolbar.barStyle = .black
let flexSpace = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil)
let fixedSpace = UIBarButtonItem(barButtonSystemItem: .fixedSpace, target: nil, action: nil)
var itemsArray = [UIBarButtonItem]()
itemsArray.append(previousButton)
itemsArray.append(fixedSpace)
itemsArray.append(nextButton)
itemsArray.append(flexSpace)
itemsArray.append(doneButton)
keyboardToolbar.items = itemsArray
keyboardToolbar.sizeToFit()
return keyboardToolbar
}
This one is old code may be swift3 I guess. Here Im adding 3 buttons previous next and done button. flexible space and fixed space are used for spaces between buttons. Important to note here is the order that you adding your barbutton items. In your case use flexible space to place your 2 buttons on right and left end in the order of left end button, flexible space, right end button.
I've got the solution finally.
I am adding the ToolBar to the PickerView and then calling UIToolBar.SizeToFit() which is must in all cases.
the issue was I had to change the picker view size later in this case the size of subview ToolBar is not adapting with the new size coordination of pickerView. So the solution simply to call again ToolBar.SizeToFit() after any modification of parent view. here's snap of the code:
// popupView is custom UIPickerView
popupView.frame = CGRect(x:0, y:0, width:100, height:100)
// toolBar is an object of UIToolBar of the custom UIPickerView AddCurrencyPicker
(popupView as! AddCurrencyPicker).toolBar.sizeToFit()
In Swift 3, I've programmatically created a (bottom) toolbar with custom buttons separated by a flexible spacer to separate the custom buttons, pushing one ("Previous") to the left edge and the other ("Next") to the right edge of the view. But I have not been able to get the button titles ("Previous" and "Next") to display. Please advise me. Thanks. Here is my code:
First, the class declaration and a few variables:
class TextsController: UIViewController,UIGestureRecognizerDelegate {
let textWebView = WKWebView(frame: .zero)
var toolbar:UIToolbar?
Next, in the viewDidLoad:
view = textWebView
// Create (bottom) toolbar:
let frame = CGRect(x: 0, y: UIScreen.main.bounds.size.height-44, width: UIScreen.main.bounds.size.width, height: 44)
toolbar = UIToolbar(frame: frame)
toolbar?.sizeToFit()
toolbar?.isHidden = true
self.view.addSubview(toolbar!)
self.toolbar?.isTranslucent = false // Required for setting tintColor & barTintColor below
toolbar?.tintColor = UIColor(red: 0.5, green: 0.0, blue: 1.0, alpha: 1.0) //purple for toolbar items
toolbar?.barTintColor = UIColor.white //white for toolbar color
let triangleLeftButton = UIBarButtonItem(image: UIImage(named: "triangleLeft_15x20"), style: .plain, target: self, action:#selector(showPrevious))
let flexibleSpacer = UIBarButtonItem(barButtonSystemItem:.flexibleSpace , target: self, action: nil)
let triangleRightButton = UIBarButtonItem(image: UIImage(named: "triangleRight_15x20"), style: .plain, target: self, action:#selector(showNext))
triangleLeftButton.title = "Previous"
triangleRightButton.title = "Next"
var items = [UIBarButtonItem]()
items.append(triangleLeftButton)
items.append(flexibleSpacer)
items.append(triangleRightButton)
toolbar?.items = items
A custom view or image bar button item has no title. A bar button item is either a title or a custom view or an image. If you want some words to appear in a custom view or image bar button item, make those words part of the custom view or image.
Here is how I solved this.
I eliminated the two statements attempting to assign a title to each button (I do wonder why Xcode did not flag that, allowing me to assign a title to each initially, though neither title would display).
I rewrote (compare the code below with the code in the question) the UIBarButtonItems as follows to now include two text items:
// Create toolbar items (buttons and texts)
let triangleLeftButton = UIBarButtonItem(image: UIImage(named: "triangleLeft_15x20"), style: .plain, target: self, action:#selector(showPrevious))
let triangleLeftText = UIBarButtonItem(title: "Previous", style: .plain, target: nil, action: nil)
let flexibleSpacer = UIBarButtonItem(barButtonSystemItem:.flexibleSpace , target: self, action: nil)
let triangleRightText = UIBarButtonItem(title: "Next", style: .plain, target: nil, action: nil)
let triangleRightButton = UIBarButtonItem(image: UIImage(named: "triangleRight_15x20"), style: .plain, target: self, action:#selector(showNext))
Then I appended everything, including the two new text items, to the array:
var items = [UIBarButtonItem]()
items.append(triangleLeftButton)
items.append(triangleLeftText)
items.append(flexibleSpacer)
items.append(triangleRightText)
items.append(triangleRightButton)
toolbar?.items = items
This effectively places "Previous" adjacent to the left-pointing button and "Next" adjacent to the right-pointing button, with the flexible spacer affording a nice wide gap between.
I hit a road bump trying to change the toolbar button of type UIBarButtonItem during runtime.
I've created programatically a Toolbar for a given text view and I want to change the button image when it's pressed, like if it has a toggle on image and a toggle off one.
I'll explain:
Here I create the toolbar with the desired buttons
func configureToolbar(forTextView textView: UITextView) {
toolbar?.barStyle = UIBarStyle.default
toolbar?.items = [
UIBarButtonItem.init(image: UIImage.init(named: "bold_unselected"), style: UIBarButtonItemStyle.plain, target: self, action: #selector(ViewController.didTapBold(sender:))),
UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.flexibleSpace, target: nil, action: nil),
UIBarButtonItem(title: "Italic", style: UIBarButtonItemStyle.plain, target: self, action: #selector(ViewController.didTapItalic(sender:))),
UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.flexibleSpace, target: nil, action: nil),
UIBarButtonItem(title: "Underline", style: UIBarButtonItemStyle.plain, target: self, action: #selector(ViewController.dismissKB))]
toolbar?.sizeToFit()
for (index,item) in (toolbar?.items?.enumerated())! {
item.tag = index
}
// Adds a view as a upper border line
let border = UIView(frame: CGRect(x: 0, y: 0, width: self.view.bounds.width, height: 0.5))
border.backgroundColor = UIColor.lightGray
toolbar?.addSubview(border)
// Configures the toolbar
toolbar?.backgroundColor = UIColor.white
toolbar?.barTintColor = UIColor.white
toolbar?.tintColor = UIColor.black
toolbar?.clipsToBounds = true
// Adds to the super view;
textView.inputAccessoryView = toolbar
}
Here's the bold button function
func didTapBold(sender: UIBarButtonItem) {
typeface.isBold = typeface.isBold! ? false : true // true -> false -> true
toggleButton(button: sender, status: typeface.isBold!)
}
Here's where I want to change the button 'status' ON - OFF
func toggleButton(button: UIBarButtonItem, status: Bool) {
// changes the button appearance
switch button.tag {
case 0:
print("bold")
print("status \(status)")
if status {
button.image = UIImage.init(named: "bold_selected")
} else {
button.image = UIImage.init(named: "bold_unselected")
}
case 2:
print("bla bla bla")
case 4:
print("bla bla bla 2")
default:
print("default value called")
}
}
For some reason, I can't change the image to the one that I want to, but I can change to another one.
I've read the Human Interface Guidelines and can't find which are the recommended image size to the toolbar, but after searching I've read in some websites that is 20x20, can someone confirm it?
There are the default image and the selected one.
UPDATE
Somehow it seems that I can't add any coloured icon/image to the toolbar. Just tried to add a different icon and it just showed up as a black dot.
So I have found the solution, which is pretty simple but it wasn't easy to find.
If you want to add coloured icons/images to your toolbar, when you're adding the image don't forget to set the rendering mode property to always original.
Se corrected code now should be:
//when setting the toolbar icons
toolbar?.items = [UIBarButtonItem.init(image: UIImage.init(named: "bold_unselected")?.withRenderingMode(.alwaysOriginal), style: UIBarButtonItemStyle.plain, target: self, action: #selector(ViewController.didTapBold(sender:)))]
Or instantiate your images to
let img = UIImage(named: "image").withRenderingMode(.alwaysOriginal)
let barBtnItm = UIBarButtonItem.init(image: img, style: UIBarButtonItemStyle.plain, target: self, action: #selector(ViewController.didTapBold(sender:)))
Hope it helps
I'm trying to add a Done button to a keyboard. The code below used to work:
func addDoneButtonOnKeyboard()
{
let doneToolbar: UIToolbar = UIToolbar(frame: CGRectMake(0, 0, screenWidth, 50))
//doneToolbar.barStyle = UIBarStyle.BlackTranslucent
let flexSpace = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.FlexibleSpace, target: nil, action: nil)
let done: UIBarButtonItem = UIBarButtonItem(title: "Done", style: UIBarButtonItemStyle.Done, target: self, action: Selector("doneButtonAction"))
var items: [UIBarButtonItem]?
items?.append(flexSpace)
items?.append(done)
doneToolbar.items = items
doneToolbar.sizeToFit()
commentsField.inputAccessoryView=doneToolbar
}
It puts the toolbar above the keyboard but there is no done button.
The issue comes from the line
var items: [UIBarButtonItem]?
Your array of UIBarButtonItem is never initialized. Replace this line with
var items: [UIBarButtonItem]? = [UIBarButtonItem]()
I made a custom UINavigationBar looks like this:[
Now I want to increase spacing between left and left bar button. I tried to do that this way using UIEdgeInsets this way:
self.navigationItem.leftBarButtonItem?.imageInsets = UIEdgeInsetsMake(0, 20, 0, 0)
Then it gets shrieked :
You can add extra spacing item before button:
let button = UIBarButtonItem(title: "<", style: .plain, target: self, action: "someSelector")
let spacing = UIBarButtonItem(barButtonSystemItem: .fixedSpace, target: nil, action: nil)
spacing.width = 20;
navigationItem.leftBarButtonItems = [spacing, button]