Изменение положения UIBarButtonItem в UINavigationBar


Как я могу изменить положение UIBarButtonItem в UINavigationBar? Я хотел бы, чтобы моя кнопка была примерно на 5px выше, чем ее нормальное положение.

18 61

18 ответов:

нет особенно хорошего способа сделать это. Ваш лучший выбор, если вы действительно должны это подкласс UINavigationBar, и переопределить layoutSubviews называть [super layoutSubviews] а затем найти и изменить вид кнопки.

этот код создает кнопку Назад для UINavigationBar с фоном изображения и пользовательской позиции. Хитрость заключается в том, чтобы создать промежуточный вид и изменить его границы.

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;

Я решил с помощью преобразования и пользовательского представления:

(Swift)

  // 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

для тех из вас, кто разрабатывал для iOS 5, кто наткнулся на это и был обескуражен... Попробуйте что-то вроде этого:

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];

лучший способ-это подкласс вашего UINavigationBar, как описано здесь:https://stackoverflow.com/a/17434530/1351190

вот мой пример:

#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

надеюсь, что это помогает.

попробуйте код ниже

UIBarButtonItem *button = [[UIBarButtonItem alloc] initWithTitle:@"Logout" style:UIBarButtonItemStyleDone target:self action:nil];
[button setBackgroundVerticalPositionAdjustment:-20.0f forBarMetrics:UIBarMetricsDefault];
[[self navigationItem] setRightBarButtonItem:button];

используется для изменения позиции ' y ' в этом коде. Измените значение ' y ' (здесь оно -20.0 f) согласно вашему требованию. Если значение положительное, он будет вниз положение кнопки. Если значение отрицательное, он будет до вашего положения кнопки.

Мне нужно, чтобы установить мою кнопку, чтобы быть более вправо. Вот как я это сделал, используя UIAppearance в Swift. Там также есть свойство вертикального положения, поэтому я думаю, что вы можете настроить в любом направлении.

UIBarButtonItem.appearance().setTitlePositionAdjustment(UIOffset.init(horizontal: 15, vertical: 0), forBarMetrics: UIBarMetrics.Default)

Это кажется мне гораздо менее инвазивным, чем возиться с кадром напрямую или добавлять пользовательские подвиды.

Если вы просто используете изображение, а не chrome по умолчанию, вы можете использовать отрицательные вставки изображений (установленные в инспекторе размеров) для перемещения изображения внутри UIBarButtonItem (удобно, потому что по умолчанию горизонтальное заполнение может привести к тому, что изображение будет дальше внутри, чем вы хотите). Вы можете использовать вставки изображения для размещения изображения за пределами границ UIBarButtonItem, а также всю окрестность левой боковой кнопки можно нажать, так что вы не нужно беспокоиться о том, что он расположен рядом с целью крана. (по крайней мере, в разумных пределах.)

лучшее решение, которое я мог бы найти, - это инициализация UIBarButtonItem с подвидом, который включает дополнительное пространство слева/справа. Таким образом, вам не придется беспокоиться о подклассах и изменении компоновки других элементов внутри панели навигации, таких как заголовок.

например, чтобы переместить кнопку 14 точек влево:

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: Установите позицию заголовка с помощью API внешнего вида. Например, в AppDelegate didFinishLaunchingWithOptions

UINavigationBar.appearance().setTitleVerticalPositionAdjustment(-7, for: .default)

Шаг 2: Подкласс 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)
            }
        }
    }
}

как сказал @ Anomie, нам нужно подкласс UINavigationBar, и переопределить layoutSubviews().

Это разместит все элементы кнопки правой панели, прочно прикрепленные к правой стороне панели навигации (в отличие от слегка левому краю по умолчанию):

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)
                }

            }
        }
    }
}

единственное место для установки свойства UINavigationBar UINavigationController находится в его init (), например:

let controllerVC = UINavigationController(navigationBarClass: AdjustedNavigationBar.self, toolbarClass: nil)
controllerVC.viewControllers = [UIViewController()]

вторая строка задает корень смотреть контроллер UINavigationController. (так как мы не можем установить его через init(rootViewController:)

Swift 3.1

let cancelBarButtonItem = UIBarButtonItem()
cancelBarButtonItem.setBackgroundVerticalPositionAdjustment(4, for: .default)
vc.navigationItem.setLeftBarButton(cancelBarButtonItem, animated: true)

вот решение Адриано с помощью Swift 3. Это было единственное решение, которое сработало для меня, и я попробовал несколько.

  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

В моем случае

  1. измените рамку barbuttonItem, чтобы настроить пробелы

  2. добавить, удалить barButtonItems динамически.

  3. изменить оттенок цвета по contentOffset tableview.г

такой enter image description here enter image description here

enter image description here enter image description here

Если ваша минимальная цель iOS 11, вы можете изменить кадры barButton в 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)
    }
}

но, это работает только на iOS 11.

Я также попытался использовать fixedSpace. Но он не работал в нескольких элементах navigationBarButton.

 let space = UIBarButtonItem(barButtonSystemItem: .fixedSpace, target: nil, action: nil)
    space.width = -10

Итак, я изменил ширину customView, чтобы настроить горизонтальное пространство.

Это один из моих 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
}
}

это и есть результат.

Я тестировал на iOS 9 ~ 11, (Swift 4)

enter image description here

Init UIBarButtonItem с пользовательским представлением и перегрузкой layoutSubviews в пользовательском представлении, как это

-(void) layoutSubviews {
  [super layoutSubviews];
  CGRect frame = self.frame;
  CGFloat offsetY = 5;
  frame.origin.y = (44 - frame.size.height) / 2 - offsetY;
  self.frame = frame;
}

вы всегда можете сделать настройки с помощью вставок на кнопке. Например,

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];

это работает для меня.

вот простой обходной путь, который был достаточно для моих потребностей. Я добавил информационную кнопку на правой стороне панели UINavigationBar, но по умолчанию она сидит слишком близко к краю. Расширяя ширину рамки, я смог создать дополнительный интервал, необходимый справа.

 UIButton *info = [UIButton buttonWithType:UIButtonTypeInfoLight];
 CGRect frame = info.frame;
 frame.size.width += 20;
 info.frame = frame;
 myNavigationItem.rightBarButtonItem = [[[UIBarButtonItem alloc]initWithCustomView:info]autorelease];

Я нашел решение этой проблемы, сделав настройку в краевых вставках изображения пользовательской кнопки. У меня было требование в приложении, чтобы увеличить высоту панели навигации и после увеличения высоты делает rightBarButtonItem и leftBarButtonItem изображения непозиционные проблемы.

найти код ниже:

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;

надеюсь, это поможет кому-нибудь.