web-dev-qa-db-ja.com

カスタム画像を使用したUIButtonからのカスタムUIBarButtonItems-タップターゲットを大きくすることは可能ですか?

私は次のようにUIBarButtonsを作成しています:

// Create "back" UIBarButtonItem
UIButton *backButton = [UIButton buttonWithType:UIButtonTypeCustom];
backButton.frame = CGRectMake(0, 0, 28, 17);
[backButton addTarget:self action:@selector(backButtonTapped) forControlEvents:UIControlEventTouchUpInside];
backButton.showsTouchWhenHighlighted = YES;

UIImage *backButtonImage = [UIImage imageNamed:@"back-button.png"];
[backButton setBackgroundImage:backButtonImage forState:UIControlStateNormal];

UIBarButtonItem *backBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:backButton];

[toolBarItems addObject:backBarButtonItem];

ただし、タップターゲットは小さいです。より正確には、それらはカスタム画像のサイズです。 (これも小さいです。)タップターゲットのサイズを大きくする方法はありますか?

(注:UIButtonsのframeプロパティを変更すると、画像が引き伸ばされるだけです。)

15
Doug Smith

コードに小さな変更を加えるだけで問題は解決します

必要な変更:

  • backButtonImageのサイズは_{28,17}_であると想定し、ボタンフレームをCGRectMake(0, 0, 48, 37)`として設定します。
  • backGroundImageを削除し、_setImage:_を使用します
  • プロパティimageEdgeInsetsUIEdgeInsetsMake(10, 10, 10, 10)に設定します

コードは次のようになります。

_UIButton *backButton = [UIButton buttonWithType:UIButtonTypeCustom];
backButton.frame = CGRectMake(0, 0, 48, 37);
[backButton addTarget:self action:@selector(backButtonTapped) forControlEvents:UIControlEventTouchUpInside];
backButton.showsTouchWhenHighlighted = YES;

UIImage *backButtonImage = [UIImage imageNamed:@"back-button.png"];
[backButton setImage:backButtonImage forState:UIControlStateNormal];

backButton.imageEdgeInsets = UIEdgeInsetsMake(10, 10, 10, 10);

UIBarButtonItem *backBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:backButton];

[toolBarItems addObject:backBarButtonItem];
_

必要に応じて、frameimageEdgeInsetsの値を変更できます。
このコードは私のために働いた。

26
Prasad Devadiga

UIBarButtonItemのwidthプロパティを変更できます

backBarButtonItem.width = x;

残念ながら、heightプロパティがないため、heightを変更することはできません。

ただし、できることは、UIBarButtonItemを使用して定義されたフレームでUIButtoninitWithCustomViewを渡すことです。

例えば:

    UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];

    UIImage *backButtonImage = [UIImage imageNamed:@"back-button.png"];

   [button setBackgroundImage:backButtonImage forState:UIControlStateNormal];

    button.frame = CGRectMake(0, 0, width, height);

    UIBarButtonItem *barButtonItem = [[UIBarButtonItem alloc] initWithCustomView:button];

画像が引き伸ばされているように見える場合は、同じアスペクト比を維持するようにしてください。または、画像が正確に同じサイズであることを確認してください。

5
VGruenhagen

1)UIButtonにカテゴリを追加します
2)カテゴリに新しいプロパティを追加します
3)戻るボタンを初期化するメソッドを追加します
4)オーバーライド-(BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event
5)サブクラスtoolBarItems

_@implementation UIButton (yourButtonCategory)
@dynamic shouldHitTest; // boolean
@dynamic hitTestRect; // enlarge rect of the button
@dynamic buttonPressedInterval; // interval of press, sometimes its being called twice

-(id)initBackBtnAtPoint:(CGPoint)_point{
// we only need the Origin of the button since the size and width are fixed so the image won't be stretched
    self = [self initWithFrame:CGRectMake(_point.x, _point.y, 28, 17)];   
    [self setBackgroundImage:[UIImage imageNamed:@"back-button.png"]forState:UIControlStateNormal];

    self.shouldHitTest = CGRectMake(self.frame.Origin.x - 25, self.frame.Origin.y-10, self.frame.size.width+25, self.frame.size.height+25); // this will be the enlarge frame of the button
    self.shouldHitTest = YES;
    return self;
}


-(BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event{
BOOL shouldReturn = [super pointInside:point withEvent:event];
NSSet *touches = [event allTouches];
BOOL shouldSendTouches = NO;

for (UITouch *touch in touches) {
    switch (touch.phase) {
        case UITouchPhaseBegan:
            shouldSendTouches = YES;
            break;
        default:
            shouldSendTouches = NO;
            break;
    }
}


if(self.shouldHitTest){

    double elapse = CFAbsoluteTimeGetCurrent();
    CGFloat totalElapse = elapse - self.buttonPressedInterval;
    if (totalElapse < .32) {
        return NO;
        // not the event we were interested in
    } else {
                    // use this call

        if(CGRectContainsPoint(self.hitTestRect, point)){
            if(shouldSendTouches){
                self.buttonPressedInterval = CFAbsoluteTimeGetCurrent();

                [self sendActionsForControlEvents:UIControlEventTouchUpInside];
            }

            return NO;
        }
    }

}

return shouldReturn;

}


-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{

[super touchesBegan:touches withEvent:event];
UITouch *touch = [touches anyObject]; 
CGPoint touch_point = [touch locationInView:self];
[self pointInside:touch_point withEvent:event];
}

@end
_

Touchイベントがトリガーされないとすると、ボタンを呼び出すためにビューを表示する必要があるため、toolBarItemsでは次のようにします。

_-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
    [super touchesBegan:touches withEvent:event];
    for(id subs in self.subviews){
        if([subs isKindOfClass:[UIButton class]]){
            [subs touchesBegan:touches withEvent:event];
        }
    }


}
_

それでそれです。実際のボタンを拡大せずにフレームを拡大します。

次のようにボタンを初期化します:UIButton *btn = [[UIButton alloc]initBackBtnAtPoint:CGPointMake(0,0)];

それが役に立てば幸い

3
Joshua

initWithCustomViewを呼び出すと、UIBarButtonItemはイベント処理をカスタムビュー(この場合はUIButton)に委任します。次に、UIButtonは画像から境界を取得しており、背景画像として、必要に応じて新しい境界を埋めるために拡大することが期待されています。

代わりに、UIBarButtonItemで直接imageプロパティとimageInsetsプロパティを設定します。これらのプロパティは、親クラスUIBarItemで宣言されています。また、ランドスケープバリアントを設定することもできます。

1
Steven McGrath

ボタンフレームを大きくしてラインを変えてください

[backButton setBackgroundImage:backButtonImage forState:UIControlStateNormal];

に:

[backButton setImage:backButtonImage forState:UIControlStateNormal];
1

3行のコードを変更して、機能することを期待する必要があります。

1)必要に応じてbackButtonの幅を変更します。

2)backButtonのImageの代わりにbackButtonのBackgroundImageを設定します

[backButton setImage:backButtonImage forState:UIControlStateNormal];

3)backButtonのcontentHorizontalAlignmentも設定します

backButton.contentHorizontalAlignment=UIControlContentHorizontalAlignmentLeft;
1
korat prashant

うーん...あなたが達成する必要があることのために-それは画像のストレッチではありません-簡単な方法があります:

1)Gimpまたはphotoshopを使用して、画像の下に透明なレイヤーを作成し、必要なサイズに一致させます。

2)マージして、網膜と非網膜の画像を作成します。

3)新しい画像サイズを反映するようにコードを更新します。

4)画像を割り当ててから、コードを実行します。

これにより、元の画像の境界が透明部分を考慮に入れるため、元の画像が引き伸ばされることはありません。

それ以外は、おそらくこれをすべてプログラムで行うことができますが、他の理由でUIGraphicsに飛び込む予定がない限り、これが良い考えだとは思えません。

1
Alex

使用するだけ

[button setImage:backButtonImage forState:UIControlStateNormal];

の代わりに

[backButton setBackgroundImage:backButtonImage forState:UIControlStateNormal];

フレームを好きなように設定します。次に、画像が中央に配置され、ボタンは指定されたフレームでタッチを受け取ります。

このようなもの:

UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
button.frame = CGRectMake(50, 50, 50, 50);
[button setImage:backButtonImage forState:UIControlStateNormal];
1
Lukas Kukacka

UIButtonフレームを増やします(必要なタップサイズまで)

      button.frame = CGRectMake(0, 0, 56, 20);

完全なボタンの画像を見たい場合は、次の方法を書いてください

      [backButton setBackgroundImage:backButtonImage forState:UIControlStateNormal];

画像の実際のサイズを確認したい場合(タップサイズはボタンサイズのみですのでご安心ください)

      [backButton setImage:backButtonImage forState:UIControlStateNormal];

そして最後に

      UIBarButtonItem *backBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:backButton];

お役に立てば幸いです。

0
Ganee....

ボタンにエッジインセットを設定できるはずです。

そのため、ボタンのフレームを画像よりも大きく設定してから、ボタンのエッジインセットを設定します。

したがって、幅を両側で10ピクセルずつ拡大するには、このようなものが機能するはずです。

backButton.frame = CGRectMake(0,0,28,37);
backButton.imageEdgeInsets = UIEdgeInsetsMake(0, 10, 0, 10);
0
andrew lattis