Change position of UIBarButtonItem in UINavigationBar

后端 未结 20 1349
一个人的身影
一个人的身影 2020-11-27 10:31

How can I change the position of a UIBarButtonItem in a UINavigationBar? I would like my button to be about 5px higher than its normal position.

相关标签:
20条回答
  • 2020-11-27 11:16

    Init UIBarButtonItem with custom view and overload layoutSubviews in custom view, like this

    -(void) layoutSubviews {
      [super layoutSubviews];
      CGRect frame = self.frame;
      CGFloat offsetY = 5;
      frame.origin.y = (44 - frame.size.height) / 2 - offsetY;
      self.frame = frame;
    }
    
    0 讨论(0)
  • 2020-11-27 11:17

    There is no particularly good way to do this. Your best bet if you really must is to subclass UINavigationBar, and override layoutSubviews to call [super layoutSubviews] and then find and reposition the button's view.

    0 讨论(0)
  • 2020-11-27 11:18

    This code creates a back button for UINavigationBar with image background and custom position. The trick is to create an intermediate view and modify its bounds.

    Swift 5

    let menuBtn = UIButton(type: .custom)
    let backBtnImage = UIImage(named: "menu")
    
    menuBtn.setBackgroundImage(backBtnImage, for: .normal)
    menuBtn.addTarget(self, action: #selector(showMenuTapped), for: .touchUpInside)
    menuBtn.frame = CGRect(x: 0, y: 0, width: 45, height: 45)
    
    let view = UIView(frame: CGRect(x: 0, y: 0, width: 45, height: 45))
    view.bounds = view.bounds.offsetBy(dx: 10, dy: 3)
    view.addSubview(menuBtn)
    let backButton = UIBarButtonItem(customView: view)
    
    navigationItem.leftBarButtonItem = backButton
    

    Objective C

    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;
    
    0 讨论(0)
  • 2020-11-27 11:18

    As @Anomie said, we need to subclass UINavigationBar, and override layoutSubviews().

    This will place all right bar button items firmly attached to the right side of the navigation bar (as opposed to being slightly left-adjusted by default):

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

    The only place to set the UINavigationBar property of UINavigationController is in its init(), like so:

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

    The second line sets the root view controller of UINavigationController. (Since we cannot set it via init(rootViewController:)

    0 讨论(0)
  • 2020-11-27 11:19

    The best way is to subclass your UINavigationBar, as described here: https://stackoverflow.com/a/17434530/1351190

    Here is my example:

    #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
    

    Hope it helps.

    0 讨论(0)
  • 2020-11-27 11:19

    Navigation bar using change left bar position and image edge insets

    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)
    
    0 讨论(0)
提交回复
热议问题