iOS 7:如何为UIControlStateHighlighted设置UIBarButtonItem backButtonBackgroundImage?

Eug*_*nyk 13 uibarbuttonitem navigationbar ios ios7

我正在尝试在正常和突出显示状态下设置后退按钮的背景图像.

- (void)configureBackButtonInNavigationItem:(UINavigationItem *)item
{
    UIBarButtonItem *backBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"back"
            style:UIBarButtonItemStyleBordered target:nil action:NULL];
    [backBarButtonItem setTitleTextAttributes:@{NSForegroundColorAttributeName : [UIColor whiteColor]} forState:UIControlStateNormal];
    [backBarButtonItem setTitleTextAttributes:@{NSForegroundColorAttributeName : [UIColor orangeColor]} forState:UIControlStateHighlighted];

    // white arrow image
    UIImage *normalImage = [[[UIImage imageNamed:@"btn_normal"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal] resizableImageWithCapInsets:UIEdgeInsetsMake(0.f, 17.f, 0.f, 0.f)];

    // orange arrow image
    UIImage *pressedImage = [[[UIImage imageNamed:@"btn_on_press"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal] resizableImageWithCapInsets:UIEdgeInsetsMake(0.f, 17.f, 0.f, 0.f)];

    [backBarButtonItem setBackButtonBackgroundImage:normalImage
                    forState:UIControlStateNormal barMetrics:UIBarMetricsDefault];
    [backBarButtonItem setBackButtonBackgroundImage:pressedImage
                forState:UIControlStateHighlighted barMetrics:UIBarMetricsDefault];

    [backBarButtonItem setBackgroundImage:normalImage
                    forState:UIControlStateNormal barMetrics:UIBarMetricsDefault];
    [backBarButtonItem setBackgroundImage:pressedImage
                forState:UIControlStateHighlighted barMetrics:UIBarMetricsDefault];

    NSLog(@"NORMAL: %@ HIGHLIGHTED: %@", [backBarButtonItem backButtonBackgroundImageForState:UIControlStateNormal barMetrics:UIBarMetricsDefault],
                [backBarButtonItem backButtonBackgroundImageForState:UIControlStateHighlighted barMetrics:UIBarMetricsDefault]);
    item.backBarButtonItem = backBarButtonItem;

    NSLog(@"NORMAL: %@ HIGHLIGHTED: %@", [backBarButtonItem backButtonBackgroundImageForState:UIControlStateNormal barMetrics:UIBarMetricsDefault],
                [backBarButtonItem backButtonBackgroundImageForState:UIControlStateHighlighted barMetrics:UIBarMetricsDefault]);
}
Run Code Online (Sandbox Code Playgroud)

输出如下:

NORMAL: <_UIResizableImage: 0x16b55e10> HIGHLIGHTED: <_UIResizableImage: 0x16b593d0>
NORMAL: <_UIResizableImage: 0x16b55e10> HIGHLIGHTED: <_UIResizableImage: 0x16b593d0>
Run Code Online (Sandbox Code Playgroud)

但是突出显示状态的观察结果只是设置为正常状态而不是使用正确的突出显示图像.

正常:

背栏按钮项的正常状态

突出显示(箭头仍为白色,按钮意外变暗):

背景栏按钮项目的突出显示状态

请不要将有关leftBarButtonItem或UIButton用法的答案发布为自定义视图.这两种方法都可以在iOS 7上实现刷卡到后退行为.

UPD:关于这个问题的填充雷达#17481106.

UPD2:雷达#17481106已在iOS 8中修复.

l0g*_*g3r 5

目前Apple已经出现了错误interactivePopGestureRecognizer(在刷回动画后会冻结导航控制器的视图,你会nested pop animation can result in corrupted navigation bar在控制台中看到警告),顺便说一下,我们可以做一个小的黑客来解决这个bug.

这是一个适合我的解决方案,

子类化NavigationController类并使其委派手势

@interface CBNavigationController : UINavigationController 
@end

@implementation CBNavigationController

- (void)viewDidLoad
{
  __weak CBNavigationController *weakSelf = self;

  if ([self respondsToSelector:@selector(interactivePopGestureRecognizer)])
  {
    self.interactivePopGestureRecognizer.delegate = weakSelf;
    self.delegate = weakSelf;
  }
}

// Hijack the push method to disable the gesture

- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated
{
  if ([self respondsToSelector:@selector(interactivePopGestureRecognizer)])
    self.interactivePopGestureRecognizer.enabled = NO;

  [super pushViewController:viewController animated:animated];
}

#pragma mark UINavigationControllerDelegate

- (void)navigationController:(UINavigationController *)navigationController
       didShowViewController:(UIViewController *)viewController
                    animated:(BOOL)animate
{
  // Enable the gesture again once the new controller is shown

  if ([self respondsToSelector:@selector(interactivePopGestureRecognizer)])
    self.interactivePopGestureRecognizer.enabled = YES;
}


@end

当用户在转换过程中开始向后滑动时,弹出事件会叠加并"损坏"导航堆栈.我的解决方法是在推送转换期间暂时禁用手势识别器,并在新视图控制器加载时再次启用它.同样,使用UINavigationController子类更容易.

在此之后,您可以冷静地使用item.leftBarButtonItemUIButton作为自定义视图.


yoe*_*ven -3

您不需要自定义视图,因为它会破坏滑动,但您应该添加这一行。

self.navigationController.interactivePopGestureRecognizer.delegate = (id<UIGestureRecognizerDelegate>)self; 
Run Code Online (Sandbox Code Playgroud)

您的代码如下所示。

UIImage *normalImage = [[[UIImage imageNamed:@"btn_normal"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal] resizableImageWithCapInsets:UIEdgeInsetsMake(0.f, 17.f, 0.f, 0.f)];
UIImage *pressedImage = [[[UIImage imageNamed:@"btn_on_press"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal] resizableImageWithCapInsets:UIEdgeInsetsMake(0.f, 17.f, 0.f, 0.f)];    

UIButton *customBackButton = [UIButton buttonWithType:UIButtonTypeCustom];
[customBackButton setBackgroundImage:normalImage forState:UIControlStateNormal];
[customBackButton setBackgroundImage:pressedImage forState:UIControlStateHighlighted];
[customBackButton addTarget:self action:@selector(customBackMethod:) forControlEvents:UIControlEventTouchUpInside];
UIBarButtonItem *customBackBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:customBackButton];
self.navigationItem.leftBarButtonItem = customBackBarButtonItem;
self.navigationController.interactivePopGestureRecognizer.delegate = (id<UIGestureRecognizerDelegate>)self;

- (IBAction)customBackMethod:(id)sender {
    [self.navigationController popViewControllerAnimated:YES];
}
Run Code Online (Sandbox Code Playgroud)