Подвид UINavigationBar скрывает правильный UIBarButtonItem

В контроллере представления корневой таблицы я добавляю подпредставление, содержащее изображение:

[self.navigationController.navigationBar addSubview:imageView];

Затем в дочернем контроллере табличного представления, который я помещаю в стек, я устанавливаю правильный UIBarButtonItem:

UIBarButtonItem *rightButton = [[UIBarButtonItem alloc] initWithTitle:@"Right"  style:UIBarButtonItemStylePlain target:self action:@selector(rightAction:)];
self.navigationItem.rightBarButtonItem = rightButton;
[rightButton release];

Я не могу понять, почему кнопка не отображается в панели навигации. Если я нажму (пустое место), вызовется метод rightAction:, поэтому кнопка «находится» там, ожидайте, что она не отображается.

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

Кто-нибудь знает, как я могу заставить эту кнопку отображаться правильно?

Обновление: кнопка «Назад» отображается правильно, но она добавляется системой...


person nicktmro    schedule 28.10.2009    source источник


Ответы (2)


Лучший способ добавить изображение в UINavigationBar — создать его подкласс или создать категорию и переопределить метод drawRect:

//                                  #Lighter r,g,b,a            #Darker r,g,b,a
#define MAIN_COLOR_COMPONENTS       { 0.153, 0.306, 0.553, 1.0, 0.122, 0.247, 0.482, 1.0 }
#define LIGHT_COLOR_COMPONENTS      { 0.478, 0.573, 0.725, 1.0, 0.216, 0.357, 0.584, 1.0 }

@implementation UINavigationBar (UINavigationBarCategory)

- (void)drawRect:(CGRect)rect {
    if (imageReady) {
        UIImage *img = [UIImage imageNamed: @"navigation_background.png"];
        [img drawInRect:CGRectMake(0, 0, self.frame.size.width, self.frame.size.height)];
    } else {
        // Render yourself instead.
        // You will need to adjust the MAIN_COLOR_COMPONENTS and LIGHT_COLOR_COMPONENTS to match your app

       // emulate the tint colored bar
       CGContextRef context = UIGraphicsGetCurrentContext();
       CGFloat locations[2] = { 0.0, 1.0 };
       CGColorSpaceRef myColorspace = CGColorSpaceCreateDeviceRGB();

       CGFloat topComponents[8] = LIGHT_COLOR_COMPONENTS;
       CGGradientRef topGradient = CGGradientCreateWithColorComponents(myColorspace, topComponents, locations, 2);
       CGContextDrawLinearGradient(context, topGradient, CGPointMake(0, 0), CGPointMake(0,self.frame.size.height/2), 0);
       CGGradientRelease(topGradient);

       CGFloat botComponents[8] = MAIN_COLOR_COMPONENTS;
       CGGradientRef botGradient = CGGradientCreateWithColorComponents(myColorspace, botComponents, locations, 2);
       CGContextDrawLinearGradient(context, botGradient,
       CGPointMake(0,self.frame.size.height/2), CGPointMake(0, self.frame.size.height), 0);
       CGGradientRelease(botGradient);

       CGColorSpaceRelease(myColorspace);


       // top Line
       CGContextSetRGBStrokeColor(context, 1, 1, 1, 1.0);
       CGContextMoveToPoint(context, 0, 0);
       CGContextAddLineToPoint(context, self.frame.size.width, 0);
       CGContextStrokePath(context);

       // bottom line
       CGContextSetRGBStrokeColor(context, 0, 0, 0, 1.0);
       CGContextMoveToPoint(context, 0, self.frame.size.height);
       CGContextAddLineToPoint(context, self.frame.size.width, self.frame.size.height);
       CGContextStrokePath(context);
    }
}

@end

Если вы сделаете это таким образом, ваши кнопки будут отображаться правильно и менее «хакерски».

person coneybeare    schedule 28.10.2009
comment
Я мог бы создать подкласс UINavigationBar, но это свойство доступно только для чтения в UINavigationController... другое дело, что изображение фактически извлекается с сервера, поэтому его нужно устанавливать на лету. - person nicktmro; 28.10.2009
comment
Я принял ваш ответ, но был бы очень признателен за ваш вклад в следующее: если мое изображение не готово, когда я отображаю панель навигации, я получаю черный фон. Любое изменение, которое я мог бы вернуть к синему фону/стилю по умолчанию без использования изображения? - person nicktmro; 28.10.2009
comment
@coneybeare hai У меня была такая же проблема, я использовал ваш фрагмент кода, все та же проблема, не могли бы вы помочь мне? - person Bad Boy; 20.10.2011
comment
@balu, это больше не работает в iOS 5, если вы не используете подкласс. - person coneybeare; 20.10.2011

Я думаю, вы должны установить представление заголовка элемента навигации в свой imageView.

self.navigationItem.titleView = imageView;

Я предполагаю, что UINavigationBar отображает UINavigationItem в подвиде, и вы добавляли свой UIImageView поверх этого подвида.

В одном из представлений я показываю метку и изображение рядом с ней. Я думаю, что просто добавил метку и представление изображения в представление, которое затем использовал для titleView.

person Thomas Müller    schedule 28.10.2009
comment
Обычно это работает, но titleView не охватывает весь экран. Я подозреваю, что это всего лишь 300 пикселей, а не 320. - person nicktmro; 28.10.2009
comment
Я думаю, вы хотите, чтобы это было фоновым изображением? ОК, тогда, возможно, попробуйте добавить свой imageView в индекс 0 (-insertSubview:atIndex:) - person Thomas Müller; 28.10.2009