iOS 7: Custom Back Indicator Image Position

与世无争的帅哥 提交于 2019-11-27 13:49:49

问题


I'm having trouble setting properly a custom back indicator image. The indicator is not centered!

Here is a pic:

I'm setting the indicator image in didFinishLaunchingWithOptions: method...

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

   UIImage *image = [UIImage imageNamed:@"Back"];
   [UINavigationBar appearance].backIndicatorImage = image;
   [UINavigationBar appearance].backIndicatorTransitionMaskImage = image;

   return YES;
}

How can I center it?

p.s I've already read this Custom back indicator image in iOS 7 not vertically centered, but actually it didn't work for me.


回答1:


That happens because you are just changing the image source of the Back Indicator in your UINavigationView, and not the frame as well. See, when the UINavigationView is created, the Back Indicator's frame is set to hold the size of the default iOS 7 back button image. The default back button image is bigger than yours, and that's why it looks not aligned.

To fix that you have to reset the Back Indicator's Frame to hold the size of your image. Another option is to create a UIButton with the right frame size and image and assign to a UIBarButtonItem. Then you can replace the backBarButtonItem from your UINavigationItem with the new UIBarButtonItem you created.




回答2:


 UIEdgeInsets insets = UIEdgeInsetsMake(0, 0, 2, 0);
 UIImage *backArrowImage = [[UIImage imageNamed:@"Back"] imageWithAlignmentRectInsets:insets];

 [[UINavigationBar appearance] setBackIndicatorImage:backArrowImage];
 [[UINavigationBar appearance] setBackIndicatorTransitionMaskImage:backArrowImage];



回答3:


This solution worked for me in Swift 2.1. iOS 9.2.1. (XCode 7.2) on iPhone in portrait Mode. I have tested it on the simulators iPhone 5 and 6+ and it also worked.

import UIKit

class EVEMainNaviVC: UINavigationController
{
    override func viewWillAppear(animated: Bool)
    {
        super.viewWillAppear(animated)
    }

override func viewDidLoad()
{
    super.viewDidLoad()
    self.view.backgroundColor = APP_BACKGROUND_COLOR
    self.setupAppNaviagtionBar()
}


private func setupAppNaviagtionBar()
{
    dispatch_async(dispatch_get_main_queue())
    { () -> Void in
        self.navigationBar.setHeight(55.0)
        self.navigationBar.translucent        = false
        self.navigationBar.alpha              = 1.0
        self.navigationBar.barTintColor       = UIColor.whiteColor()
        let newBackButtonImageInset                         = UIEdgeInsetsMake(0, 0, -6, 0)
        let newBackButtonImage                              = UIImage(named: "back")?.imageWithAlignmentRectInsets(newBackButtonImageInset)
        self.navigationBar.backIndicatorImage               = newBackButtonImage
        self.navigationBar.backIndicatorTransitionMaskImage = newBackButtonImage
        self.navigationBar.tintColor = CUSTOM_BUTTON_COLOR
    }
}
}



回答4:


This is how I dealt with the problem using Appearance API and is working great. When changing backButtonBackgroundImage image is automatically stretched across barButtonItem so we must resize it back to original using resizableImageWithCapInsets:. To position it inside barButtonItem we then use imageWithAlignmentRectInsets to add caps around it. Then just assign it using setBackButtonBackgroundImage:forState:barMetrics.

Just play with the numbers and you will find the right position.

int imageSize = 24;
UIImage *barBackBtnImg = [[[UIImage imageNamed:@"backButton"] resizableImageWithCapInsets:UIEdgeInsetsMake(0, imageSize, 0, 0)] imageWithAlignmentRectInsets:UIEdgeInsetsMake(0, -10, 0, -10)];
[[UIBarButtonItem appearance] setBackButtonBackgroundImage:barBackBtnImg forState:UIControlStateNormal barMetrics:UIBarMetricsDefault];



回答5:


I found the simplest solution I have ever seen. Just three things.

  1. Override UINavigationBar and use it in your UINavigationController

    let navigationController = UINavigationController(navigationBarClass: NavigationBar.self, toolbarClass: nil)
    navigationController.viewControllers = [viewController]
    
  2. Setup your indicator images:

    backIndicatorImage = #imageLiteral(resourceName: "back")
    backIndicatorTransitionMaskImage = #imageLiteral(resourceName: "back")
    
  3. Implement layoutSubviews in your custom UINavigationBar class.

    override func layoutSubviews() {
        super.layoutSubviews()
    
        subviews.forEach { (view) in
            if let imageView = view as? UIImageView {
                if imageView.image == backIndicatorImage || imageView.image == backIndicatorTransitionMaskImage {
                    view.frame.origin.y = floor((frame.height - view.frame.height) / 2.0)
                }
            }
        }
    }
    

That is all. :)




回答6:


My goal was to position the back button image without meddling with the subviews of the UINavigationItem. So, what I did was to create an extension for UIImage that adds a padding around of the image.

extension UIImage {
    public func imageWith(padding: UIEdgeInsets) -> UIImage {
        let origin = CGPoint(x: padding.left, y: padding.top)
        let sizeWithPadding = CGSize(width: padding.left + size.width + padding.right, height: padding.top + size.height + padding.bottom)

        UIGraphicsBeginImageContextWithOptions(sizeWithPadding, false, 0.0)
        draw(in: CGRect(origin: origin, size: size))

        let imageWithPadding = UIGraphicsGetImageFromCurrentImageContext() ?? self
        UIGraphicsEndImageContext()

        return imageWithPadding
    }
}

For example: if you want to move the image to the top you add the corresponding padding to the bottom. .imageWith(padding: UIEdgeInsets(top: 0, left: 0, bottom: 2, right: 0))



来源:https://stackoverflow.com/questions/25250389/ios-7-custom-back-indicator-image-position

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!