In my app, I have a toolbar with UIBarButtonItems
.
In most circumstances, the UIBarButtonItems
are set via storyboard, and look as follows:
In a special case, I have to replace one UIBarButtonItem
programmatically. This is done with the following code:
let rotatingButton = UIButton(type: .custom)
rotatingButton.setImage(UIImage(named: "LocalizationInUseNoFix"), for: .normal)
rotatingButton.addTarget(self, action: #selector(localizationButtonTapped), for: .touchUpInside)
rotatingButton.rotateStart()
let barButtonItem = UIBarButtonItem(customView: rotatingButton)
leftBarButtonItems![2] = barButtonItem
When the rotatingButton is displayed in the toolbar, it placed at a different position. It is shifted to the right, as you can see here:
How can I achieve to place both UIBarButtonItems
at the same position?
EDIT:
By now I realized that the horizontal shift of the programmatically created UIBarButtonItem
is not always the same, without any changes to the code: Sometimes it is shifted left, and not right:
EDIT 2:
I found a workaround:
If I set a width constrain to my button like
rotatingButton.widthAnchor.constraint(equalToConstant: 40).isActive = true
then the button is apparently always correctly placed. But I hate to hard-code constraints like this.
Is there a more elegant way to do it?
Try the below steps to perform your task:
NSMutableArray
UIBarbuttonItem
Hope this steps will work
When you set the image on UIBarButton programmatically, the contentmode of the leftBarButtonItems becomes 'left' and rightBarButtonItems become 'right'. But from storyboard, it is centered. Set the image and adjust the contentMode as required.
All are working fine for Navigationbar and Toolbar
class ViewController: UIViewController {
@IBOutlet weak var toolbar: UIToolbar!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
@IBAction func leftAction(_ sender: Any) {
}
@IBAction func rightAction(_ sender: Any) {
}
@IBAction func changeLeftItems(_ sender: Any) {
if let items = self.navigationItem.leftBarButtonItems {
var addItems = [UIBarButtonItem]()
addItems.append(contentsOf: items)
let barItem = UIBarButtonItem(title: "3", style: UIBarButtonItemStyle.plain, target: self, action: #selector(ViewController.leftAction(_:)))
addItems.append(barItem)
self.navigationItem.leftBarButtonItems = addItems
}
if let items = self.toolbar.items {
var addItems = [UIBarButtonItem]()
addItems.append(contentsOf: items)
let barItem = UIBarButtonItem(title: "L3", style: UIBarButtonItemStyle.plain, target: self, action: #selector(ViewController.leftAction(_:)))
addItems.insert(barItem, at: 2)
self.toolbar.setItems(addItems, animated: true)
}
}
}
This is the best solution I found so far:
Get the width of a view of another bar button item using key value coding. This is from Jeremy W. Sherman's answer here .
Please note that it does not use any private API, see the discussion there. The worst thing that can happen is that the view
property of the UIBarButtonItem
cannot be accessed. In this case, I use a default value:
var leftBarButtonItems = self.navigationItem.leftBarButtonItems
let rotatingButton = UIButton(type: .custom)
rotatingButton.setImage(UIImage(named: "LocalizationInUseNoFix"), for: .normal)
rotatingButton.addTarget(self, action: #selector(localizationButtonTapped), for: .touchUpInside)
rotatingButton.rotateStart()
// Get the width of the bar button items if possible, else set default
let leftmostBarButtonItem = leftBarButtonItems![0]
let barButtonItemWidth: CGFloat
if let leftmostBarButtonItemView = leftmostBarButtonItem.value(forKey: "view") as? UIView {
barButtonItemWidth = leftmostBarButtonItemView.frame.size.width
} else {
barButtonItemWidth = 40.0
}
rotatingButton.widthAnchor.constraint(equalToConstant: barButtonItemWidth).isActive = true
let barButtonItem = UIBarButtonItem(customView: rotatingButton)
leftBarButtonItems![2] = barButtonItem
self.navigationItem.leftBarButtonItems = leftBarButtonItems
This is working fine for me. Best way is identify item to replace and change the content
@IBAction func changeLeftItems(_ sender: Any) {
if let items = self.toolbar.items {
var addItems = [UIBarButtonItem]()
addItems.append(contentsOf: items)
let barItem = UIBarButtonItem(title: "L5", style: UIBarButtonItemStyle.plain, target: self, action: #selector(ViewController.leftAction(_:)))
addItems.remove(at: 1)
addItems.insert(barItem, at: 1)
self.toolbar.setItems(addItems, animated: true)
}
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.