Как настроить пространство между двумя UIBarButtonItem в rightBarButtonItems
Я использую следующие коды, чтобы добавить две кнопки в self.navigationItem.rightBarButtonItems, и я думаю, что в iOS7 пространство между двумя кнопками слишком велико, есть ли способ уменьшить пространство между этими двумя кнопками?
UIBarButtonItem *saveStyleButton = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"save.png"] style:UIBarButtonItemStyleBordered target:self action:@selector(saveStyle)];
UIBarButtonItem *shareStyleButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAction target:self action:@selector(shareStyle)];
NSArray *arr= [[NSArray alloc] initWithObjects:shareStyleButton,saveStyleButton,nil];
self.navigationItem.rightBarButtonItems=arr;
Оцените любые намеки или идеи.
Ответы
Ответ 1
Обновлено на июль 2015
Лучший способ сделать это - использовать раскадровку (проверенную в Xcode 6.4). Сначала добавьте UINavigationItem; во-вторых, добавьте элемент кнопки "Бар"; в-третьих, добавьте представление к элементу кнопки бара, который вы только что создали на шаге 2; в-четвертых, добавьте столько кнопок, сколько пожелаете, в эту точку зрения, которую вы просто затащили; наконец, отрегулируйте пространство мышью и ограничениями.
Вопросы, относящиеся
Невозможно назначить несколько кнопок UINavigationItem при использовании раскадровки с iOS 5
Как добавить кнопки в навигационный контроллер, видимые после segueing?
Старый ответ (только для небольших вложений)
Использовать свойство imageInsets:
leftButton.imageInsets = UIEdgeInsetsMake(0.0, 0.0, 0, -15);
rightButton.imageInsets = UIEdgeInsetsMake(0.0, -15, 0, 0);
для трех или более кнопок, средний (-ы) получает обе вставки:
leftButton.imageInsets = UIEdgeInsetsMake(0.0, 0.0, 0, -15);
middleButton.imageInsets = UIEdgeInsetsMake(0.0, -15, 0, -15);
rightButton.imageInsets = UIEdgeInsetsMake(0.0, -15, 0, 0);
Для кнопок с правой стороны будьте осторожны: кнопка FIRST в массиве элементов является ПРАВОЙ:
rightButton.imageInsets = UIEdgeInsetsMake(0.0, -15, 0, 0);
middleButton.imageInsets = UIEdgeInsetsMake(0.0, -15, 0, -15);
leftButton.imageInsets = UIEdgeInsetsMake(0.0, 0.0, 0, -15);
ВАЖНО: Разделите вставку между двумя соседями; если применить всю вставку к одному краю, станет очевидно, что кнопки перекрываются в "пустое" пространство - одна кнопка получает все "пробелы". Даже когда "расколоть" такую настройку, при -40 на обоих краях, кран иногда будет иногда ошибаться. -15 или -20 - это больше всего, чтобы использовать эту технику.
Применяя этот метод, кнопку можно даже перемещать в четырех направлениях.
Ответ 2
Если вы хотите иметь 2 кнопки в правом верхнем углу без места между ними или справа, это сработало для меня.
let imgLeft = UIImage(named: "buttonLeft")?.imageWithRenderingMode(.AlwaysOriginal)
let bLeft = UIBarButtonItem(image: imgLeft, style: UIBarButtonItemStyle.Done, target: self, action: "action1:")
let space = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.FixedSpace, target: nil, action: nil)
space.width = -16.0
bLeft.imageInsets = UIEdgeInsetsMake(0, 0, 0, -25.0)
let imgRight = UIImage(named: "buttonRight")?.imageWithRenderingMode(.AlwaysOriginal)
let bRight = UIBarButtonItem(image: imgRight, style: UIBarButtonItemStyle.Done, target: self, action: "action2:")
bRight.imageInsets = UIEdgeInsetsMake(0, -25, 0, 0)
self.navigationItem.rightBarButtonItems = [space,bLeft,bRight ]
Ответ 3
Моя ситуация заключалась в предоставлении горизонтального пространства для кнопки logOut на правом краю.
func addLogOutButtonToNavigationBar(triggerToMethodName: String)
{
let button: UIButton = UIButton()
button.setImage(UIImage(named: "logOff.png"), forState: .Normal)
button.frame = CGRectMake(20, 0, 30, 25)
button.contentEdgeInsets = UIEdgeInsets.init(top: 0, left: 10, bottom: 0, right: -10)
button .addTarget(self, action:Selector(triggerToMethodName), forControlEvents: UIControlEvents.TouchUpInside)
let rightItem:UIBarButtonItem = UIBarButtonItem()
rightItem.customView = button
self.navigationItem.rightBarButtonItem = rightItem
}
Ответ 4
Может быть, немного поздно для этого ответа, однако это может помочь новейшей комбинации IOS + Swift (IOS 10 и Swift 3 в моем случае). Здесь я описываю общий подход к тому, как перемещать объекты справа/слева для rightBarButtonItems/leftBarButtonItems:
Свойство, которое вы используете здесь для перемещения barButtonItem, это "imageEdgeInsets". Итак, вот как использовать это свойство -
yourBarButtonItem.imageEdgeInsets = UIEdgeInsetsMake(top, left, bottom, right)
Эти верхние, левые, нижние, правые имеют тип CGFloat, и это в основном значение поля, которое толкает ваш элемент из/друг к другу. Для уменьшения пробела мы можем использовать значения минус (-), такие как "-10".
Итак, например, если мы хотим использовать это для группы leftBatButtonItems и скажем, если мы хотим переместить элемент в бит справа, то мы можем это сделать -
ourBarButtonItem.imageEdgeInsets = UIEdgeInsetsMake(0.0, 0.0, 0.0, -15)
Надеюсь, мы получим общую идею и надеемся, что это поможет:)
Ответ 5
Создайте UIBarButtonItem
с типом гибкого или фиксированного пространства. Установите ширину и добавьте ее в массив barbuttonitems. Попробуйте использовать отрицательную ширину, посмотрите, работает ли это.
Или, возможно, вы можете настроить свой образ. Системные кнопки, которые, как я думаю, имеют фиксированный размер и могут включать в себя некоторую прозрачную часть, поэтому даже когда они упакованы вместе, все еще кажутся разнесенными.
Ответ 6
Без какого-либо кода. Я просто поместил другой UIBarButtonItem между кнопками, которые должны быть расставлены в раскадровке. Кнопка является просто заполнителем для интервала, и UIBarButton должен иметь UIView в качестве подпредставления UIBarButtonItem. отрегулируйте ширину вида для вашего расстояния. Смотрите скриншоты.
![enter image description here]()
![enter image description here]()
![enter image description here]()
Ответ 7
Чтобы выполнить это в коде без добавления дополнительного вида контейнера, используйте UIBarButtonItem
с типом системного элемента, установленным на FixedSpace
. Затем установите ширину фиксированного пространства на -10
и поместите его между двумя кнопками.
Ответ 8
другой ответ: это работает в ios 9-12. Вы должны вызвать fixNavigationItemsMargin (margin :) в функциях viewDidAppear (_ animated: Bool) и viewDidLayoutSubviews(). fixNavigationItemsMargin (margin :) будет изменять стек UINavigationController.
Вы можете вызвать fixNavigationItemsMargin (margin :) в BaseNavigationController, сделать общую работу. И вызовите fixNavigationItemsMargin (margin :) в UIViewController, чтобы сделать точный макет.
// do common initilizer
class BaseNavigationController: UINavigationController {
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
fixNavigationItemsMargin()
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
fixNavigationItemsMargin()
}
}
extension UINavigationController {
func fixNavigationItemsMargin(_ margin: CGFloat = 8) {
let systemMajorVersion = ProcessInfo.processInfo.operatingSystemVersion.majorVersion
if systemMajorVersion >= 11 {
// iOS >= 11
guard let contentView = navigationBar.subviews
.first(
where: { sub in
String(describing: sub).contains("ContentView")
}) else { return }
// refer to: https://www.matrixprojects.net/p/uibarbuttonitem-ios11/
// if rightBarButtonItems has not any custom views, then margin would be 8(320|375)/12(414)
// should use customView
let needAdjustRightItems: Bool
if let currentVC = viewControllers.last,
let rightItems = currentVC.navigationItem.rightBarButtonItems,
rightItems.count > 0,
rightItems.filter({ $0.customView != nil }).count > 0 {
needAdjustRightItems = true
} else {
print("Use 8(320|375)/12(414), if need precious margin ,use UIBarButtonItem(customView:)!!!")
needAdjustRightItems = false
}
let needAdjustLeftItems: Bool
if let currentVC = viewControllers.last,
let leftItems = currentVC.navigationItem.leftBarButtonItems,
leftItems.count > 0,
leftItems.filter({ $0.customView != nil }).count > 0 {
needAdjustLeftItems = true
} else {
print("Use 8(320|375)/12(414), if need precious margin ,use UIBarButtonItem(customView:)!!!")
needAdjustLeftItems = false
}
let layoutMargins: UIEdgeInsets
if #available(iOS 11.0, *) {
let directionInsets = contentView.directionalLayoutMargins
layoutMargins = UIEdgeInsets(
top: directionInsets.top,
left: directionInsets.leading,
bottom: directionInsets.bottom,
right: directionInsets.trailing)
} else {
layoutMargins = contentView.layoutMargins
}
contentView.constraints.forEach(
{ cst in
// iOS 11 the distance between rightest item and NavigationBar should be margin
// rightStackView trailing space is -margin / 2
// rightestItem trailing to rightStackView trailing is -margin / 2
let rightConstant = -margin / 2
switch (cst.firstAttribute, cst.secondAttribute) {
case (.leading, .leading), (.trailing, .trailing):
if let stackView = cst.firstItem as? UIStackView,
stackView.frame.minX < navigationBar.frame.midX {
// is leftItems
if needAdjustLeftItems {
cst.constant = margin - layoutMargins.left
}
} else if let layoutGuide = cst.firstItem as? UILayoutGuide,
layoutGuide.layoutFrame.minX < navigationBar.frame.midX {
// is leftItems
if needAdjustLeftItems {
cst.constant = margin - layoutMargins.left
}
}
if let stackView = cst.firstItem as? UIStackView,
stackView.frame.maxX > navigationBar.frame.midX {
// is rightItems
if needAdjustRightItems {
cst.constant = rightConstant
}
} else if let layoutGuide = cst.firstItem as? UILayoutGuide,
layoutGuide.layoutFrame.maxX > navigationBar.frame.midX {
// is rightItems
if needAdjustRightItems {
cst.constant = rightConstant
}
}
default: break
}
})
// ensure items space == 8, minispcae
contentView.subviews.forEach(
{ subsub in
guard subsub is UIStackView else { return }
subsub.constraints.forEach(
{ cst in
guard cst.firstAttribute == .width
|| cst.secondAttribute == .width
else { return }
cst.constant = 0
})
})
} else {
// iOS < 11
let versionItemsCount: Int
if systemMajorVersion == 10 {
// iOS 10 navigationItem.rightBarButtonItems == 0
// space = 16(320|375) / 20(414)
// should adjust margin
versionItemsCount = 0
} else {
// iOS 9 navigationItem.rightBarButtonItems == 0
// space = 8(320|375) / 12(414)
// should not adjust margin
versionItemsCount = 1
}
let spaceProducer = { () -> UIBarButtonItem in
let spaceItem = UIBarButtonItem(
barButtonSystemItem: .fixedSpace,
target: nil,
action: nil)
spaceItem.width = margin - 16
return spaceItem
}
if let currentVC = viewControllers.last,
var rightItems = currentVC.navigationItem.rightBarButtonItems,
rightItems.count > versionItemsCount,
let first = rightItems.first {
// ensure the first BarButtonItem is NOT fixedSpace
if first.title == nil && first.image == nil && first.customView == nil {
print("rightBarButtonItems SPACE SETTED!!! SPACE: ", abs(first.width))
} else {
rightItems.insert(spaceProducer(), at: 0)
// arranged right -> left
currentVC.navigationItem.rightBarButtonItems = rightItems
}
}
if let currentVC = viewControllers.last,
var leftItems = currentVC.navigationItem.leftBarButtonItems,
leftItems.count > versionItemsCount,
let first = leftItems.first {
if first.title == nil && first.image == nil && first.customView == nil {
print("leftBarButtonItems SPACE SETTED!!! SPACE: ", abs(first.width))
} else {
leftItems.insert(spaceProducer(), at: 0)
// arranged left -> right
currentVC.navigationItem.leftBarButtonItems = leftItems
}
}
}
}
}
// do precise layout
class ViewController: UIViewController {
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
navigationController?.fixNavigationItemsMargin(40)
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
navigationController?.fixNavigationItemsMargin(40)
}
Ответ 9
Нашел сумасшедшую идею, которая работает.
func createCustomToolbar(items: [UIBarButtonItem]) -> UIToolbar
{
// no spacing between bar buttons
let customToolbar = UIToolbar(frame: CGRect(x: 0, y: 0, width: items.count*45, height: 44))
customToolbar.items = items
customToolbar.barStyle = UIBarStyle(rawValue: -1)!
customToolbar.clearsContextBeforeDrawing = false
customToolbar.backgroundColor = UIColor.clearColor()
customToolbar.tintColor = UIColor.clearColor()
customToolbar.translucent = true
return customToolbar
}
let customToolbar = createCustomToolbar([item0,item1,item2,item3])
navigationItem.rightBarButtonItems = [UIBarButtonItem(customView: customToolbar)]
Протестировано на iOS7 и в верхней части. Даже это написано быстро, концепция понятна.
Ответ 10
Я отказался от борьбы с этой ошибкой и придумал следующее расширение:
import UIKit
extension UIBarButtonItem {
convenience init(buttonImage: UIImage?, target: Any?, action: Selector?) {
let button = UIButton(type: .system)
button.frame = CGRect(origin: CGPoint.zero, size: buttonImage != nil ? buttonImage!.size : CGSize.zero)
button.setImage(buttonImage, for: .normal)
if let action = action {
button.addTarget(target, action: action, for: .touchUpInside)
}
self.init(customView: button)
}
public func updateButton(image: UIImage?) {
if let button = self.customView as? UIButton {
button.setImage(image, for: .normal)
let size = image != nil ? image!.size : CGSize.zero
let frame = button.frame
button.frame = frame.insetBy(dx: ceil((frame.size.width - size.width) / 2), dy: ceil((frame.size.height - size.height) / 2))
}
}
}
Ответ 11
Первый:
Для UIBarButtonItem
вы должны пользовательский конструктор init(customView: UIView)
Во-вторых:
Используйте fixedSpace
для установки пространства между кнопками
пример:
let firstButton = UIButton()
let firstButtonItem = UIBarButtonItem(customView: firstButton)
let secondButton = UIButton()
let secondButtonItem = UIBarButtonItem(customView: secondButton)
let space = UIBarButtonItem(barButtonSystemItem: .fixedSpace, target: nil, action: nil)
space.width = WIDTH
self.navigationItem.rightBarButtonItems = [firstButtonItem, space, secondButtonItem]
Ответ 12
Мое решение заключается в использовании пользовательского представления для кнопок правой панели. Создайте горизонтальное представление стека с равным интервалом и добавьте любое количество кнопок в качестве подпредставления.
Образец кода:
func addRightBarButtonItems()
{
let btnSearch = UIButton.init(type: .custom)
btnSearch.setImage(UIImage(named: "icon-search"), for: .normal)
btnSearch.addTarget(self, action: #selector(MyPageContainerViewController.searchButtonPressed), for: .touchUpInside)
let btnEdit = UIButton.init(type: .custom)
btnEdit.setImage(UIImage(named: "icon-edit"), for: .normal)
btnEdit.addTarget(self, action: #selector(MyPageContainerViewController.editButtonPressed), for: .touchUpInside)
let stackview = UIStackView.init(arrangedSubviews: [btnEdit, btnSearch])
stackview.distribution = .equalSpacing
stackview.axis = .horizontal
stackview.alignment = .center
stackview.spacing = 8
let rightBarButton = UIBarButtonItem(customView: stackview)
self.navigationItem.rightBarButtonItem = rightBarButton
}