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

时间:2019-04-05 15:59:29

标签: ios swift xcode uinavigationbar

我正在尝试复制Podcasts应用中显示的行为(通过Apple)。 enter image description here

如图所示,rightBarButtonItem与标题“立即收听”对齐。该图标甚至随它向上滚动(直到它消失)。

带有大标题的rightBarButtonItem的默认行为在库部分中显示: enter image description here

任何人都知道如何复制第一个示例吗?我需要一个与标题对齐的按钮。

谢谢。

1 个答案:

答案 0 :(得分:0)

我不认为他们在播客应用中使用实际的大标题。看起来他们只是在使用tableHeaderView,并使其看起来像是导航栏的一部分。之所以可行,是因为它们会擦除导航控制器的shadowImage导航栏。然后,他们在表标题视图中放置大小为.largeTitle的标签。例如:

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)")
    }

}

TitleStackView是具有要显示为“大标题” UI的UI的自定义视图。

例如:

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
    }()
}

最后,他们使用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
 }

如果您执行所有这些操作,最终将产生如下效果:

Screencast