diff --git a/Sources/RDEpubReaderView/EPUBUI/RDEPUBReaderTopToolView.swift b/Sources/RDEpubReaderView/EPUBUI/RDEPUBReaderTopToolView.swift index 28ddb84..0ca47f6 100644 --- a/Sources/RDEpubReaderView/EPUBUI/RDEPUBReaderTopToolView.swift +++ b/Sources/RDEpubReaderView/EPUBUI/RDEPUBReaderTopToolView.swift @@ -1,6 +1,6 @@ import UIKit -public final class RDEPUBReaderTopToolView: RDEPUBReaderToolView, RDEPUBReaderTopToolViewProtocol { +open class RDEPUBReaderTopToolView: RDEPUBReaderToolView, RDEPUBReaderTopToolViewProtocol { public var onBack: (() -> Void)? @@ -8,9 +8,14 @@ public final class RDEPUBReaderTopToolView: RDEPUBReaderToolView, RDEPUBReaderTo public var onSearch: (() -> Void)? + /// 宿主可配置的登录 / 购买等业务入口。未设置标题时不占用工具栏空间。 + public var onAuthorization: (() -> Void)? + private let backButton = RDEPUBReaderTintButton(type: .system) private let searchButton = RDEPUBReaderTintButton(type: .system) private let bookmarkButton = RDEPUBReaderTintButton(type: .system) + private let authorizationButton = RDEPUBReaderTintButton(type: .system) + private var authorizationButtonWidthConstraint: NSLayoutConstraint! private let titleLabel: UILabel = { let label = UILabel() label.textAlignment = .center @@ -20,23 +25,28 @@ public final class RDEPUBReaderTopToolView: RDEPUBReaderToolView, RDEPUBReaderTo }() private var isBookmarked = false - override init(frame: CGRect) { + public override init(frame: CGRect) { super.init(frame: frame) accessibilityIdentifier = "epub.reader.topToolbar" self.backgroundColor = .white addSubview(backButton) addSubview(searchButton) addSubview(bookmarkButton) + addSubview(authorizationButton) addSubview(titleLabel) backButton.translatesAutoresizingMaskIntoConstraints = false searchButton.translatesAutoresizingMaskIntoConstraints = false bookmarkButton.translatesAutoresizingMaskIntoConstraints = false + authorizationButton.translatesAutoresizingMaskIntoConstraints = false titleLabel.translatesAutoresizingMaskIntoConstraints = false backButton.addTarget(self, action: #selector(backAction), for: .touchUpInside) searchButton.addTarget(self, action: #selector(searchAction), for: .touchUpInside) bookmarkButton.addTarget(self, action: #selector(bookmarkAction), for: .touchUpInside) + authorizationButton.addTarget(self, action: #selector(authorizationAction), for: .touchUpInside) + + authorizationButtonWidthConstraint = authorizationButton.widthAnchor.constraint(equalToConstant: 0) NSLayoutConstraint.activate([ backButton.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 8), @@ -45,7 +55,13 @@ public final class RDEPUBReaderTopToolView: RDEPUBReaderToolView, RDEPUBReaderTo backButton.widthAnchor.constraint(equalToConstant: 44), backButton.heightAnchor.constraint(equalToConstant: 44), - bookmarkButton.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -8), + authorizationButton.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -8), + authorizationButton.topAnchor.constraint(equalTo: safeAreaLayoutGuide.topAnchor, constant: 4), + authorizationButton.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -4), + authorizationButton.heightAnchor.constraint(equalToConstant: 44), + authorizationButtonWidthConstraint, + + bookmarkButton.trailingAnchor.constraint(equalTo: authorizationButton.leadingAnchor, constant: -4), bookmarkButton.topAnchor.constraint(equalTo: safeAreaLayoutGuide.topAnchor, constant: 4), bookmarkButton.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -4), bookmarkButton.widthAnchor.constraint(equalToConstant: 44), @@ -72,11 +88,12 @@ public final class RDEPUBReaderTopToolView: RDEPUBReaderToolView, RDEPUBReaderTo backButton.accessibilityIdentifier = "epub.reader.back" searchButton.accessibilityIdentifier = "epub.reader.search" bookmarkButton.accessibilityIdentifier = "epub.reader.bookmark" + authorizationButton.accessibilityIdentifier = "epub.reader.authorization" titleLabel.accessibilityIdentifier = "epub.reader.title" updateBookmarkButtonAppearance() } - required init?(coder: NSCoder) { + public required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } @@ -90,10 +107,12 @@ public final class RDEPUBReaderTopToolView: RDEPUBReaderToolView, RDEPUBReaderTo backButton.tintColor = theme.toolControlTextColor searchButton.tintColor = theme.toolControlTextColor bookmarkButton.tintColor = theme.toolControlTextColor + authorizationButton.tintColor = theme.toolControlTextColor if #unavailable(iOS 13.0) { backButton.setTitleColor(theme.toolControlTextColor, for: .normal) searchButton.setTitleColor(theme.toolControlTextColor, for: .normal) bookmarkButton.setTitleColor(theme.toolControlTextColor, for: .normal) + authorizationButton.setTitleColor(theme.toolControlTextColor, for: .normal) } updateBookmarkButtonAppearance() } @@ -112,6 +131,17 @@ public final class RDEPUBReaderTopToolView: RDEPUBReaderToolView, RDEPUBReaderTo bookmarkButton.alpha = isEnabled ? 1 : 0.45 } + /// 设置右上角业务按钮。传 `nil` 或空字符串时隐藏按钮并恢复原工具栏布局。 + public func setAuthorizationButton(title: String?) { + let resolvedTitle = title?.trimmingCharacters(in: .whitespacesAndNewlines) + let isVisible = resolvedTitle?.isEmpty == false + authorizationButton.setTitle(resolvedTitle, for: .normal) + authorizationButton.isHidden = !isVisible + authorizationButton.isEnabled = isVisible + authorizationButtonWidthConstraint.constant = isVisible ? 56 : 0 + authorizationButton.accessibilityLabel = resolvedTitle + } + @objc private func backAction() { onBack?() } @@ -124,6 +154,10 @@ public final class RDEPUBReaderTopToolView: RDEPUBReaderToolView, RDEPUBReaderTo onToggleBookmark?() } + @objc private func authorizationAction() { + onAuthorization?() + } + private func updateBookmarkButtonAppearance() { if #available(iOS 13.0, *) { let imageName = isBookmarked ? "bookmark.fill" : "bookmark"