添付の画像にあるようなナビゲーションバーを作成したいと思います。
ナビゲーションバーのタイトルは、画像とテキストの組み合わせになります。
これは、ベストプラクティスに従って実行する必要がありますか?
どうすればそれができますか?
この回答が示す のように、最も簡単な解決策は、画像にテキストを追加し、その画像を次のようにナビゲーションバーに追加することです。
var image = UIImage(named: "logo.png")
self.navigationItem.titleView = UIImageView(image: image)
ただし、テキストと画像を別々に追加する必要がある場合(たとえば、ローカリゼーションの場合)、ナビゲーションバーのタイトルビューをUIView
に追加し、設定することで、画像とテキストの両方を含むように設定できます。たとえば、navigationItem
のそのUIView
に対するタイトルビュー(ナビゲーションバーがナビゲーションコントローラーの一部であると仮定):
// Only execute the code if there's a navigation controller
if self.navigationController == nil {
return
}
// Create a navView to add to the navigation bar
let navView = UIView()
// Create the label
let label = UILabel()
label.text = "Text"
label.sizeToFit()
label.center = navView.center
label.textAlignment = NSTextAlignment.Center
// Create the image view
let image = UIImageView()
image.image = UIImage(named: "Image.png")
// To maintain the image's aspect ratio:
let imageAspect = image.image!.size.width/image.image!.size.height
// Setting the image frame so that it's immediately before the text:
image.frame = CGRect(x: label.frame.Origin.x-label.frame.size.height*imageAspect, y: label.frame.Origin.y, width: label.frame.size.height*imageAspect, height: label.frame.size.height)
image.contentMode = UIViewContentMode.ScaleAspectFit
// Add both the label and image view to the navView
navView.addSubview(label)
navView.addSubview(image)
// Set the navigation bar's navigation item's titleView to the navView
self.navigationItem.titleView = navView
// Set the navView's frame to fit within the titleView
navView.sizeToFit()
水平方向のUIStackView
を使用すると、はるかにクリーンで簡単になります
次の拡張子をUIViewController
に追加してください
extension UIViewController {
func setTitle(_ title: String, andImage image: UIImage) {
let titleLbl = UILabel()
titleLbl.text = title
titleLbl.textColor = UIColor.white
titleLbl.font = UIFont.systemFont(ofSize: 20.0, weight: .bold)
let imageView = UIImageView(image: image)
let titleView = UIStackView(arrangedSubviews: [imageView, titleLbl])
titleView.axis = .horizontal
titleView.spacing = 10.0
navigationItem.titleView = titleView
}
}
次に、viewController内で使用します。
setTitle("yourTitle", andImage: UIImage(named: "yourImage"))
(これにより、テキストとアイコンが中央に揃えられます。テキストを中央に配置し、アイコンを左側に配置する場合は、アイコンの幅に等しい幅の制約を持つ空のUIView
を追加するだけです)
これがSwift 4の2セントです。受け入れられた答えは私にはうまくいきませんでした(ほとんど画面から外れていました):
// .. in ViewController
var navBar = CustomTitleView()
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
// =================== navBar =====================
navBar.loadWith(title: "Budget Overview", leftImage: Images.pie_chart)
self.navigationItem.titleView = navBar
}
class CustomTitleView: UIView
{
var title_label = CustomLabel()
var left_imageView = UIImageView()
override init(frame: CGRect){
super.init(frame: frame)
setup()
}
required init?(coder aDecoder: NSCoder){
super.init(coder: aDecoder)
setup()
}
func setup(){
self.addSubview(title_label)
self.addSubview(left_imageView)
}
func loadWith(title: String, leftImage: UIImage?)
{
//self.backgroundColor = .yellow
// =================== title_label ==================
//title_label.backgroundColor = .blue
title_label.text = title
title_label.font = UIFont.systemFont(ofSize: FontManager.fontSize + 5)
// =================== imageView ===================
left_imageView.image = leftImage
setupFrames()
}
func setupFrames()
{
let height: CGFloat = Navigation.topViewController()?.navigationController?.navigationBar.frame.height ?? 44
let image_size: CGFloat = height * 0.8
left_imageView.frame = CGRect(x: 0,
y: (height - image_size) / 2,
width: (left_imageView.image == nil) ? 0 : image_size,
height: image_size)
let titleWidth: CGFloat = title_label.intrinsicContentSize.width + 10
title_label.frame = CGRect(x: left_imageView.frame.maxX + 5,
y: 0,
width: titleWidth,
height: height)
contentWidth = Int(left_imageView.frame.width)
self.frame = CGRect(x: 0, y: 0, width: CGFloat(contentWidth), height: height)
}
var contentWidth: Int = 0 //if its CGFloat, it infinitely calls layoutSubviews(), changing franction of a width
override func layoutSubviews() {
super.layoutSubviews()
self.frame.size.width = CGFloat(contentWidth)
}
}
Swift 4.2 + Interface Builderソリューション
Lyndsey Scott 's answer の続編として、InterfaceBuilderでUIView
.xibを作成し、それを使用してタイトルをレイアウトすることもできます。と画像を作成し、@IBOutlet
を介してオンザフライで更新します。これは、動的コンテンツ、国際化、保守性などに役立ちます。
UIView
アウトレットを使用してUILabel
サブクラスを作成し、新しい.xibをこのクラスに割り当てます。
import UIKit
class FolderTitleView: UIView {
@IBOutlet weak var title : UILabel!
/// Create an instance of the class from its .xib
class func instanceFromNib() -> FolderTitleView {
return UINib(nibName: "FolderTitleView", bundle: nil).instantiate(withOwner: nil, options: nil)[0] as! FolderTitleView
}
}
ラベルを.xibのコンセント(私の例ではtitle
)に接続し、次にUIViewController
に接続します。
/// Reference to the title view
var folderTitleView : FolderTitleView?
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
// Set the screen title to match the active folder
updateTitle()
}
/// Updates the title of the navigation controller.
func updateTitle() {
self.title = ""
if folderTitleView == nil {
folderTitleView = FolderTitleView.instanceFromNib()
self.navigationItem.titleView = folderTitleView
}
folderTitleView!.title.text = "Listening"
folderTitleView!.layoutIfNeeded()
}
これにより、コードから簡単に更新できる画像が埋め込まれた、優れたセルフセンタリングタイトルバーが作成されます。
//私のために働いた
ビューに画像とラベルを追加した後、navigationItemに同じビューを追加します
ナビゲーションビュー= UIView(フレーム:CGRect(x:0、y:0、幅:50、高さ:55))
let labell : UILabel = UILabel(frame: CGRect(x: -38, y: 25, width: 150, height: 25))
labell.text = "Your text"
labell.textColor = UIColor.black
labell.font = UIFont.boldSystemFont(ofSize: 10)
navigationView.addSubview(labell)
let image : UIImage = UIImage(named: ValidationMessage.headerLogoName)!
let imageView = UIImageView(frame: CGRect(x: -20, y: 0, width: 100, height: 30))
imageView.contentMode = .scaleAspectFit
imageView.image = image
//navigationItem.titleView = imageView
navigationView.addSubview(imageView)
navigationItem.titleView = navigationView