import UIKit // MARK: - 顶部工具栏 /// 阅读器顶部工具栏 /// 显示书名、返回按钮和书签按钮 /// 位于阅读内容上方,支持 iOS 13+ SF Symbols 和低版本文字回退 public final class RDEPUBReaderTopToolView: RDEPUBReaderToolView { /// 返回按钮点击回调 var onBack: (() -> Void)? /// 书签按钮点击回调 var onToggleBookmark: (() -> Void)? /// 搜索按钮点击回调 var onSearch: (() -> Void)? private let backButton = RDEPUBReaderTintButton(type: .system) private let searchButton = RDEPUBReaderTintButton(type: .system) private let bookmarkButton = RDEPUBReaderTintButton(type: .system) private let titleLabel: UILabel = { let label = UILabel() label.textAlignment = .center label.font = UIFont.systemFont(ofSize: 16, weight: .semibold) label.numberOfLines = 1 return label }() private var isBookmarked = false override init(frame: CGRect) { super.init(frame: frame) accessibilityIdentifier = "epub.reader.topToolbar" self.backgroundColor = .white addSubview(backButton) addSubview(searchButton) addSubview(bookmarkButton) addSubview(titleLabel) backButton.translatesAutoresizingMaskIntoConstraints = false searchButton.translatesAutoresizingMaskIntoConstraints = false bookmarkButton.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) NSLayoutConstraint.activate([ backButton.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 8), backButton.topAnchor.constraint(equalTo: safeAreaLayoutGuide.topAnchor, constant: 4), backButton.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -4), backButton.widthAnchor.constraint(equalToConstant: 44), backButton.heightAnchor.constraint(equalToConstant: 44), bookmarkButton.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -8), bookmarkButton.topAnchor.constraint(equalTo: safeAreaLayoutGuide.topAnchor, constant: 4), bookmarkButton.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -4), bookmarkButton.widthAnchor.constraint(equalToConstant: 44), bookmarkButton.heightAnchor.constraint(equalToConstant: 44), searchButton.trailingAnchor.constraint(equalTo: bookmarkButton.leadingAnchor, constant: -4), searchButton.topAnchor.constraint(equalTo: safeAreaLayoutGuide.topAnchor, constant: 4), searchButton.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -4), searchButton.widthAnchor.constraint(equalToConstant: 44), searchButton.heightAnchor.constraint(equalToConstant: 44), titleLabel.leadingAnchor.constraint(equalTo: backButton.trailingAnchor, constant: 8), titleLabel.trailingAnchor.constraint(equalTo: searchButton.leadingAnchor, constant: -8), titleLabel.centerYAnchor.constraint(equalTo: backButton.centerYAnchor) ]) if #available(iOS 13.0, *) { backButton.setImage(UIImage(systemName: "chevron.left")?.withRenderingMode(.alwaysTemplate), for: .normal) searchButton.setImage(UIImage(systemName: "magnifyingglass")?.withRenderingMode(.alwaysTemplate), for: .normal) } else { backButton.setTitle("返回", for: .normal) searchButton.setTitle("搜索", for: .normal) } backButton.accessibilityIdentifier = "epub.reader.back" searchButton.accessibilityIdentifier = "epub.reader.search" bookmarkButton.accessibilityIdentifier = "epub.reader.bookmark" titleLabel.accessibilityIdentifier = "epub.reader.title" updateBookmarkButtonAppearance() } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } override public func lineFrame(in bounds: CGRect) -> CGRect { CGRect(x: 0, y: bounds.height - 0.5, width: bounds.width, height: 0.5) } override public func apply(theme: RDEPUBReaderTheme) { super.apply(theme: theme) titleLabel.textColor = theme.toolControlTextColor backButton.tintColor = theme.toolControlTextColor searchButton.tintColor = theme.toolControlTextColor bookmarkButton.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) } updateBookmarkButtonAppearance() } func setTitle(_ title: String?) { titleLabel.text = title } func setBookmarkSelected(_ isSelected: Bool) { isBookmarked = isSelected updateBookmarkButtonAppearance() } func setBookmarkEnabled(_ isEnabled: Bool) { bookmarkButton.isEnabled = isEnabled bookmarkButton.alpha = isEnabled ? 1 : 0.45 } @objc private func backAction() { onBack?() } @objc private func searchAction() { onSearch?() } @objc private func bookmarkAction() { onToggleBookmark?() } private func updateBookmarkButtonAppearance() { if #available(iOS 13.0, *) { let imageName = isBookmarked ? "bookmark.fill" : "bookmark" bookmarkButton.setImage(UIImage(systemName: imageName)?.withRenderingMode(.alwaysTemplate), for: .normal) } else { bookmarkButton.setTitle(isBookmarked ? "已签" : "书签", for: .normal) } } }