web-dev-qa-db-ja.com

UINavigationBarのUIBarButtonItemの位置を変更します

UINavigationBarのUIBarButtonItemの位置を変更するにはどうすればよいですか?ボタンを通常の位置よりも約5ピクセル高くしたいです。

64
Ben Williams

これを行うための特に良い方法はありません。本当に必要な場合の最善の策は、UINavigationBarをサブクラス化し、layoutSubviewsをオーバーライドして[super layoutSubviews]を呼び出し、ボタンのビューを見つけて再配置することです。

34
Anomie

このコードは、画像の背景とカスタム位置を持つ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;
119

変換とカスタムビューを使用して解決しました。

(迅速)

  // 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
39
Adriano Spadoni

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];
17
Joe Marx

最善の方法は、ここで説明するように、UINavigationBarをサブクラス化することです。 https://stackoverflow.com/a/17434530/135119

これが私の例です:

#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

それが役に立てば幸い。

12
Simone Lai

私はボタンを右に向けてもっと上に設定する必要がありました。 SwiftでUIAppearanceを使用してどのように実行したかを示します。縦位置プロパティもありますので、どの方向にも調整できると思います。

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

これは、フレームを直接いじったり、カスタムサブビューを追加したりするよりもはるかに侵襲性が低いようです。

6
Mark Bridges

以下のコードを試してください、

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.0f)を変更します。値が正の場合、ボタンの位置を下げます。値が負の場合、ボタンの位置が上がります。

6
Augustine P A

デフォルトのクロムではなく単に画像を使用している場合は、負の画像インセット(サイズインスペクターで設定)を使用して画像を移動できますinside UIBarButtonItem(デフォルトでは水平方向のパディングのため便利です)画像が必要以上に内側になる可能性があります)。画像インセットを使用して、画像をUIBarButtonItemの境界の外側に配置することもできます。また、左側のボタンの周辺全体がタップ可能です。そのため、画像の近くに配置することを心配する必要はありません。ターゲットをタップします。 (少なくとも、合理的な範囲内で。)

4
  • スイフト3
  • カスタムナビゲーションバーの高さ
  • タイトルジャンプなし

ステップ1: Appearance 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)
            }
        }
    }
}
3
andriy_fedin

私が見つけることができる最良の解決策は、左/右に余分なスペースを含むサブビューで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];
3
Jorge Aguirre

Swift 3.1

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

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
2
JP Aquino

@Anomieが言ったように、サブクラスUINavigationBarlayoutSubviews()をオーバーライドする必要があります。

これにより、すべての右バーボタンアイテムがナビゲーションバーの右側にしっかりと接続されます(デフォルトでわずかに左に調整されるのではなく)

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

            }
        }
    }
}
_

UINavigationControllerのUINavigationBarプロパティを設定する唯一の場所は、次のようにinit()にあります。

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

2行目は、UINavigationControllerのroot View Controllerを設定します。 init(rootViewController:)で設定できないため

2
Zoltán Matók

私の場合

  1. スペースをカスタマイズするためにbarbuttonItemのフレームを変更します

  2. BarButtonItemsを動的に追加、削除します。

  3. tableviewのcontentOffset.yによって色合いを変更します

このような - enter image description hereenter image description here

enter image description hereenter image description here

最小ターゲットがiOS 11の場合、viewDidLayoutSubviewsのbarButtonフレームを変更できます

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の幅を変更して水平方向のスペースを調整しました。

これはmy barButtonItemクラスの1つです

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

2
Den

次のように、カスタムビューで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;
}
1
alex1704

ボタンのインセットを使用していつでも調整を行うことができます。例えば、

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

わたしにはできる。

1
Joe M

左のバーの位置の変更と画像のエッジインセットを使用したナビゲーションバー

スイフト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
CSE 1994

アフィン変換は必要なことを実行できます。私の場合、デザイナーは16x16の閉じるアイコンをくれたので、44x44のタップ領域を作成したいと思います。

closeButton.transform = CGAffineTransform(translationX: (44-16)/2, y: 0)
closeButton.snp.makeConstraints { make in
   make.size.equalTo(CGSize(width: 44, height: 44))
}
self.navigationItem.rightBarButtonItem = UIBarButtonItem(customView: closeButton)
0
vdugnist

これが私のニーズに十分な簡単な回避策です。 UINavigationBarの右側に情報ボタンを追加しましたが、デフォルトではEdgeに近すぎます。フレームの幅を広げることで、右側に必要な余分なスペースを作成することができました。

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

カスタムボタンのイメージエッジインセットを調整することで、この問題の解決策を見つけました。アプリにはナビゲーションバーの高さを増やす必要があり、高さを増やした後、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;

これが誰にも役立つことを願っています。

0
iGW