简体   繁体   English

带有大标题和右侧 UIBarButtonItem 的导航栏

[英]Navigation bar with large titles and right UIBarButtonItem

I am trying to replicate the behaviour shown in Podcasts app (by apple).我正在尝试复制 Podcasts 应用程序(由苹果提供)中显示的行为。 在此处输入图片说明

As shown in the image, the rightBarButtonItem is aligned with the title "Listen Now".如图所示, rightBarButtonItem与标题“Listen Now”对齐。 The icon even scrolls up with it (until it disappears).图标甚至会随着它向上滚动(直到它消失)。

The default behavior for a rightBarButtonItem with large titles it is shown in the library section:带有大标题的rightBarButtonItem的默认行为显示在库部分中: 在此处输入图片说明

Anyone knows how to replicate the first example?有谁知道如何复制第一个例子? I need a button aligned with the title.我需要一个与标题对齐的按钮。

Thanks.谢谢。

I don't think they use actual large titles in the podcast app.我不认为他们在播客应用程序中使用真正的大标题。 It looks like they are just using a tableHeaderView and making it appear as though it's part of the navigation bar.看起来他们只是在使用tableHeaderView并使其看起来好像它是导航栏的一部分。 This works because they erase the shadowImage of the navigation controllers the navigation bar.这是有效的,因为它们擦除了导航栏导航控制器的shadowImage Then they place a label with a .largeTitle sized font in the table header view.然后他们在表格标题视图中放置一个带有.largeTitle大小字体的标签。 For example:例如:

class ViewController: UIViewController {

    @IBOutlet weak var tableView: UITableView!

    lazy var titleStackView: TitleStackView = {
        let titleStackView = TitleStackView(frame: CGRect(origin: .zero, size: CGSize(width: view.bounds.width, height: 44.0)))
        titleStackView.translatesAutoresizingMaskIntoConstraints = false
        return titleStackView
    }()

    lazy var tableHeaderView: UIView = {
        let tableHeaderView = UIView(frame: CGRect(origin: .zero, size: CGSize(width: view.bounds.width, height: 44.0)))
        tableHeaderView.addSubview(titleStackView)
        titleStackView.leadingAnchor.constraint(equalTo: tableHeaderView.leadingAnchor, constant: 16.0).isActive = true
        titleStackView.topAnchor.constraint(equalTo: tableHeaderView.topAnchor).isActive = true
        titleStackView.trailingAnchor.constraint(equalTo: tableHeaderView.trailingAnchor, constant: -16.0).isActive = true
        titleStackView.bottomAnchor.constraint(equalTo: tableHeaderView.bottomAnchor).isActive = true
        return tableHeaderView
    }()

    override func viewDidLoad() {
        super.viewDidLoad()
        title = nil
        navigationController?.navigationBar.isTranslucent = false
        navigationController?.navigationBar.barTintColor = UIColor.white
        navigationController?.navigationBar.shadowImage = UIImage()
        tableView.tableHeaderView = tableHeaderView
        tableView.register(UITableViewCell.self, forCellReuseIdentifier: "\(UITableViewCell.self)")
    }

}

Where TitleStackView is a custom view with the UI that you want to appear as the "large title" UI.其中TitleStackView是一个自定义视图,其 UI 要显示为“大标题”UI。

For example:例如:

class TitleStackView: UIStackView {

    override init(frame: CGRect) {
        super.init(frame: frame)
        commonInit()
    }

    required init(coder: NSCoder) {
        super.init(coder: coder)
        commonInit()
    }

    private func commonInit() {
        axis = .horizontal
        alignment = .center
        addArrangedSubview(titleLabel)
        addArrangedSubview(button)
    }

    lazy var titleLabel: UILabel = {
        let label = UILabel()
        label.font = UIFont.systemFont(ofSize: UIFont.preferredFont(forTextStyle: .largeTitle).pointSize, weight: .heavy)
        label.text = "Listen Now"
        label.setContentHuggingPriority(.defaultLow, for: .horizontal)
        label.translatesAutoresizingMaskIntoConstraints = false
        return label
    }()

    lazy var button: UIButton = {
        let buttonWidth: CGFloat = 35.0
        let button = UIButton(frame: CGRect(origin: .zero, size: CGSize(width: buttonWidth, height: buttonWidth)))
        button.backgroundColor = .purple
        button.setTitleColor(.white, for: .normal)
        button.setTitle("B", for: .normal)
        button.translatesAutoresizingMaskIntoConstraints = false
        button.widthAnchor.constraint(equalToConstant: buttonWidth).isActive = true
        button.heightAnchor.constraint(equalToConstant: buttonWidth).isActive = true
        button.layer.cornerRadius = button.bounds.height * 0.5
        button.layer.masksToBounds = true
        return button
    }()
}

Finally, they use the UIScrollViewDelegate callback to monitor when to show the title:最后,他们使用UIScrollViewDelegate回调来监控何时显示标题:

func scrollViewDidScroll(_ scrollView: UIScrollView) {
    let maxTitlePoint = tableView.convert(CGPoint(x: titleStackView.titleLabel.bounds.minX, y: titleStackView.titleLabel.bounds.maxY), from: titleStackView.titleLabel)
    title = scrollView.contentOffset.y > maxTitlePoint.y ? "Listen Now" : nil
 }

If you do all of those things you end up with an effect like the following:如果你做所有这些事情,你最终会得到如下效果:

截屏

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM