J'utilise les codes suivants pour ajouter deux boutons à self.navigationItem.rightBarButtonItems, et je pense que dans iOS7, l'espace entre deux boutons est trop large, existe-t-il un moyen de réduire l'espace entre ces deux boutons?
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;
Appréciez n'importe quel indice ou idée.
Mis à jour en juillet 2015
Une meilleure façon de faire est d’utiliser le storyboard (testé dans Xcode 6.4). Tout d'abord, ajoutez un UINavigationItem; deuxièmement, ajoutez un élément de bouton de barre; troisièmement, ajoutez une vue à l'élément de bouton de barre que vous venez de créer à l'étape 2; quatrièmement, ajoutez autant de boutons que vous le souhaitez dans la vue que vous venez de faire glisser; Enfin, ajustez l’espace avec votre souris et vos contraintes.
Questions connexes
Comment ajouter des boutons au contrôleur de navigation visibles après le classement?
Old Answer (Acceptable uniquement pour les petits encarts)
Utilisez la propriété imageInsets:
leftButton.imageInsets = UIEdgeInsetsMake(0.0, 0.0, 0, -15);
rightButton.imageInsets = UIEdgeInsetsMake(0.0, -15, 0, 0);
pour trois boutons ou plus, le ou les boutons du milieu reçoivent les deux incrustations:
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);
Faites attention aux boutons de droite: le bouton PREMIER du tableau d’éléments est le bouton DROIT:
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);
IMPORTANT: Séparez l’encart entre les deux voisins. si vous appliquez l'intégralité de l'encadré à un bord, il deviendra évident que les boutons se chevauchent dans l'espace "vide" - un bouton obtient toutes les touches "d'espace". Même en "divisant" le réglage comme celui-ci, à -40 sur les deux bords, le tap tapera parfois sur le mauvais bouton. -15 ou -20 est le plus à envisager avec cette technique.
En appliquant cette méthode, le bouton pourrait même être déplacé dans quatre directions.
Si vous souhaitez avoir 2 boutons en haut à droite, sans espace entre eux ou à droite, cela a fonctionné pour moi.
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 ]
Ma situation était de donner un espace horizontal pour logOut Button sur le bord droit.
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
}
Ma solution utilise un affichage personnalisé pour les boutons de la barre de droite. Créez un stackview horizontal avec un espacement égal et ajoutez autant de boutons que vous le souhaitez en tant que sous-vue.
Exemple de code:
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
}
Créez une UIBarButtonItem
avec le type flexible ou fixe. Définissez la largeur et ajoutez-la au tableau des éléments barbutton. Essayez d’utiliser une largeur négative pour voir si cela fonctionne.
Ou, vous pourriez peut-être ajuster votre image. Je pense que les boutons du système ont une taille fixe et peuvent inclure une partie transparente. Ainsi, même quand ils sont emballés, ils semblent toujours espacés.
Sans code. Je viens de mettre un autre UIBarButtonItem entre les boutons qui ont besoin d'espacement dans le storyboard. Le bouton est simplement un espace réservé pour l'espacement et UIBarButton doit avoir UIView comme sous-vue de UIBarButtonItem. ajustez la largeur de la vue pour votre espacement. Voir Captures d'écran.
Pour ce faire dans le code sans ajouter de vue de conteneur supplémentaire, utilisez une UIBarButtonItem
avec le type d'élément système défini sur FixedSpace
. Définissez ensuite la largeur de l’espace fixe sur -10
et placez-le entre les deux boutons.
Premier:
Pour UIBarButtonItem
, vous devez utiliser le constructeur init(customView: UIView)
Seconde:
Utilisez fixedSpace
pour définir l'espace entre les boutons
exemple:
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]
autre réponse: Cela fonctionne sous ios 9 - 12 . Vous devriez appeler fixNavigationItemsMargin (margin :) dans la fonction viewDidAppear (_ animated: Bool) et viewDidLayoutSubviews () .fixNavigationItemsMargin (margin :) modifierait la pile UINavigationController.
vous pouvez appeler fixNavigationItemsMargin (margin :) dans BaseNavigationController, effectuez le travail commun. Et appelez fixNavigationItemsMargin (margin :) dans UIViewController pour une mise en page précise.
// 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)
}
Trouvé une idée folle qui fonctionne.
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)]
Testé sur iOS7 et supérieur. Même si cela est écrit en Swift, le concept est clair.
J'ai abandonné la lutte contre ce bogue et j'ai proposé l'extension suivante:
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))
}
}
}