Comment puis-je changer la position d'un UIBarButtonItem dans un UINavigationBar? Je voudrais que mon bouton soit environ 5px plus élevé que sa position normale.
Il n'y a pas de moyen particulièrement efficace de le faire. Votre meilleur choix si vous devez vraiment est de sous-classer UINavigationBar et de remplacer layoutSubviews
pour appeler [super layoutSubviews]
, puis de rechercher et de repositionner la vue du bouton.
Ce code crée un bouton de retour pour UINavigationBar avec un fond d’image et une position personnalisée. L'astuce consiste à créer une vue intermédiaire et à modifier ses limites.
UIButton *backBtn = [UIButton buttonWithType:UIButtonTypeCustom];
UIImage *backBtnImage = [UIImage imageNamed:@"btn-back"];
UIImage *backBtnImagePressed = [UIImage imageNamed:@"btn-back-pressed"];
[backBtn setBackgroundImage:backBtnImage forState:UIControlStateNormal];
[backBtn setBackgroundImage:backBtnImagePressed forState:UIControlStateHighlighted];
[backBtn addTarget:self action:@selector(goBack) forControlEvents:UIControlEventTouchUpInside];
backBtn.frame = CGRectMake(0, 0, 63, 33);
UIView *backButtonView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 63, 33)];
backButtonView.bounds = CGRectOffset(backButtonView.bounds, -14, -7);
[backButtonView addSubview:backBtn];
UIBarButtonItem *backButton = [[UIBarButtonItem alloc] initWithCustomView:backButtonView];
self.navigationItem.leftBarButtonItem = backButton;
J'ai résolu l'utilisation de la transformation et de la vue personnalisée:
(Rapide)
// create the button
let suggestImage = UIImage(named: "tab-item-popcorn-on")!.imageWithRenderingMode(.AlwaysOriginal)
let suggestButton = UIButton(frame: CGRectMake(0, 0, 40, 40))
suggestButton.setBackgroundImage(suggestImage, forState: .Normal)
suggestButton.addTarget(self, action: Selector("suggesMovie:"), forControlEvents:.TouchUpInside)
// here where the magic happens, you can shift it where you like
suggestButton.transform = CGAffineTransformMakeTranslation(10, 0)
// add the button to a container, otherwise the transform will be ignored
let suggestButtonContainer = UIView(frame: suggestButton.frame)
suggestButtonContainer.addSubview(suggestButton)
let suggestButtonItem = UIBarButtonItem(customView: suggestButtonContainer)
// add button shift to the side
navigationItem.rightBarButtonItem = suggestButtonItem
Pour ceux d'entre vous développant pour iOS 5 qui ont trébuché sur cela et ont été découragés ... Essayez quelque chose comme ça:
float my_offset_plus_or_minus = 3.0f;
UIBarButtonItem * item = [[UIBarButtonItem alloc] initWithTitle:@"title"
style:UIBarButtonItemStyleDone
target:someObject action:@selector(someMessage)];
[item setBackgroundVerticalPositionAdjustment:my_offset_plus_or_minus forBarMetrics:UIBarMetricsDefault];
Le meilleur moyen consiste à sous-classer votre UINavigationBar, comme décrit ici: https://stackoverflow.com/a/17434530/1351190
Voici mon exemple:
#define NAVIGATION_BTN_MARGIN 5
@implementation NewNavigationBar
- (void)layoutSubviews {
[super layoutSubviews];
UINavigationItem *navigationItem = [self topItem];
UIView *subview = [[navigationItem rightBarButtonItem] customView];
if (subview) {
CGRect subviewFrame = subview.frame;
subviewFrame.Origin.x = self.frame.size.width - subview.frame.size.width - NAVIGATION_BTN_MARGIN;
subviewFrame.Origin.y = (self.frame.size.height - subview.frame.size.height) / 2;
[subview setFrame:subviewFrame];
}
subview = [[navigationItem leftBarButtonItem] customView];
if (subview) {
CGRect subviewFrame = subview.frame;
subviewFrame.Origin.x = NAVIGATION_BTN_MARGIN;
subviewFrame.Origin.y = (self.frame.size.height - subview.frame.size.height) / 2;
[subview setFrame:subviewFrame];
}
}
@end
J'espère que ça aide.
Je devais régler mon bouton pour être plus vers la droite. Voici comment je l'ai fait en utilisant UIAppearance dans Swift. Il existe également une propriété de position verticale, alors j'imagine que vous pouvez vous ajuster dans n'importe quelle direction.
UIBarButtonItem.appearance().setTitlePositionAdjustment(UIOffset.init(horizontal: 15, vertical: 0), forBarMetrics: UIBarMetrics.Default)
Cela me semble beaucoup moins invasif que de jouer directement avec le cadre ou d'ajouter des sous-vues personnalisées.
Essayez le code ci-dessous,
UIBarButtonItem *button = [[UIBarButtonItem alloc] initWithTitle:@"Logout" style:UIBarButtonItemStyleDone target:self action:nil];
[button setBackgroundVerticalPositionAdjustment:-20.0f forBarMetrics:UIBarMetricsDefault];
[[self navigationItem] setRightBarButtonItem:button];
Il est utilisé pour changer la position 'y' dans ce code. Modifiez la valeur 'y' (ici -20.0f) en fonction de vos besoins. Si la valeur est positive, la position du bouton sera abaissée. Si la valeur est négative, cela augmentera la position de votre bouton.
Si vous utilisez simplement une image et non le chrome par défaut, vous pouvez utiliser des encarts d’image négatifs (définis dans l’inspecteur de taille) pour déplacer votre image dans l’UIBarButtonItem (pratique, car par défaut le remplissage horizontal peut l'image étant plus à l'intérieur que vous le souhaitez). Vous pouvez également utiliser les encarts d'image pour positionner l'image en dehors des limites de UIBarButtonItem. De plus, tout le voisinage du bouton situé à gauche est encliquetable. Vous n'avez donc pas à vous soucier de le positionner près d'un appuyez sur la cible. (du moins dans les limites du raisonnable.)
Étape 1: Définissez la position du titre à l'aide de l'API d'apparence. Par exemple, dans didFinishLaunchingWithOptions de AppDelegate
UINavigationBar.appearance().setTitleVerticalPositionAdjustment(-7, for: .default)
Étape 2: Sous-classe UINavigationBar
class YourNavigationBar: UINavigationBar {
let YOUR_NAV_BAR_HEIGHT = 60
override func sizeThatFits(_ size: CGSize) -> CGSize {
return CGSize(width: UIScreen.main.bounds.width,
height: YOUR_NAV_BAR_HEIGHT)
}
override func layoutSubviews() {
super.layoutSubviews()
let navigationItem = self.topItem
for subview in subviews {
if subview == navigationItem?.leftBarButtonItem?.customView ||
subview == navigationItem?.rightBarButtonItem?.customView {
subview.center = CGPoint(x: subview.center.x, y: YOUR_NAV_BAR_HEIGHT / 2)
}
}
}
}
La meilleure solution que je puisse trouver consiste à initialiser un UIBarButtonItem avec une sous-vue comprenant un espace supplémentaire à gauche/à droite. Ainsi, vous n'aurez pas à vous préoccuper des sous-classes et de la disposition des autres éléments de la barre de navigation, tels que le titre.
Par exemple, pour déplacer un bouton de 14 points à gauche:
UIView *containerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, image.size.width + 14, image.size.height)];
UIButton* button = [UIButton buttonWithType:UIButtonTypeCustom];
button.frame = CGRectMake(-14, 0, image.size.width, image.size.height);
[button setImage:image forState:UIControlStateNormal];
[button addTarget:target action:action forControlEvents:UIControlEventTouchUpInside];
[containerView addSubview:button];
UIButton* button2 = [UIButton buttonWithType:UIButtonTypeCustom];
button2.frame = CGRectMake(0, 0, image.size.width + 14, image.size.height);
[button2 addTarget:target action:action forControlEvents:UIControlEventTouchUpInside];
[containerView addSubview:button2];
UIBarButtonItem* item = [[[self alloc] initWithCustomView:containerView] autorelease];
Swift 3.1
let cancelBarButtonItem = UIBarButtonItem()
cancelBarButtonItem.setBackgroundVerticalPositionAdjustment(4, for: .default)
vc.navigationItem.setLeftBarButton(cancelBarButtonItem, animated: true)
Voici la solution d'Adriano utilisant Swift 3. C'était la seule solution qui fonctionnait pour moi et j'ai essayé plusieurs solutions.
let suggestImage = UIImage(named: "menu.png")!
let suggestButton = UIButton(frame: CGRect(x:0, y:0, width:34, height:20))
suggestButton.setBackgroundImage(suggestImage, for: .normal)
suggestButton.addTarget(self, action: #selector(self.showPopover(sender:)), for:.touchUpInside)
suggestButton.transform = CGAffineTransform(translationX: 0, y: -8)
// add the button to a container, otherwise the transform will be ignored
let suggestButtonContainer = UIView(frame: suggestButton.frame)
suggestButtonContainer.addSubview(suggestButton)
let suggestButtonItem = UIBarButtonItem(customView: suggestButtonContainer)
// add button shift to the side
navigationItem.leftBarButtonItem = suggestButtonItem
Comme @Anomie l'a dit, nous devons sous-classe UINavigationBar
, et remplacer layoutSubviews()
.
Cela placera tous les éléments de bouton de la barre de droite fermement attachés au côté droit de la barre de navigation (au lieu d'être légèrement ajustés à gauche par défaut):
class AdjustedNavigationBar: UINavigationBar {
override func layoutSubviews() {
super.layoutSubviews()
if let rightItems = topItem?.rightBarButtonItems where rightItems.count > 1 {
for i in 0..<rightItems.count {
let barButtonItem = rightItems[i]
if let customView = barButtonItem.customView {
let frame = customView.frame
customView.frame = CGRect(x: UIApplication.sharedApplication().windows.last!.bounds.size.width-CGFloat(i+1)*44, y: frame.Origin.y, width: frame.size.width, height: frame.size.height)
}
}
}
}
}
Le seul endroit où définir la propriété UINavigationBar de UINavigationController se trouve dans init (), comme suit:
let controllerVC = UINavigationController(navigationBarClass: AdjustedNavigationBar.self, toolbarClass: nil)
controllerVC.viewControllers = [UIViewController()]
La deuxième ligne définit le contrôleur de vue racine de UINavigationController .(nous ne pouvons pas le définir via init(rootViewController:)
Dans mon cas
changer le cadre de barbuttonItem pour personnaliser les espaces
Ajouter, supprimer barButtonItems dynamiquement.
changer les couleurs de teinte par contentOffset.y de tableview
Si votre cible minimale est iOS 11, vous pouvez modifier les images barButton dans le viewDidLayoutSubviews.
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
// Change the navigationBar item frames
if let customView = wishButton.customView?.superview {
customView.transform = CGAffineTransform(translationX: 7.0, y: 0)
}
if let customView = gourmetCountButton.customView?.superview {
customView.transform = CGAffineTransform(translationX: 9.0, y: 0)
}
}
Mais cela ne fonctionne que sur iOS 11.
J'ai aussi essayé d'utiliser le fixedSpace. Mais cela ne fonctionnait pas dans plusieurs éléments navigationBarButton.
let space = UIBarButtonItem(barButtonSystemItem: .fixedSpace, target: nil, action: nil)
space.width = -10
Alors, j'ai changé la largeur de customView pour ajuster l'espace horizontal.
C'est l'un des cours de ma classe barButtonItem
final class DetailShareBarButtonItem: UIBarButtonItem {
// MARK: - Value
// MARK: Public
***// Change the width to adjust space***
let button = UIButton(frame: CGRect(x: 0, y: 0, width: 32.0, height: 30.0))
override var tintColor: UIColor? {
didSet {
button.tintColor = tintColor
}
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
setButton()
}
required override init() {
super.init()
setButton()
}
// MARK: - Function
// MARK: Private
private func setButton() {
// Button
button.setImage( #imageLiteral(resourceName: "navibarIcShare02White").withRenderingMode(.alwaysTemplate), for: .normal)
button.tintColor = .white
button.imageEdgeInsets = UIEdgeInsetsMake(0, 1.0, 1.0, 0)
button.imageView?.contentMode = .scaleAspectFill
let containerView = UIView(frame: button.bounds)
containerView.backgroundColor = .clear
containerView.addSubview(button)
customView = containerView
}
}
C'est le résultat.
J'ai testé sur iOS 9 ~ 11, (Swift 4)
Init UIBarButtonItem
avec vue personnalisée et surcharge layoutSubviews
en vue personnalisée, comme ceci
-(void) layoutSubviews {
[super layoutSubviews];
CGRect frame = self.frame;
CGFloat offsetY = 5;
frame.Origin.y = (44 - frame.size.height) / 2 - offsetY;
self.frame = frame;
}
Vous pouvez toujours faire des ajustements en utilisant Inserts sur le bouton. Par exemple,
UIButton *toggleBtn = [UIButton buttonWithType:UIButtonTypeCustom];
[toggleBtn setFrame:CGRectMake(0, 0, 20, 20)];
[toggleBtn addTarget:self action:@selector(toggleView) forControlEvents:UIControlEventTouchUpInside];
[toggleBtn setImageEdgeInsets:((IS_IPAD)? UIEdgeInsetsMake(0,-18, 0, 6) : UIEdgeInsetsMake(0, -3, 0, -3))];
UIBarButtonItem *toggleBtnItem = [[UIBarButtonItem alloc] initWithCustomView: toggleBtn];
self.navigationItem.rightBarButtonItems = [NSArray arrayWithObjects:searchBtnItem, toggleBtnItem, nil];
Ça marche pour moi.
Barre de navigation utilisant la modification de la position de la barre gauche et des incrustations d'image
Swift 4
let leftBarButtonItem = UIBarButtonItem.init(image: UIImage(named:"ic_nav-bar_back.png"), landscapeImagePhone: nil, style: .plain, target: viewController, action: #selector(viewController.buttonClick(_:)))
leftBarButtonItem.imageInsets = UIEdgeInsets(top: 0, left: -15, bottom: 0, right: 0)
leftBarButtonItem.tintColor = UIColor(hex: 0xED6E19)
viewController.navigationItem.setLeftBarButton(leftBarButtonItem, animated: true)
La transformation affine peut faire ce dont vous avez besoin. Dans mon cas, le concepteur m'a donné l'icône de fermeture 16x16 et je veux créer une zone de prise 44x44.
closeButton.transform = CGAffineTransform(translationX: 14, y: 0)
closeButton.snp.makeConstraints { make in
make.size.equalTo(CGSize(width: 44, height: 44))
}
self.navigationItem.rightBarButtonItem = UIBarButtonItem(customView: closeButton)
Voici une solution de contournement simple et suffisante pour mes besoins. J'ai ajouté un bouton d'information sur le côté droit de la barre UINavigationBar, mais par défaut, il se trouve trop près du bord. En étendant la largeur du cadre, j'ai pu créer l'espacement supplémentaire nécessaire à droite.
UIButton *info = [UIButton buttonWithType:UIButtonTypeInfoLight];
CGRect frame = info.frame;
frame.size.width += 20;
info.frame = frame;
myNavigationItem.rightBarButtonItem = [[[UIBarButtonItem alloc]initWithCustomView:info]autorelease];
J'ai trouvé la solution à ce problème en ajustant les incrustations d'image du bouton personnalisé. J'avais l'exigence dans l'application d'augmenter la hauteur de la barre de navigation et après l'augmentation de la hauteur, le problème sans positionnement des images rightBarButtonItem et leftBarButtonItem.
Trouvez le code ci-dessous: -
UIImage *image = [[UIImage imageNamed:@"searchbar.png"];
UIButton* searchbutton = [UIButton buttonWithType:UIButtonTypeCustom];
[searchbutton addTarget:self action:@selector(searchBar:) forControlEvents:UIControlEventTouchUpInside];
searchbutton.frame = CGRectMake(0,0,22, 22);
[searchbutton setImage:image forState:UIControlStateNormal];
[searchbutton setImageEdgeInsets:UIEdgeInsetsMake(-50, 0,50, 0)];
// Make BarButton Item
UIBarButtonItem *navItem = [[UIBarButtonItem alloc] initWithCustomView:searchbutton];
self.navigationItem.rightBarButtonItem = navItem;
J'espère que cela aide quelqu'un.