xcode 带有大标题 iOS 11 的导航栏图像
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/47062176/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Image for Navigation Bar with Large Title iOS 11
提问by Tung Fam
AppStore app has an icon with an image on the right side of the NabBar with Large Title:
AppStore 应用程序在 NabBar 的右侧有一个带有大标题的图像图标:
Would really appreciate if anyone knows how to implementit or ideason how to do it.
如果有人知道如何实施它或有关如何实施的想法,将不胜感激。
BTW: Setting an image for UIButton inside of UIBarButtonItem won't work. Tried already. The button sticks to the top of the screen:
顺便说一句:在 UIBarButtonItem 内为 UIButton 设置图像将不起作用。已经试过了。该按钮粘在屏幕顶部:
回答by Tung Fam
After several hours of coding, I finally managed to make it work. I also decided to write a detailed tutorial: link. Follow it in case you prefer very detailed instructions.
经过几个小时的编码,我终于设法让它工作了。我也决定写一个详细的教程:链接。如果您更喜欢非常详细的说明,请遵循它。
Complete project on GitHub: link.
GitHub 上的完整项目:链接。
Here are 5 stepsto accomplish it:
这里有5 个步骤来完成它:
Step 1: Create an image
第 1 步:创建图像
private let imageView = UIImageView(image: UIImage(named: "image_name"))
Step 2: Add Constants
第 2 步:添加常量
/// WARNING: Change these constants according to your project's design
private struct Const {
/// Image height/width for Large NavBar state
static let ImageSizeForLargeState: CGFloat = 40
/// Margin from right anchor of safe area to right anchor of Image
static let ImageRightMargin: CGFloat = 16
/// Margin from bottom anchor of NavBar to bottom anchor of Image for Large NavBar state
static let ImageBottomMarginForLargeState: CGFloat = 12
/// Margin from bottom anchor of NavBar to bottom anchor of Image for Small NavBar state
static let ImageBottomMarginForSmallState: CGFloat = 6
/// Image height/width for Small NavBar state
static let ImageSizeForSmallState: CGFloat = 32
/// Height of NavBar for Small state. Usually it's just 44
static let NavBarHeightSmallState: CGFloat = 44
/// Height of NavBar for Large state. Usually it's just 96.5 but if you have a custom font for the title, please make sure to edit this value since it changes the height for Large state of NavBar
static let NavBarHeightLargeState: CGFloat = 96.5
}
Step 3: setup UI:
第 3 步:设置 UI:
private func setupUI() {
navigationController?.navigationBar.prefersLargeTitles = true
title = "Large Title"
// Initial setup for image for Large NavBar state since the the screen always has Large NavBar once it gets opened
guard let navigationBar = self.navigationController?.navigationBar else { return }
navigationBar.addSubview(imageView)
imageView.layer.cornerRadius = Const.ImageSizeForLargeState / 2
imageView.clipsToBounds = true
imageView.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
imageView.rightAnchor.constraint(equalTo: navigationBar.rightAnchor,
constant: -Const.ImageRightMargin),
imageView.bottomAnchor.constraint(equalTo: navigationBar.bottomAnchor,
constant: -Const.ImageBottomMarginForLargeState),
imageView.heightAnchor.constraint(equalToConstant: Const.ImageSizeForLargeState),
imageView.widthAnchor.constraint(equalTo: imageView.heightAnchor)
])
}
Step 4: create image resizing method
第 4 步:创建图像大小调整方法
private func moveAndResizeImage(for height: CGFloat) {
let coeff: CGFloat = {
let delta = height - Const.NavBarHeightSmallState
let heightDifferenceBetweenStates = (Const.NavBarHeightLargeState - Const.NavBarHeightSmallState)
return delta / heightDifferenceBetweenStates
}()
let factor = Const.ImageSizeForSmallState / Const.ImageSizeForLargeState
let scale: CGFloat = {
let sizeAddendumFactor = coeff * (1.0 - factor)
return min(1.0, sizeAddendumFactor + factor)
}()
// Value of difference between icons for large and small states
let sizeDiff = Const.ImageSizeForLargeState * (1.0 - factor) // 8.0
let yTranslation: CGFloat = {
/// This value = 14. It equals to difference of 12 and 6 (bottom margin for large and small states). Also it adds 8.0 (size difference when the image gets smaller size)
let maxYTranslation = Const.ImageBottomMarginForLargeState - Const.ImageBottomMarginForSmallState + sizeDiff
return max(0, min(maxYTranslation, (maxYTranslation - coeff * (Const.ImageBottomMarginForSmallState + sizeDiff))))
}()
let xTranslation = max(0, sizeDiff - coeff * sizeDiff)
imageView.transform = CGAffineTransform.identity
.scaledBy(x: scale, y: scale)
.translatedBy(x: xTranslation, y: yTranslation)
}
Step 5:
第 5 步:
override func scrollViewDidScroll(_ scrollView: UIScrollView) {
guard let height = navigationController?.navigationBar.frame.height else { return }
moveAndResizeImage(for: height)
}
Hope it's clear and helps you! Please let me know in comments if you have any additional questions.
希望它很清楚并能帮助你!如果您有任何其他问题,请在评论中告诉我。
回答by Casey West
You could create the UIBarButtonItem using a custom view. This custom view will be a UIView with the actual UIButton (as a subview) placed x pixels from the top (x=the number of pixels you want to move it down).
您可以使用自定义视图创建 UIBarButtonItem。这个自定义视图将是一个 UIView,实际的 UIButton(作为子视图)从顶部放置 x 个像素(x=你想要向下移动的像素数)。
回答by huahuahu
Thanks to @TungFam, I think I have a better solution. check it out
感谢@TungFam,我想我有一个更好的解决方案。一探究竟
two points:
两点:
change button frame according to navigation bar height
// adjust topview height override func scrollViewDidScroll(_ scrollView: UIScrollView) { guard let navBar = self.navigationController?.navigationBar else { return } // hardcoded .. to improve if navBar.bounds.height > 44 + 40 + 10 { NSLayoutConstraint.deactivate(heightConstraint) heightConstraint = [topview.heightAnchor.constraint(equalToConstant: 40)] NSLayoutConstraint.activate(heightConstraint) } else { NSLayoutConstraint.deactivate(heightConstraint) var height = navBar.bounds.height - 44 - 10 if height < 0 { height = 0 } heightConstraint = [topview.heightAnchor.constraint(equalToConstant: height)] NSLayoutConstraint.activate(heightConstraint) } }
change button alpha according to pop/push progress
@objc func onGesture(sender: UIGestureRecognizer) { switch sender.state { case .began, .changed: if let ct = navigationController?.transitionCoordinator { topview.alpha = ct.percentComplete } case .cancelled, .ended: return case .possible, .failed: break } }
根据导航栏高度更改按钮框架
// adjust topview height override func scrollViewDidScroll(_ scrollView: UIScrollView) { guard let navBar = self.navigationController?.navigationBar else { return } // hardcoded .. to improve if navBar.bounds.height > 44 + 40 + 10 { NSLayoutConstraint.deactivate(heightConstraint) heightConstraint = [topview.heightAnchor.constraint(equalToConstant: 40)] NSLayoutConstraint.activate(heightConstraint) } else { NSLayoutConstraint.deactivate(heightConstraint) var height = navBar.bounds.height - 44 - 10 if height < 0 { height = 0 } heightConstraint = [topview.heightAnchor.constraint(equalToConstant: height)] NSLayoutConstraint.activate(heightConstraint) } }
根据弹出/推送进度更改按钮 alpha
@objc func onGesture(sender: UIGestureRecognizer) { switch sender.state { case .began, .changed: if let ct = navigationController?.transitionCoordinator { topview.alpha = ct.percentComplete } case .cancelled, .ended: return case .possible, .failed: break } }