【问题标题】:UIBarButtonItem with custom image and no borderUIBarButtonItem 具有自定义图像且无边框
【发布时间】:2011-02-10 11:59:05
【问题描述】:

我想创建一个带有自定义图像的 UIBarButtonItem,但我不想要 iPhone 添加的边框,因为我的图像有一个特殊的边框。

它和后退按钮一样,但是一个前进按钮。

这个应用程序是一个内部项目,所以我不在乎苹果是否拒绝或批准它或喜欢它:-)

如果我使用 UIBarButtonItem 的 initWithCustomView:v 属性,我可以做到:

UIImage *image = [UIImage imageNamed:@"right.png"];

UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
[button setBackgroundImage: [image stretchableImageWithLeftCapWidth:7.0 topCapHeight:0.0] forState:UIControlStateNormal];
[button setBackgroundImage: [[UIImage imageNamed: @"right_clicked.png"] stretchableImageWithLeftCapWidth:7.0 topCapHeight:0.0] forState:UIControlStateHighlighted];

 button.frame= CGRectMake(0.0, 0.0, image.size.width, image.size.height);

[button addTarget:self action:@selector(AcceptData)    forControlEvents:UIControlEventTouchUpInside];

UIView *v=[[UIView alloc] initWithFrame:CGRectMake(0.0, 0.0, image.size.width, image.size.height) ];

[v addSubview:button];

UIBarButtonItem *forward = [[UIBarButtonItem alloc] initWithCustomView:v];

self.navigationItem.rightBarButtonItem= forward;

[v release];
[image release];

这可行,但如果我必须在 10 个视图中重复此过程,这不是 DRY。

我想我必须继承,但是什么?

  • NSView ?
  • UIBarButtonItem ?

谢谢,

问候,

【问题讨论】:

  • 感谢分享您的代码,这就是我所需要的 :) .
  • 大家,我使用了 San 在 2 月 6 日提供的答案。整合到我的 Storyboard 中花了整整 5 分钟,而且效果很好。 Selector 属性位于 IB 的 Connections Inspector 下。控制从 UIButton 拖动到 ViewController 对象,方法将弹出。点击你想要的方法,你就完成了。唯一剩下的就是一些代码清理。使用 btnXXXXX.hidden 隐藏和取消隐藏以替换 barbuttonitem = nil。但是这种方法很简单,也很干净。

标签: ios iphone uibarbuttonitem


【解决方案1】:

您可以向 UIBarButtonItem 添加方法,而无需使用自定义类别对其进行子类化:

@interface UIBarButtonItem(MyCategory)

+ (UIBarButtonItem*)barItemWithImage:(UIImage*)image target:(id)target action:(SEL)action;

@end

@implementation UIBarButtonItem(MyCategory)

+ (UIBarButtonItem*)barItemWithImage:(UIImage*)image target:(id)target action:(SEL)action{
 // Move your item creation code here
}
@end

因此,您可以在代码中的任何位置创建调用此方法的条形项(前提是您在其声明中包含标题)。

附:您不需要使用“v”UIView,因为您可以使用按钮直接创建 UIBarButtonItem 作为自定义视图。
附言您的代码中还需要 [forward release]。

【讨论】:

  • 自定义类别:我必须创建带有这些声明的头文件和实现文件,我将您引用的代码放在哪里?谢谢
  • 它的工作量很大,但我不能写选择器我不想在类别上写选择器我怎么能把它写在我的课上
  • @NileshTupe 你是什么意思?你传递选择器方法 目标 - 所以目标可以是你想要的任何对象
  • 顺便说一句-我将此添加到我的小型开源存储库中,用于 UIKit 便利类别。感谢@Vladimir 的启发。 (注意我所有的东西都是基于 ARC 的)github.com/egold/UIKitConvenience/blob/master/UIKitConvenience/…
【解决方案2】:

另一种方法是继承 UIBarButtonItem。为什么?以便使用正确的发送者在目标上调用该操作。在上面的代码中,动作消息中的 sender 参数是 UIButton 实例,而不是 UIBarButtonItem 实例。这很重要,例如,如果您希望从栏按钮项中呈现 UIPopoverController。通过子类化 UIBarButtonItem,您可以添加一个保留原始目标的 ivar,从而允许我们的子类实例拦截、修改和转发具有正确发送者的操作消息。

所以,CCFBarButtonItem.h:

#import <uIKit/UIBarButtonItem.h>

@interface CCFBarButtonItem : UIBarButtonItem
{
@protected
    id _originalTarget;
}
- (id)initWithImage:(UIImage *)image target:(id)target action:(SEL)action;
@end

和 CCFBarButtonItem.m

#import "CCFBarButtonItem.h"
#import <UIKit/UIButton.h>
#import <UIKit/UIView.h>
#import <UIKit/UIImage.h>

@implementation CCFBarButtonItem

#pragma mark - Object life cycle

- (id)initWithImage:(UIImage *)image target:(id)target action:(SEL)action;
{
    _ASSIGN( _originalTarget, target );

    UIButton *imgButton = [UIButton buttonWithType:UIButtonTypeCustom];
    [imgButton setImage:image forState:UIControlStateNormal];
    imgButton.frame = CGRectMake(0.0, 0.0, image.size.width, image.size.height);
    [imgButton addTarget:self action:action forControlEvents:UIControlEventTouchUpInside];

    self = [super initWithCustomView:imgButton];

    return self;
}

- (void)dealloc;
{
    MCRelease(_originalTarget);
    [super dealloc];
}

- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector;
{
    if( [_originalTarget respondsToSelector:aSelector] )
    {
        return [_originalTarget methodSignatureForSelector:aSelector];
    }
    else
    {
        return [super methodSignatureForSelector:aSelector];
    }
}

- (void)forwardInvocation:(NSInvocation *)anInvocation;
{
    SEL aSelector = [anInvocation selector];
    if( [_originalTarget respondsToSelector:aSelector] )
    {
        //  modify the 'sender' argument so that it points to self
        [anInvocation setArgument:&self atIndex:2];
        [anInvocation invokeWithTarget:_originalTarget];
    }
    else
    {
        [self doesNotRecognizeSelector:aSelector];
    }
}
@end

【讨论】:

    【解决方案3】:

    我发现这很容易。建议放在上面。 “random.png”必须在项目中。只需拖放任何图像。

     UIButton *a1 = [UIButton buttonWithType:UIButtonTypeCustom];
            [a1 setFrame:CGRectMake(0.0f, 0.0f, 25.0f, 25.0f)];
            [a1 addTarget:self action:@selector(randomMsg) forControlEvents:UIControlEventTouchUpInside];
            [a1 setImage:[UIImage imageNamed:@"config.png"] forState:UIControlStateNormal];
            UIBarButtonItem *random = [[UIBarButtonItem alloc] initWithCustomView:a1];
    
     //? line incomplete ?//   imageNamed:@"random.png"] style:UIBarButtonItemStylePlain target:self action:@selector(randomMsg)];
    
        self.navigationItem.rightBarButtonItem = random;
    

    【讨论】:

      【解决方案4】:

      另一个简单的解决方案是

      1. 拖动标准 UIButton
      2. 将按钮的样式设置为自定义并为该按钮设置图像
      3. 将其拖到 UINavigationBar 上
      4. 设置选择器

      【讨论】:

      • 可能是最简单的解决方案。谢谢!
      • 太棒了!唯一的怪癖 - 如果您将按钮直接拖动到导航栏,它将无法正常工作。按钮必须在添加到导航栏之前设置为自定义。不知道为什么,但事实就是这样。所以第 1 步 - 意味着将 UIBatton 拖到 UI 上的某个位置,而不是导航栏。
      • 很难简单有效。不错的答案
      【解决方案5】:

      好的,这个类别效果很好,因为 Popovercontroller 没有问题 :-)

      #import <UIKit/UIKit.h>
      
      @interface UIBarButtonItem (BarButtonItemExtended)
      + (UIBarButtonItem*)barItemWithImage:(UIImage*)image target:(id)target action:(SEL)action;
      -(void)performBarButtonAction:(id)sender;
      @end
      
      
      
      #import "UIBarButtonItem+BarButtonItemExtended.h"
      
      @implementation UIBarButtonItem (BarButtonItemExtended)
      
      + (UIBarButtonItem*)barItemWithImage:(UIImage*)image target:(id)target action:(SEL)action
      {    
          UIButton *imgButton = [UIButton buttonWithType:UIButtonTypeCustom];
          [imgButton setImage:image forState:UIControlStateNormal];
          imgButton.frame = CGRectMake(0.0, 0.0, image.size.width, image.size.height);
      
          UIBarButtonItem *b = [[UIBarButtonItem alloc]initWithCustomView:imgButton];
      
          [imgButton addTarget:b action:@selector(performBarButtonAction:) forControlEvents:UIControlEventTouchUpInside];
      
          [b setAction:action];
          [b setTarget:target];
      
          return b;
      }
      
      -(void)performBarButtonAction:(UIButton*)sender
      {
          [[self target] performSelector:self.action withObject:self];
      }
      @end
      

      【讨论】:

        【解决方案6】:

        这也可以通过编程方式完成(当然):

        首先,创建一个自定义视图。此自定义视图可以包含图像、按钮或您想要的任何其他内容。可以通过编程方式或在 IB 中制作自定义视图:

        UIImage *customImage = [UIImage imageNamed:@"imageName"];
        UIView *customView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, customImage.size.width, customImage.size.height)];
        customView.backgroundColor = [UIColor colorWithPatternImage:customImage];
        

        接下来,创建一个 UIBarButtonItem 并使用自定义视图对其进行初始化。

        UIBarButtonItem *customBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:customView];
        

        现在,只需将自定义 UIBarButton 添加到 leftBarButtonItem:

        self.navigationItem.leftBarButtonItem = customBarButtonItem;
        

        【讨论】:

          【解决方案7】:

          另一种解决方案,认为以编程方式创建按钮时会更简单:

          UIBarButtonItem *button = [[UIBarButtonItem alloc] initWithImage:defaultImage
                                                       landscapeImagePhone:landscapeImage
                                                                     style:UIBarButtonItemStylePlain
                                                                    target:self
                                                                    action:@selector(someSelector)];
          [button setBackgroundImage:[UIImage new] forState:UIControlStateNormal barMetrics:UIBarMetricsDefault];
          [button setBackgroundImage:[UIImage new] forState:UIControlStateNormal barMetrics:UIBarMetricsLandscapePhone];
          

          【讨论】:

            【解决方案8】:

            看看这个简单的解决方案。

            - (void)splitViewController:(UISplitViewController *)splitController willHideViewController:(UIViewController *)viewController withBarButtonItem:(UIBarButtonItem *)barButtonItem forPopoverController:(UIPopoverController *)popoverController
            {
            barButtonItem.image = [UIImage imageNamed:@"navButton.png"];
            barButtonItem.style = UIBarButtonItemStylePlain;
            
            [barButtonItem setBackgroundImage:[UIImage imageNamed:@"1x1.png"] forState:UIControlStateNormal barMetrics:UIBarMetricsDefault];
            [self.navigationItem setLeftBarButtonItem:barButtonItem animated:YES];
            self.masterPopoverController = popoverController;
            }
            

            这里的 1x1.png 是一个 1 像素的透明 png 图片,您可以从下面的链接下载

            http://commons.wikimedia.org/wiki/File:1x1.png

            【讨论】:

            • 你可以只使用 [UIImage new] 而不是使用透明图像。
            【解决方案9】:
            UIBarButtonItem *menuItem = [[UIBarButtonItem alloc] initWithImage: [UIImage imageNamed:@"icon-menu.png"]
                                                                                style:UIBarButtonItemStylePlain
                                                                               target:self
                                                                               action:@selector(showMenu)];
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2012-03-16
              • 1970-01-01
              • 2012-11-12
              • 2020-07-26
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多