UIBarButtonItem 通过故事板放置与以编程方式放置时位置不同
UIBarButtonItem position different when placed via storyboard vs. programmatically
在我的应用程序中,我有一个带有 UIBarButtonItems
的工具栏。
在大多数情况下,UIBarButtonItems
是通过故事板设置的,如下所示:
在特殊情况下,我必须以编程方式替换一个 UIBarButtonItem
。这是通过以下代码完成的:
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
当旋转按钮显示在工具栏中时,它被放置在不同的位置。它向右移动,如您在此处所见:
我怎样才能把两个 UIBarButtonItems
放在同一个位置?
编辑:
到现在为止,我意识到以编程方式创建的 UIBarButtonItem
的水平移动并不总是相同的,没有对代码进行任何更改:有时它向左移动,而不是向右移动:
编辑 2:
我找到了解决方法:
如果我为我的按钮设置宽度限制,例如
rotatingButton.widthAnchor.constraint(equalToConstant: 40).isActive = true
然后按钮显然总是正确放置。但我讨厌像这样硬编码约束。
有没有更优雅的方法呢?
尝试以下步骤来执行您的任务:
- 将左栏按钮项存储到
NSMutableArray
- 替换所需的
UIBarbuttonItem
- 将 leftbarbuttonitems 设置为此新数组
希望这些步骤能奏效
当您以编程方式在 UIBarButton 上设置图像时,leftBarButtonItems 的内容模式变为 'left',rightBarButtonItems 变为 'right'。但是从故事板来看,它是居中的。设置图片并根据需要调整contentMode。
导航栏和工具栏都正常工作
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)
}
}
}
这是迄今为止我找到的最佳解决方案:
使用键值编码获取另一个条形按钮项的视图宽度。这是来自 Jeremy W. Sherman 的回答 here.
请注意,它不使用任何私有 API,请参阅此处的讨论。可能发生的最糟糕的事情是无法访问 UIBarButtonItem
的 view
属性。在这种情况下,我使用默认值:
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)
}
}
在我的应用程序中,我有一个带有 UIBarButtonItems
的工具栏。
在大多数情况下,UIBarButtonItems
是通过故事板设置的,如下所示:
在特殊情况下,我必须以编程方式替换一个 UIBarButtonItem
。这是通过以下代码完成的:
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
当旋转按钮显示在工具栏中时,它被放置在不同的位置。它向右移动,如您在此处所见:
我怎样才能把两个 UIBarButtonItems
放在同一个位置?
编辑:
到现在为止,我意识到以编程方式创建的 UIBarButtonItem
的水平移动并不总是相同的,没有对代码进行任何更改:有时它向左移动,而不是向右移动:
编辑 2:
我找到了解决方法:
如果我为我的按钮设置宽度限制,例如
rotatingButton.widthAnchor.constraint(equalToConstant: 40).isActive = true
然后按钮显然总是正确放置。但我讨厌像这样硬编码约束。
有没有更优雅的方法呢?
尝试以下步骤来执行您的任务:
- 将左栏按钮项存储到
NSMutableArray
- 替换所需的
UIBarbuttonItem
- 将 leftbarbuttonitems 设置为此新数组
希望这些步骤能奏效
当您以编程方式在 UIBarButton 上设置图像时,leftBarButtonItems 的内容模式变为 'left',rightBarButtonItems 变为 'right'。但是从故事板来看,它是居中的。设置图片并根据需要调整contentMode。
导航栏和工具栏都正常工作
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)
}
}
}
这是迄今为止我找到的最佳解决方案:
使用键值编码获取另一个条形按钮项的视图宽度。这是来自 Jeremy W. Sherman 的回答 here.
请注意,它不使用任何私有 API,请参阅此处的讨论。可能发生的最糟糕的事情是无法访问 UIBarButtonItem
的 view
属性。在这种情况下,我使用默认值:
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)
}
}