导航栏按钮项的图像(Swift)

23

我想在Swift中的导航栏左侧显示一张图片。

我尝试添加一个导航栏按钮项目并在那里设置图像。

问题是,我必须使用非常小的图像才能使其适合导航栏。但是制作这样小的图像会导致像素化,特别是在更大的iPhone 6和6 Plus上。

有没有办法使用高质量的图像,然后将其框架设置为适应导航栏的边界内?

我的尝试:

var image = UIImage(named: "Harp.png")

image = image?.imageWithRenderingMode(UIImageRenderingMode.AlwaysOriginal)

self.navigationItem.leftBarButtonItem = UIBarButtonItem(image: image, style: UIBarButtonItemStyle.Plain, target: nil, action: nil)
self.navigationItem.leftBarButtonItem.frame = CGRectMake(0, 0, 53, 31)
//image.frame = CGRectMake(0, 0, 53, 31)

我尝试先将框架放在图像上,然后再放在工具栏按钮项上。

但是这会出现错误:

表达式的类型在没有更多上下文的情况下是不明确的。


1
为什么不使用资源目录? - Vinay Jain
Vinay是对的。使用资源目录易于且自动化。如果我错了,请纠正我,但是我使用以下分辨率的@1、@2、@3:44x44、88x88和132x132像素。此外,有时我需要使用图像插入来更正尺寸(如果您在IBuilder中有该按钮,则可以从那里修复它)。 - MLBDG
6个回答

56

试一下

let button = UIButton(type: UIButtonType.Custom)
button.setImage(UIImage(named: "yourImageName.png"), forState: UIControlState.Normal)
button.addTarget(self, action:Selector("callMethod"), forControlEvents: UIControlEvents.TouchDragInside)
button.frame=CGRectMake(0, 0, 30, 30)
let barButton = UIBarButtonItem(customView: button)
self.navigationItem.leftBarButtonItems = [newBackButton,barButton]

对于Swift 3

let button = UIButton.init(type: .custom)
button.setImage(UIImage.init(named: "yourImageName.png"), for: UIControlState.normal)
button.addTarget(self, action:#selector(ViewController.callMethod), for:.touchUpInside)
button.frame = CGRect.init(x: 0, y: 0, width: 30, height: 30) //CGRectMake(0, 0, 30, 30)
let barButton = UIBarButtonItem.init(customView: button)
            self.navigationItem.leftBarButtonItem = barButton

Swift 4

->

Swift 4

let button = UIButton(type: UIButton.ButtonType.custom)
button.setImage(UIImage(named: "getstarted"), for: .normal)
button.addTarget(self, action:#selector(callMethod), for: .touchDragInside)
button.frame = CGRect(x: 0, y: 0, width: 30, height: 30)
let barButton = UIBarButtonItem(customView: button)
self.navigationItem.leftBarButtonItems = [barButton]

这里是操作

@objc func callMethod() {   
    //do stuff here
 }

1
有一个问题,动作没有被触发?我有一个名为“tryLogout”的动作和一个名为tryLogout()的函数,但是注销功能没有被触发? - user2363025
2
对不起,我看到只需要更改事件类型。 - user2363025
你确定第二个是针对Swift 3的吗?我记得在Swift 3中,所有方法的参数都会有标签。但是你的 button.addTarget(self... 第一个参数没有标签。 - Chen Li Yong
1
对我有用(Swift 3.0)。忘记设置框架 xD。 - cloudcal
如果我想在图像旁边添加一小段文本怎么办?例如,我想显示用户拥有的硬币数量。因此,我需要显示一个硬币图像和其旁边的硬币数量。这该如何实现?谢谢。 - Eyal Ben Yehuda

9
请使用以下代码:
self.navigationItem.leftBarButtonItem = nil

let button = UIButton(type: .custom)
button.setImage(UIImage (named: "ChatTab"), for: .normal)
button.frame = CGRect(x: 0.0, y: 0.0, width: 35.0, height: 35.0)
//button.addTarget(target, action: nil, for: .touchUpInside)
let barButtonItem = UIBarButtonItem(customView: button)

let button2 = UIButton(type: .custom)
button2.setImage(UIImage (named: "ActivityTab"), for: .normal)
button2.frame = CGRect(x: 0.0, y: 0.0, width: 35.0, height: 35.0)
//button.addTarget(target, action: nil, for: .touchUpInside)

let barButtonItem2 = UIBarButtonItem(customView: button2)
self.navigationItem.rightBarButtonItems = [barButtonItem, barButtonItem2]

输出: 在此输入图片描述


5

使用 Swift 5 和 XCode 11 制作带有圆角图片的导航栏项目,图片可以从资产中获取或从 URL 下载。

1)新建文件:UIBarButtonItem+RoundedView.swift

import Foundation

class ImageBarButton : UIView {
    var imageView: UIImageView!
    var button: UIButton!

    convenience init(withUrl imageURL: URL? = nil, withImage image: UIImage? = nil, frame: CGRect = CGRect(x: 0, y: 0, width: 40, height: 40)) {
        self.init(frame: frame)

        imageView = UIImageView(frame: frame)
        imageView.backgroundColor = .white
        imageView.layer.cornerRadius = frame.height/2
        imageView.clipsToBounds = true
        imageView.contentMode = .scaleAspectFill
        imageView.clipsToBounds = true
        addSubview(imageView)

        button = UIButton(frame: frame)
        button.backgroundColor = .clear
        button.setTitle("", for: .normal)
        addSubview(button)

        if let url = imageURL { // you can use pods like Nuke or Kingfisher 
         URLSession(configuration: .default).dataTask(with: URL(string: imageUrl)!) {[weak self] (data, response, error) in
          if let data = data , let image = UIImage(data: data) {
              DispatchQueue.main.async {
                self?.imgView.image = image
              }
           }
         }.resume()
        } else if let image = image {
            self.imageView.image = image
        }
    }

    func load()-> UIBarButtonItem {
        return UIBarButtonItem(customView: self)
    }
}

2) 添加导航栏的项目,可以使用navigationItem.rightBarButtonItems,navigationItem.leftBarButtonItems:

private func initalizeNavigationBarItems() {
    let searchBarButtonView = ImageBarButton(withImage: #imageLiteral(resourceName: "greenSearchIcon")) // Assets
    searchBarButtonView.button.addTarget(self, action: #selector(presentSearchViewController), for: .touchUpInside)

    if let user = AccountManager.currentUser, let userProfilePictureURL = user.imageUrl { // API Url
        let profileBarButtonView = ImageBarButton(withUrl: userProfilePictureURL)
        profileBarButtonView.button.addTarget(self, action: #selector(presentMoreViewController), for: .touchUpInside)
        navigationItem.rightBarButtonItems = [searchBarButtonView.load(), profileBarButtonView.load()]
    } else {
        let profileBarButtonView = ImageBarButton(withImage: #imageLiteral(resourceName: "profileIcon"))
        profileBarButtonView.button.addTarget(self, action: #selector(presentMoreViewController), for: .touchUpInside)
        navigationItem.rightBarButtonItems = [searchBarButtonView.load(), profileBarButtonView.load()]
    }
}

@objc func presentMoreViewController(_ sender: Any) {
    // present MoreViewController
}

@objc func presentSearchViewController(_ sender: Any) {
    // present SearchViewController
}

预览

在这里输入图片描述


4

Swift 4 和 5:

let imageView = UIImageView(image: UIImage(named: "Harp"))
let buttonItem = UIBarButtonItem(customView: imageView)
self.navigationItem.leftBarButtonItem = buttonItem

虽然这段代码可能解决了问题,但是包括解释这段代码如何以及为什么解决问题的说明会真正有助于提高您的帖子质量,并且可能会得到更多的赞。请记住,您正在回答未来的读者,而不仅仅是现在提问的人。请编辑您的答案以添加解释并指出适用的限制和假设。 - double-beep
@double-beep 接受的答案没有做到这一点。而且你可以看到它是一个很差的答案。在你阅读完这个之后,我会删除我的更好的解决方案。 - elarcoiris
不,你不需要这样做,我也没有强迫你删除你的答案。最好不要这样做。当然,仅有代码的解决方案很棒,但是带有解释的解决方案更加出色,会获得更多的赞同。 - double-beep

1

Swift 5

您需要使用约束来正确设置带有图像的导航栏按钮。

let button = UIButton(type: .custom)
button.setImage(UIImage(named: yourImageName), for: .normal)
button.translatesAutoresizingMaskIntoConstraints = false
button.widthAnchor.constraint(equalToConstant: 40).isActive = true
button.heightAnchor.constraint(equalToConstant: 40).isActive = true
let barButton = UIBarButtonItem(customView: button)
navigationItem.rightBarButtonItem = barButton

1
有一种方法可以根据设备使用不同大小的图像,这被称为资源目录。您可能已经在项目中拥有一个,如果没有,可以使用文件>新建>文件>资源>资源目录添加一个。
在资源目录中,您可以拥有多个“图像集”(这些将显示在左侧)。使用底部的“+”添加一个新的图像集。对于每个图像集,您可以为@1x、@2x和@3x的每个图像提供不同的图像(例如不同大小)。
然后,在代码中使用UIImage(named:"name_of_image_set")即可使用其中一个图像-请注意没有扩展名。根据设备加载正确的图像。
希望这可以帮助!

问题在于更大的图片超出了导航栏。通过Avijit的解决方案,问题得到了解决。 - user2363025

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