ios 来自带有自定义图像的 UIButtons 的自定义 UIBarButtonItems - 是否可以使点击目标更大?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/16451639/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-30 23:31:23  来源:igfitidea点击:

Custom UIBarButtonItems from UIButtons with custom images - is it possible to make the tap targets larger?

iosobjective-cuibuttonuibarbuttonitemuitoolbar

提问by Doug Smith

I'm making UIBarButtons as follows:

我正在制作 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];

However, the tap targets are tiny. More precisely, they're the size of the custom images. (Which again, are tiny.) Is there any way to increase the size of their tap target?

但是,点击目标很小。更准确地说,它们是自定义图像的大小。(同样,很小。)有没有办法增加他们的点击目标的大小?

(Note: altering the frame property of the UIButtons just stretches the image.)

(注意:改变 UIButtons 的 frame 属性只会拉伸图像。)

回答by Prasad Devadiga

Small changes to your code will do the stuff

对您的代码进行小的更改即可

Changes needed :

需要改变:

  • I am assuming that the size of backButtonImageis {28,17}and setting the button frame as CGRectMake(0, 0, 48, 37)`
  • remove the backGroundImageand use setImage:
  • set the property imageEdgeInsetsto UIEdgeInsetsMake(10, 10, 10, 10)
  • 我假设大小backButtonImage{28,17}并将按钮框架设置为CGRectMake(0, 0, 48, 37)`
  • 删除backGroundImage并使用setImage:
  • 将属性设置imageEdgeInsetsUIEdgeInsetsMake(10, 10, 10, 10)

Your code will become like this:

你的代码会变成这样:

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

You can change the value for the frameand the imageEdgeInsetsas per your requirements.
This code worked for me.

您可以更改值frameimageEdgeInsets按您的要求。
这段代码对我有用。

回答by VGruenhagen

You can change the UIBarButtonItem's width property

您可以更改UIBarButtonItem的宽度属性

backBarButtonItem.width = x;

Unfortunately you can't change the height is way, because there is no height property.

不幸的是,您无法更改高度,因为没有高度属性。

What you can do however is pass UIBarButtonIteman UIButtonwith a defined frame using initWithCustomView

但是什么你能做的就是通过UIBarButtonItem一个UIButton使用定义的帧initWithCustomView

for example:

例如:

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

If your image looks stretched, make sure you maintain the same aspect ratio! Or make sure the image is exactly the same size.

如果您的图像看起来被拉伸,请确保保持相同的纵横比!或者确保图像大小完全相同。

回答by Joshua

1) Add a category to your UIButton
2) Add new properties to the category
3) Add your method to initialise the back button
4) Override -(BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event
5) Subclass toolBarItems

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

Lets say the touch event doesn't trigger we need the view its in to call the button so in toolBarItems we do something like:

假设触摸事件不会触发,我们需要它的视图来调用按钮,因此在 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];
        }
    }


}

then thats it. we enlarge the frame without enlarging the actual button.

那么就是这样。我们放大框架而不放大实际按钮。

you just initial your button like: UIButton *btn = [[UIButton alloc]initBackBtnAtPoint:CGPointMake(0,0)];

您只需初始化您的按钮,例如: UIButton *btn = [[UIButton alloc]initBackBtnAtPoint:CGPointMake(0,0)];

Hope it helps

希望能帮助到你

回答by Alexander Merchi

Change button frame to large and change your line

将按钮框架更改为大并更改您的行

[backButton setBackgroundImage:backButtonImage forState:UIControlStateNormal];

to:

到:

[backButton setImage:backButtonImage forState:UIControlStateNormal];

回答by Lukas Kukacka

Just use

只需使用

[button setImage:backButtonImage forState:UIControlStateNormal];

instead of

代替

[backButton setBackgroundImage:backButtonImage forState:UIControlStateNormal];

and set the frame to whatever you like. The image will then be centered and the button will receive the touch in the given frame.

并将框架设置为您喜欢的任何内容。然后图像将居中,按钮将在给定帧中接收触摸。

Something like this:

像这样的东西:

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

回答by Steven McGrath

When you call initWithCustomView, the UIBarButtonItemdelegates event handling to the custom view, which, in your case, is the UIButton. In turn, the UIButtonis getting its bounds from the image, and as a background image, it is expected to stretch to fill new bounds as needed.

当您调用 时initWithCustomViewUIBarButtonItem将事件处理委托给自定义视图,在您的情况下,它是UIButton. 反过来,UIButton它从图像中获取边界,并且作为背景图像,预计会根据需要拉伸以填充新边界。

Instead, set the imageand imageInsetsproperties directly on the UIBarButtonItem. These properties are declared on the parent class, UIBarItem. You may also wish to set their landscape variants.

相反,直接在 UIBarButtonItem 上设置imageimageInsets属性。这些属性在父类上声明,UIBarItem。您可能还希望设置它们的横向变体。

回答by Alex

mmm... for what you need to achieve - that is no image stretch - there's a simple way:

嗯...对于您需要实现的目标 - 这不是图像拉伸 - 有一个简单的方法:

1) use Gimp or photoshop and create a transparent layer below your image, so that it matches the size you want.

1) 使用 Gimp 或 photoshop 并在图像下方创建一个透明层,使其与您想要的大小相匹配。

2) merge down and create retina and non-retina images.

2)合并并创建视网膜和非视网膜图像。

3) update your code so that it reflect the new image size.

3) 更新您的代码,使其反映新的图像大小。

4) assign the images and then run your code.

4)分配图像,然后运行您的代码。

This way your original image won't be stretched because it's boundaries will take into account the transparent portion of it.

这样你的原始图像就不会被拉伸,因为它的边界会考虑到它的透明部分。

Other than that, you can probably do this all programatically, but I doubt this is a good idea, unless you planned to dive into UIGraphics for other reasons.

除此之外,您可能可以通过编程方式完成这一切,但我怀疑这是一个好主意,除非您出于其他原因计划深入研究 UIGraphics。

回答by korat prashant

You need to change three line of code and hope its working.

您需要更改三行代码并希望其正常工作。

1)Change the backButton width as per your need.

1) 根据需要更改 backButton 宽度。

2)Set backButton's Imageinstead of backButton's BackgroundImage

2) 设置 backButtonImage而不是 backButtonBackgroundImage

[backButton setImage:backButtonImage forState:UIControlStateNormal];

3)Also set backButton's contentHorizontalAlignment

3)同时设置backButton的 contentHorizontalAlignment

backButton.contentHorizontalAlignment=UIControlContentHorizontalAlignmentLeft;

回答by andrew lattis

you should be able to just set the edge insets on the button.

您应该能够在按钮上设置边缘插入。

so set the frame of the button to be larger than the image, then set the edge insets on the button.

因此将按钮的框架设置为大于图像,然后在按钮上设置边缘插入。

so to expand your width by by 10 pixels on each side something like this should work

所以要在每一侧将宽度扩大 10 个像素,这样的事情应该可行

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

回答by Ganee....

Increase the UIButton frames(up to the tap size you want)

增加 UIButton 框架(达到你想要的水龙头大小)

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

If you want to see the image for complete button please write following method

如果您想查看完整按钮的图像,请编写以下方法

      [backButton setBackgroundImage:backButtonImage forState:UIControlStateNormal];

If you want to see the image actual size (Dont worry tap size is your button size only)

如果您想查看图像的实际大小(不要担心水龙头大小只是您的按钮大小)

      [backButton setImage:backButtonImage forState:UIControlStateNormal];

And finally

最后

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

Hope it helps you!

希望对你有帮助!