带有UIImage的导航栏标题

80
我希望能够通过使用标志图像作为导航栏标题来自定义我的应用程序的外观,而不是使用纯文本。当我使用这段代码时:
let logo = UIImage(named: "logo.png")
self.navigationItem.titleView = logo;

我收到了错误信息“UIImage无法转换为UIView”。我该如何正确处理?


let imageView = UIImageView(frame: CGRect(x: 0, y: 0, width: 40, height: 40)) imageView.contentMode = .scaleAspectFit imageView.image = UIImage(named: "App_icons") self.navigationItem.titleView = imageView - Mallikarjun C
18个回答

204

将它放进一个UIImageView

let logo = UIImage(named: "logo.png")
let imageView = UIImageView(image:logo)
self.navigationItem.titleView = imageView

你把这个放在类声明的哪里? - azochz
@JackWu 如果我将它添加到UINavigationController.viewDidLoad(我为导航控制器实现的类)中,它不起作用,但如果我将其添加到ViewController中,则可以正常工作。但是我想保持这段代码分离(所以在扩展UINavigationController的类中)。这可能吗? - Patriks
@Ronaldoh1,这个代码与你的回答完全一样,所以我不知道你怎么能说“这不再起作用了”。 - Jack
3
这种方法可行,但你需要在被推到导航控制器的视图控制器中使用 viewDidLoad 方法,而不是在导航控制器本身中使用。 - Martin Marconcini
如果它没有起作用,请确保您将控制器的类设置为您放置此代码的文件。 - Ashkan Ghodrat
显示剩余2条评论

64

我使用这个,它在iOS 8上有效。

override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view.
    let image = UIImage(named: "YOURIMAGE")
    navigationItem.titleView = UIImageView(image: image)
}

以下是使用CGRect的示例。

override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view.
    let imageView = UIImageView(frame: CGRect(x: 0, y: 0, width: 38, height: 38))
    imageView.contentMode = .ScaleAspectFit
    let image = UIImage(named: "YOURIMAGE")
    imageView.image = image
    navigationItem.titleView = imageView
}

希望这能有所帮助。


你把这个放在导航栏子类的哪里? - Hossein
@Hossein 我记不起来了,已经过了一段时间也没有那个项目了。抱歉。 - Fernando S. Kroes

35

对于Swift 4,您可以调整imageView的大小

 let logoContainer = UIView(frame: CGRect(x: 0, y: 0, width: 270, height: 30))

 let imageView = UIImageView(frame: CGRect(x: 0, y: 0, width: 270, height: 30))
 imageView.contentMode = .scaleAspectFit
 let image = UIImage(named: "your_image")
 imageView.image = image
 logoContainer.addSubview(imageView)
 navigationItem.titleView = logoContainer

14

我尝试了@Jack在上面给出的答案,标志确实出现了,但是图像占用了整个导航栏。我想让它适合。

Swift 4,Xcode 9.2

1.为导航控制器分配值UIImage。通过将框架和图像大小相除来调整大小。

func addNavBarImage() {

        let navController = navigationController!

        let image = UIImage(named: "logo-signIn6.png") //Your logo url here
        let imageView = UIImageView(image: image)

        let bannerWidth = navController.navigationBar.frame.size.width
        let bannerHeight = navController.navigationBar.frame.size.height

        let bannerX = bannerWidth / 2 - (image?.size.width)! / 2
        let bannerY = bannerHeight / 2 - (image?.size.height)! / 2

        imageView.frame = CGRect(x: bannerX, y: bannerY, width: bannerWidth, height: bannerHeight)
        imageView.contentMode = .scaleAspectFit

        navigationItem.titleView = imageView
    }
将该功能添加在 viewDidLoad() 函数下方。
    addNavBarImage() 

关于图像资产的注意事项。上传之前,我进行了额外的边距调整而不是裁剪边缘。

最终结果:

输入图片描述


调整大小对我没有起作用,但是我通过增加右侧和左侧条目宽度的大小来解决了这个问题。 - Coder ACJHP
你能回答我的问题吗?链接为:https://stackoverflow.com/questions/69521575/title-image-position-changing-when-changing-the-tab-swift - Noorul

10

您可以使用自定义的UINavigationItem,只需要在Main.storyboard中将“Navigation Item”更改为YourCustomClass。

在Swift 3中

class FixedImageNavigationItem: UINavigationItem {

private let fixedImage : UIImage = UIImage(named: "your-header-logo.png")!
private let imageView : UIImageView = UIImageView(frame: CGRect(x: 0, y: 0, width: 50, height: 37.5))

required init?(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)
    imageView.contentMode = .scaleAspectFit
    imageView.image = fixedImage
    self.titleView = imageView

}

}

6

这个方法在2015年9月对我有效 - 希望能帮助到某位需要的人。

// 1
    var nav = self.navigationController?.navigationBar
    // 2 set the style 
    nav?.barStyle = UIBarStyle.Black
    nav?.tintColor = UIColor.yellowColor()
    // 3
    let imageView = UIImageView(frame: CGRect(x: 0, y: 0, width: 40, height: 40))
    imageView.contentMode = .ScaleAspectFit
    // 4
    let image = UIImage(named: "logo.png")
    imageView.image = image
    // 5
    navigationItem.titleView = imageView

1
如果这个解决方案不起作用,请尝试在UIViewController类中创建对导航栏的引用。@IBOutlet weak var navBar: UINavigationBar!然后,不要使用 navigationItem.titleView = imageView 而是使用 self.navBar.topItem?.titleView = imageView这里有详细的说明: - knopch1425
https://dev59.com/PYnda4cB1Zd3GeqPCKhY - knopch1425

6
以下是一个方便的Swift 4.2函数,可以显示带有标题文本的图像:-

enter image description here

override func viewDidLoad() {

    super.viewDidLoad()

    //Sets the navigation title with text and image
    self.navigationItem.titleView = navTitleWithImageAndText(titleText: "Dean Stanley", imageName: "online")
}

func navTitleWithImageAndText(titleText: String, imageName: String) -> UIView {

    // Creates a new UIView
    let titleView = UIView()

    // Creates a new text label
    let label = UILabel()
    label.text = titleText
    label.sizeToFit()
    label.center = titleView.center
    label.textAlignment = NSTextAlignment.center

    // Creates the image view
    let image = UIImageView()
    image.image = UIImage(named: imageName)

    // Maintains the image's aspect ratio:
    let imageAspect = image.image!.size.width / image.image!.size.height

    // Sets the image frame so that it's immediately before the text:
    let imageX = label.frame.origin.x - label.frame.size.height * imageAspect
    let imageY = label.frame.origin.y

    let imageWidth = label.frame.size.height * imageAspect
    let imageHeight = label.frame.size.height

    image.frame = CGRect(x: imageX, y: imageY, width: imageWidth, height: imageHeight)

    image.contentMode = UIView.ContentMode.scaleAspectFit

    // Adds both the label and image view to the titleView
    titleView.addSubview(label)
    titleView.addSubview(image)

    // Sets the titleView frame to fit within the UINavigation Title
    titleView.sizeToFit()

    return titleView

}

这个很好用。一个问题:如何确保图像始终是圆形的?应该如何设置圆角半径?@Gagandeep - Vandal

4

我已经为iOS 10和iOS 11编写了以下内容,并且它对我有效:

extension UINavigationBar {
    func setupNavigationBar() {
        let titleImageWidth = frame.size.width * 0.32
        let titleImageHeight = frame.size.height * 0.64
        var navigationBarIconimageView = UIImageView()
        if #available(iOS 11.0, *) {
            navigationBarIconimageView.widthAnchor.constraint(equalToConstant: titleImageWidth).isActive = true
            navigationBarIconimageView.heightAnchor.constraint(equalToConstant: titleImageHeight).isActive = true
        } else {
            navigationBarIconimageView = UIImageView(frame: CGRect(x: 0, y: 0, width: titleImageWidth, height: titleImageHeight))
        }
        navigationBarIconimageView.contentMode = .scaleAspectFit
        navigationBarIconimageView.image = UIImage(named: "image")
        topItem?.titleView = navigationBarIconimageView
    }
}

4

Swift 5.1+,Xcode 13+

有时候如果你的图片分辨率很高,imageView 就会偏离中心位置,我建议使用这种方法:

  lazy var navigationTitleImageView = UIImageView()

  override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
            
    self.navigationTitleImageView.image = logo
    self.navigationTitleImageView.contentMode = .scaleAspectFit
    
    self.navigationTitleImageView.translatesAutoresizingMaskIntoConstraints = false
    
    if let navC = self.navigationController{
        navC.navigationBar.addSubview(self.navigationTitleImageView)
        self.navigationTitleImageView.centerXAnchor.constraint(equalTo: navC.navigationBar.centerXAnchor).isActive = true
        self.navigationTitleImageView.centerYAnchor.constraint(equalTo: navC.navigationBar.centerYAnchor, constant: 0).isActive = true
        self.navigationTitleImageView.widthAnchor.constraint(equalTo: navC.navigationBar.widthAnchor, multiplier: 0.2).isActive = true
        self.navigationTitleImageView.heightAnchor.constraint(equalTo: navC.navigationBar.widthAnchor, multiplier: 0.088).isActive = true
    }
}

并且viewWillDisappear()

  override func viewWillDisappear(_ animated: Bool) {
    super.viewWillDisappear(animated)
    self.navigationTitleImageView.removeFromSuperview()
}

否则就减小图片尺寸。

self.setNavigationBar() 是什么? - Javier Heisecke
实际上,这是以下代码所写的自定义函数。谢谢指出,我会将其删除。 - Kedar Sukerkar
这个解决方案的问题在于,如果你将文本设置为“View Controller”的title属性或此导航控制器的navigationItem.title,那么该文本将出现在你添加的图像后面,而我们不希望发生这种情况。 - Rhenz

3
如果你更喜欢使用自动布局,并想在导航栏中保留一个永久固定的图像,而不是每个屏幕都有动画效果,那么以下解决方案可以很好地解决问题:
class CustomTitleNavigationController: UINavigationController {

override func viewDidLoad() {
    super.viewDidLoad()

    let logo = UIImage(named: "MyHeaderImage")

    let imageView = UIImageView(image:logo)
    imageView.contentMode = .scaleAspectFit
    imageView.translatesAutoresizingMaskIntoConstraints = false

    navigationBar.addSubview(imageView)

    navigationBar.addConstraint (navigationBar.leftAnchor.constraint(equalTo: imageView.leftAnchor, constant: 0))
    navigationBar.addConstraint (navigationBar.rightAnchor.constraint(equalTo: imageView.rightAnchor, constant: 0))
    navigationBar.addConstraint (navigationBar.topAnchor.constraint(equalTo: imageView.topAnchor, constant: 0))
    navigationBar.addConstraint (navigationBar.bottomAnchor.constraint(equalTo: imageView.bottomAnchor, constant: 0))
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接