次のコードは、iOS 6まで機能します。
UIButton *myButton = nil;
myButton = [UIButton buttonWithType:UIButtonTypeCustom];
myButton.bounds = CGRectMake(0,0,44,30);
// setup myButton's images, etc.
UIBarButtonItem *item = nil;
item = [[UIBarButtonItem alloc] initWithCustomView:customButton];
これはボタンがどのように整列されることになっているかです:
ただし、iOS 7では、ボタンが多すぎるピクセルだけ右または左からオフセットされているように見えます。
カスタムバーボタン項目を適切に配置するにはどうすればよいですか?
このバグを修正するには、UIButtonをサブクラス化して、alignmentRectInsets
をオーバーライドできるようにする必要があります。私のテストでは、ボタンの位置に応じて、正の右オフセットまたは正の左オフセットのいずれかでUIEdgeInsetsを返す必要があります。これらの数字は私には意味がありません(常識によれば、少なくとも1つは負でなければなりません)が、これは実際に機能するものです:
- (UIEdgeInsets)alignmentRectInsets {
UIEdgeInsets insets;
if (IF_ITS_A_LEFT_BUTTON) {
insets = UIEdgeInsetsMake(0, 9.0f, 0, 0);
}
else { // IF_ITS_A_RIGHT_BUTTON
insets = UIEdgeInsetsMake(0, 0, 0, 9.0f);
}
return insets;
}
AlignmentRectInsetsの調整を提案してくれた@zevに特に感謝します。
IOS11まで動作します!
RightBarButtonItemの代わりに、ネガティブフレキシブルスペースとrightBarButtonItemsプロパティを使用できます。
UIBarButtonItem *spacer = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFixedSpace target:nil action:nil];
spacer.width = -10; // for example shift right bar button to the right
self.navigationItem.rightBarButtonItems = @[spacer, yourBarButton];
上記の答えをすべて試してみましたが、うまくいきませんでした。そして、もし誰かがこれを必要とするなら、ここに働くものがあります:
(サブクラス化は不要)
// Add your barButtonItem with custom image as the following
UIBarButtonItem *barButton = [[UIBarButtonItem alloc] initWithTitle:@"" style:UIBarButtonItemStyleBordered target:self action:@selector(categoryButtonPressed)];
// set your custom image
[barButton setImage:categoryImage];
// finally do the magic
barButton.imageInsets = UIEdgeInsetsMake(0.0, -20, 0, 0);
-結果を見てください。
左ボタンと右ボタンのスペースに注意してください(右ボタンにはデフォルトの動作があります)
わかりました、私は他の「方向」に行きました。 iOS 7のStoryboardを介してすべてを適切に整列させました(これが引き続き機能することを前提としています)。そして、サブクラス記述アプローチを使用して、次の実装でUIButton
をサブクラス化します。
- (UIEdgeInsets)alignmentRectInsets {
UIEdgeInsets insets;
if (SYSTEM_VERSION_LESS_THAN(@"7.0")) {
if ([self isLeftButton]) {
insets = UIEdgeInsetsMake(0, -10, 0, 0);
} else {
insets = UIEdgeInsetsMake(0, 0, 0, -10);
}
} else {
insets = UIEdgeInsetsZero;
}
return insets;
}
- (BOOL)isLeftButton {
return self.frame.Origin.x < (self.superview.frame.size.width / 2);
}
したがって、このコードは、デバイスがiOS 7より前の場合にのみ実行されます。
洞察力@jaredsinclairをありがとう!
しゅう
これが私のコードです。
// Create the tweetly button that will show settings
self.tweetlyDisplay = [NavButton buttonWithType:UIButtonTypeCustom];
[self.tweetlyDisplay setFrame:CGRectMake(0, 0, 90, 44)];
[self.tweetlyDisplay setBackgroundColor:[UIColor clearColor]];
[self.tweetlyDisplay setBackgroundImage:[UIImage imageNamed:@"settings.png"] forState:UIControlStateNormal];
[self.tweetlyDisplay setAdjustsImageWhenHighlighted:NO];
[self.tweetlyDisplay addTarget:self action:@selector(tweetlyPressed:) forControlEvents:UIControlEventTouchUpInside];
// Add the Tweetly button as the left bar button item
// This had a glitch that moves the image to the right somewhat
UIBarButtonItem *leftBarButton = [[UIBarButtonItem alloc] initWithCustomView:self.tweetlyDisplay];
self.navigationItem.leftBarButtonItem = leftBarButton;
正しくないものがありますか?
結果は次のとおりです。 2番目の画像は、スクリーンショットを撮る必要があり、まだ移行中なので、あまり見えませんが、不適切にオフセットされていることがはっきりとわかります。
正常な画像:
悪いオフセット画像:
約0.5秒後、画像は元の画像の場所にスナップします。
NavButton.hおよび.mのコードは次のとおりです。
/**********************************************
NavButton.h
**********************************************/
#import <UIKit/UIKit.h>
@interface NavButton : UIButton
@end
/**********************************************
NavButton.m
**********************************************/
#import "NavButton.h"
@implementation NavButton {
int imageHeight;
}
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
imageHeight = 44;
}
return self;
}
/*
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect
{
// Drawing code
}
*/
- (UIEdgeInsets)alignmentRectInsets {
UIEdgeInsets insets;
if ([self isLeftButton]) {
insets = UIEdgeInsetsMake(0, 9.0f, 0, 0);
}
else { // IF ITS A RIGHT BUTTON
insets = UIEdgeInsetsMake(0, 0, 0, 9.0f);
}
return insets;
}
- (BOOL)isLeftButton {
return self.frame.Origin.x < (self.superview.frame.size.width / 2);
}
// THIS IS THE TRICK. We make the height of the background rect match the image.
-(CGRect)backgroundRectForBounds:(CGRect)bounds
{
CGRect bgRect = bounds;
bgRect.Origin.y = (bounds.size.height - imageHeight)/2.0f;
bgRect.size.height = imageHeight;
return bgRect;
}
@end
周りにボタンをジャンプすることなく、より良いソリューションを見つけることができます:
サブクラス化UIButton
やマリウスの答えからスウィズルするメソッドの大ファンではありません: https://stackoverflow.com/a/19317105/2874
単純なラッパーを使用し、正しい位置が見つかるまでボタンのフレームのxを負の方向に移動しました。ボタンのタップも同様に良好に見えます(ただし、必要に応じて、ボタンの幅を拡張して負のオフセットに一致させることもできます)。
新しい戻るボタンを生成するために使用するコードは次のとおりです。
- (UIBarButtonItem *) newBackButton {
// a macro for the weak strong dance
@weakify(self);
UIButton *backButton = [[UIButton alloc] init];
[backButton setTitle:@"Back" forState:UIControlStateNormal];
backButton.titleLabel.font = [UIFont systemFontOfSize:17];
CGFloat width = [@"Back" boundingRectWithSize:CGSizeMake(CGFLOAT_MAX, CGFLOAT_MAX) options:NSStringDrawingUsesFontLeading|NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName: [UIFont systemFontOfSize:17]} context:nil].size.width + 27;
backButton.frame = CGRectMake(-17.5, 0, width + 17.5, 44);
[backButton setImage:[UIImage imageNamed:@"UINavigationBarBackIndicatorDefault"] forState:UIControlStateNormal];
[backButton setTitleEdgeInsets:UIEdgeInsetsMake(0, 14, 0, 0)];
[backButton setTitleColor:mTCOrangeColor forState:UIControlStateNormal];
backButton.contentEdgeInsets = UIEdgeInsetsZero;
backButton.imageEdgeInsets = UIEdgeInsetsZero;
[backButton addEventHandler:^(id sender) {
// a macro for the weak strong dance
@strongify(self);
// do stuff here
} forControlEvents:UIControlEventTouchUpInside];
UIView *buttonWrapper = [[UIView alloc] initWithFrame:CGRectMake(0, 0, width, 44)];
[buttonWrapper addSubview:backButton];
return [[UIBarButtonItem alloc] initWithCustomView:buttonWrapper];
}
@jaredsinclairに追加したいのは、ナビゲーションボタンにテキストおよび/または画像がある人への以下のオーバーライドメソッドの回答を確認します。そうしないと、テキストと画像が整列しません(背景画像のみ):
- (UIEdgeInsets) titleEdgeInsets {
if(SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"7.0"))
{
if (IF_ITS_A_LEFT_BUTTON) {
{
return UIEdgeInsetsMake(0, 0, 0, 9.0f);
}
else
{ // IF_ITS_A_RIGHT_BUTTON
return UIEdgeInsetsMake(0, 9.0f, 0, 0);
}
}
return [super titleEdgeInsets];
}
- (UIEdgeInsets)imageEdgeInsets {
if(SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"7.0"))
{
if (IF_ITS_A_LEFT_BUTTON)
{
return UIEdgeInsetsMake(0, 0, 0, 9.0f);
}
else
{ // IF_ITS_A_RIGHT_BUTTON
return UIEdgeInsetsMake(0, 9.0f, 0, 0);
}
}
return [super imageEdgeInsets];
}
追伸マクロは次のとおりです。
#define SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedAscending)
IOS 11でテスト済み
public lazy var navigationBackBarButton : UIBarButtonItem = {
let backBarButtonIcon = <Image Literal here>
let backBarButton = UIBarButtonItem(image: backBarButtonIcon, style: .plain, target: self, action: #selector(self.backBarButtonTouched(_:)))
backBarButton.imageInsets = UIEdgeInsets(top: 0.0, left: -9.0, bottom: 0.0, right: 0.0)
return backBarButton
}()
Jaredsinclairのアプローチの短縮版を思い付きました。
- (UIEdgeInsets)alignmentRectInsets {
return [self isLeftButton] ? UIEdgeInsetsMake(0, 9.0f, 0, 0) : UIEdgeInsetsMake(0, 0, 0, 9.0f);
}
- (BOOL)isLeftButton {
return self.frame.Origin.x < (self.superview.frame.size.width / 2);
}
魅力のように機能します。
このバグを修正するには、単にimageEdgeInsets
を調整するだけです。
これを試して。
UIButton *actionBtn = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 40, 40)];
[actionBtn setImage:[UIImage imageNamed:@"arrow.png"] forState:UIControlStateNormal];
[actionBtn addTarget:self action:@selector(goToSetting) forControlEvents:UIControlEventTouchUpInside];
actionBtn.imageEdgeInsets = UIEdgeInsetsMake(0, 9, 0, -9);
UIBarButtonItem *profileBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:actionBtn];
self.topViewController.navigationItem.rightBarButtonItems = @[profileBarButtonItem];
2018、iOS 11以降、Swift 4.x、これは私のために働いた。
上位の回答を組み合わせる:
プロパティ
internal lazy var button_Favorite: UIButton = {
let button = UIButton(type: .custom)
button.setImage(.favNormal, for: .normal)
button.contentHorizontalAlignment = .right
button.imageEdgeInsets = UIEdgeInsetsMake(0, 0, 0, -9.0)
return button
}()
viewDidLoad
で:
let barButton = UIBarButtonItem(customView: self.button_Favorite)
self.button_Favorite.frame = CGRect(x: 0, y: 0, width: 40.0, height: 44.0)
let negativeSpacer = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.fixedSpace, target: nil, action: nil)
negativeSpacer.width = -10.0
self.navigationItem.rightBarButtonItems = [negativeSpacer, barButton]
iOS7では、左スペースを修正するためのダミーbarbuttonitemを追加することができます。最初にダミーを追加し、右に最後を追加する必要があります
左の例では、元のアイテムを設定した後、またはストーリーボードを使用してボタンを設定している場合はviewdidloadにこれを追加する必要があります。
NSMutableArray *buttons = [[NSMutableArray alloc] init];
UIBarButtonItem *spacerItem = [[UIBarButtonItem alloc] init];
[buttons addObject:spacerItem];
for(UIBarButtonItem *item in self.leftBarButtonItems){
[buttons addObject:item];
}
[self setLeftBarButtonItems:[NSArray arrayWithArray:buttons] animated:NO];
* 解決策が見つかりました、回答の最後に読みます。*
しゅう
カイル・ベゲマンと似たようなケースがあります
これはボタンです
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
self.contentHorizontalAlignment = UIControlContentHorizontalAlignmentCenter;
}
return self;
}
- (UIEdgeInsets)alignmentRectInsets {
UIEdgeInsets insets;
if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"7.0")){
if ([self isLeftButton]) {
insets = UIEdgeInsetsMake(0, 9.0f, 0, 0);
} else {
insets = UIEdgeInsetsMake(0, 0, 0, 9.0f);
}
}else{
insets = UIEdgeInsetsZero;
}
return insets;
}
- (BOOL)isLeftButton {
return self.frame.Origin.x < (self.superview.frame.size.width / 2);
}
この場合に使用します
PBNavigationBarButton *dashboardButton = [PBNavigationBarButton buttonWithType:UIButtonTypeCustom];
UIImage *dashboardImage = [UIImage imageNamed:@"btn_dashboard.png"];
UIImage *dashboardImageHighlighted = [UIImage imageNamed:@"btn_dashboard_pressed.png"];
NSInteger halfImageWidth = ceilf([dashboardImage size].width/2.0f);
[dashboardButton setBackgroundImage:[dashboardImage stretchableImageWithLeftCapWidth:halfImageWidth topCapHeight:0] forState:UIControlStateNormal];
[dashboardButton setBackgroundImage:[dashboardImageHighlighted stretchableImageWithLeftCapWidth:halfImageWidth topCapHeight:0] forState:UIControlStateHighlighted];
[dashboardButton addTarget:target action:action forControlEvents:UIControlEventTouchUpInside];
[dashboardButton sizeToFit];
UIBarButtonItem *barButtonItem = [[UIBarButtonItem alloc] initWithCustomView:dashboardButton];
前のVCに戻ると、ボタンが再配置されることを除いて、すべてが素晴らしく見えます。小さなジャンプのような。私にとっては、すぐにジャンプします。そして、それはNavigationViewControllerからpopVCを行った後に起こります。
編集:以下の答え、マリウスのスウィズルメソッドも助けてくれました。
UIButton
の以下を変更します
コントロール->整列->水平方向に右揃え