UIBarButtonItem с настраиваемым изображением и без рамки


89

Я хочу создать UIBarButtonItem с настраиваемым изображением, но мне не нужна граница, которую добавляет iPhone, поскольку мое изображение имеет специальную границу.

Это то же самое, что и кнопка назад, но кнопка вперед.

Это приложение предназначено для проекта inHouse, поэтому меня не волнует, отклонит ли Apple, одобрит его или понравится :-)

Если я использую свойство initWithCustomView: v UIBarButtonItem, я могу это сделать:

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 представлениях, это не СУХОЙ.

Полагаю, мне нужно создать подкласс, но что?

  • NSView?
  • UIBarButtonItem?

Благодарность,

С уважением,


3
Спасибо, что поделились своим кодом, это все, что мне было нужно :).
Макс,

1
Все, я использовал ответ, предоставленный Саном 6 февраля. На интеграцию в мою раскадровку ушло всего 5 минут, и это сработало отлично. Свойство Selector находится в Инспекторе подключений IB. Перетащите элемент управления из UIButton в объект ViewController, и методы появятся. Коснитесь желаемого метода, и все готово. Единственное, что осталось, - это очистить код. Используется btnXXXXX.hidden для скрытия и отображения для замены barbuttonitem = nil. Но этот метод был легким и очень чистым.
user589642

Ответы:


44

Вы можете добавить метод в 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

Таким образом, в любом месте вашего кода вы можете создать элемент панели, вызывающий этот метод (при условии, что вы включаете заголовок с его объявлением).

PS Вам не нужно использовать 'v' UIView, так как вы можете создавать UIBarButtonItemс помощью кнопки напрямую настраиваемый вид.
PPS Вам также потребуется [предварительная версия] в вашем коде.


Пользовательская категория: мне нужно создать файл заголовка с этими объявлениями и файл реализации, в который я помещаю код, на который вы ссылаетесь? спасибо
mongeta

Его работа, спасибо большое, но я не могу написать селектор, я не хочу писать селектор по категории, как я могу написать его в своем классе
Nilesh Tupe

@NileshTupe, что ты имеешь в виду? Вы передаете метод селектора и цель - так что целью может быть любой объект, который вы хотите,
Владимир

2
Кстати, я добавил это в свое небольшое репозиторий с открытым исходным кодом для категорий удобства UIKit. Спасибо @Vladimir за вдохновение. (обратите внимание, что все мои материалы основаны на ARC) github.com/egold/UIKitConvenience/blob/master/UIKitConvenience/…
Эрик Голдберг,

50

Еще одно простое решение:

  1. Перетащите стандартный UIButton
  2. Установите стиль кнопки на свой и установите изображение для этой кнопки
  3. Перетащите его на UINavigationBar
  4. Установить селектор

1
Наверное, самое простое решение. Благодарность!
Prine,

1
Гениально! Единственная причуда - это не сработает, если перетащить кнопку прямо на панель навигации. Перед добавлением на панель навигации кнопка должна быть настроена на заказ. Не знаю почему, но так оно и есть. Итак, шаг №1 - означает перетащить UIBatton куда-нибудь в пользовательский интерфейс, кроме панели навигации.
Андрей Чижов

1
трудно быть простым и эффективным. Хороший ответ
Add080bbA

37

Я нашел это легко. Его подают сверху. "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;

6

Альтернативой является создание подкласса UIBarButtonItem. Зачем? Таким образом, действие вызывается для цели с правильным отправителем. В приведенном выше коде аргументом отправителя в сообщении действия является экземпляр 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

5
UIBarButtonItem *menuItem = [[UIBarButtonItem alloc] initWithImage: [UIImage imageNamed:@"icon-menu.png"]
                                                                    style:UIBarButtonItemStylePlain
                                                                   target:self
                                                                   action:@selector(showMenu)];

3

Это также можно сделать программно (конечно):

Сначала создайте настраиваемый вид. Это настраиваемое представление может содержать изображение, кнопку или что угодно еще. Пользовательское представление можно сделать программно или в 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;

1

Хорошо, эта категория работает очень хорошо, потому что с 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

1

Проверьте это простое решение.

- (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 - это прозрачное png-изображение размером 1 пиксель, которое вы можете скачать по ссылке ниже.

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


Вы можете просто использовать [UIImage new] вместо прозрачного изображения.
Джеймс Кэмпбелл

0

Еще одно решение, думаю, это проще в случае создания кнопки программно:

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];
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.