【问题标题】:Custom UIBarButtonItems from UIButtons with custom images - is it possible to make the tap targets larger?来自带有自定义图像的 UIButtons 的自定义 UIBarButtonItems - 是否可以使点击目标更大?
【发布时间】:2013-05-03 07:56:07
【问题描述】:

我正在制作 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 属性只会拉伸图像。)

【问题讨论】:

  • 您能否提供图片以便我们复制/查看确切的问题?

标签: ios objective-c uibutton uibarbuttonitem uitoolbar


【解决方案1】:

对您的代码稍作改动即可解决问题

需要更改:

  • 我假设backButtonImage的大小为{28,17},并将按钮框架设置为CGRectMake(0, 0, 48, 37)`
  • 删除backGroundImage 并使用setImage:
  • 将属性imageEdgeInsets 设置为UIEdgeInsetsMake(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 的值。
这段代码对我有用。

【讨论】:

    【解决方案2】:

    随便用

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

    【讨论】:

    • 这对我不起作用。图像总是会拉伸以填满整个按钮。
    • @user3344977 因为您当然需要为按钮设置正确的contentMode。默认值大概是UIViewContentModeScaleToFill,设置成你需要的(可能是UIViewContentModeCenter
    【解决方案3】:

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

    [backButton setBackgroundImage:backButtonImage forState:UIControlStateNormal];
    

    到:

    [backButton setImage:backButtonImage forState:UIControlStateNormal];
    

    【讨论】:

      【解决方案4】:

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

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

      【讨论】:

        【解决方案5】:

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

        1)根据需要更改后退按钮的宽度。

        2)设置backButton的Image而不是backButton的BackgroundImage

        [backButton setImage:backButtonImage forState:UIControlStateNormal];
        

        3)同样设置backButton的contentHorizontalAlignment

        backButton.contentHorizontalAlignment=UIControlContentHorizontalAlignmentLeft;
        

        【讨论】:

          【解决方案6】:

          增加 UIButton 框架(直到你想要的点击大小)

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

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

                [backButton setBackgroundImage:backButtonImage forState:UIControlStateNormal];
          

          如果您想查看图像的实际尺寸(不要担心点击尺寸只是您的按钮尺寸)

                [backButton setImage:backButtonImage forState:UIControlStateNormal];
          

          最后

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

          希望对你有帮助!

          【讨论】:

          • “完成按钮”是什么意思?
          • 意思是,如果你给按钮的尺寸大于图片的实际尺寸,图片将被拉伸并显示为完整的按钮。
          【解决方案7】:

          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
          

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

          希望对你有帮助

          【讨论】:

            【解决方案8】:

            您可以更改UIBarButtonItem 的宽度属性

            backBarButtonItem.width = x;
            

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

            但是,您可以做的是使用 initWithCustomView 传递带有定义框架的 UIBarButtonItemUIButton

            例如:

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

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

            【讨论】:

            • 我也需要身高。
            • @DougSmith 我已经为你更新了我的答案。希望现在对您有所帮助。
            【解决方案9】:

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

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

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

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

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

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

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

            【讨论】:

              【解决方案10】:

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

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

              所以要在每边将宽度扩大 10 像素,这样应该可以工作

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

              【讨论】:

              • 这仍然会拉伸图像。
              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2011-01-06
              • 2020-01-22
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多