Fixes bugs in article search
Placement of the article search bar is now always done with constraints. Previously, I'd used inputAccessoryView when the keyboard appeared. That approach, although ostensibly permitted, causes a hierarchy inconsistency error when the device orientation changes.
This commit is contained in:
parent
62d04e8881
commit
b058f27064
|
@ -73,13 +73,15 @@ import UIKit
|
|||
}
|
||||
|
||||
@discardableResult override func becomeFirstResponder() -> Bool {
|
||||
super.becomeFirstResponder()
|
||||
return searchField.becomeFirstResponder()
|
||||
searchField.becomeFirstResponder()
|
||||
}
|
||||
|
||||
@discardableResult override func resignFirstResponder() -> Bool {
|
||||
super.resignFirstResponder()
|
||||
return searchField.resignFirstResponder()
|
||||
searchField.resignFirstResponder()
|
||||
}
|
||||
|
||||
override var isFirstResponder: Bool {
|
||||
searchField.isFirstResponder
|
||||
}
|
||||
|
||||
deinit {
|
||||
|
|
|
@ -27,6 +27,7 @@ class ArticleViewController: UIViewController {
|
|||
@IBOutlet private weak var actionBarButtonItem: UIBarButtonItem!
|
||||
|
||||
@IBOutlet private var searchBar: ArticleSearchBar!
|
||||
@IBOutlet private var searchBarBottomConstraint: NSLayoutConstraint!
|
||||
private var defaultControls: [UIBarButtonItem]?
|
||||
|
||||
private var pageViewController: UIPageViewController!
|
||||
|
@ -70,6 +71,10 @@ class ArticleViewController: UIViewController {
|
|||
|
||||
private let keyboardManager = KeyboardManager(type: .detail)
|
||||
override var keyCommands: [UIKeyCommand]? {
|
||||
if searchBar.isFirstResponder {
|
||||
return nil
|
||||
}
|
||||
|
||||
return keyboardManager.keyCommands
|
||||
}
|
||||
|
||||
|
@ -132,14 +137,11 @@ class ArticleViewController: UIViewController {
|
|||
}
|
||||
|
||||
// Search bar
|
||||
makeSearchBarConstraints()
|
||||
searchBar.translatesAutoresizingMaskIntoConstraints = false
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(beginFind(_:)), name: .FindInArticle, object: nil)
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(endFind(_:)), name: .EndFindInArticle, object: nil)
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide(_:)), name: UIWindow.keyboardWillHideNotification, object: nil)
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(keyboardDidChangeFrame(_:)), name: UIWindow.keyboardDidChangeFrameNotification, object: nil)
|
||||
|
||||
// searchBar.translatesAutoresizingMaskIntoConstraints = false
|
||||
// searchBar.delegate = self
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillChangeFrame(_:)), name: UIWindow.keyboardWillChangeFrameNotification, object: nil)
|
||||
searchBar.delegate = self
|
||||
view.bringSubviewToFront(searchBar)
|
||||
|
||||
updateUI()
|
||||
|
@ -151,7 +153,9 @@ class ArticleViewController: UIViewController {
|
|||
}
|
||||
|
||||
override func viewWillDisappear(_ animated: Bool) {
|
||||
searchBar.inputAccessoryView = nil
|
||||
if searchBar != nil && !searchBar.isHidden {
|
||||
endFind()
|
||||
}
|
||||
}
|
||||
|
||||
override func viewSafeAreaInsetsDidChange() {
|
||||
|
@ -335,24 +339,14 @@ extension ArticleViewController: SearchBarDelegate {
|
|||
|
||||
extension ArticleViewController {
|
||||
|
||||
private func makeSearchBarConstraints() {
|
||||
NSLayoutConstraint.activate([
|
||||
searchBar.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor),
|
||||
searchBar.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor),
|
||||
searchBar.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor),
|
||||
])
|
||||
}
|
||||
|
||||
@objc func beginFind(_ _: Any? = nil) {
|
||||
searchBar.isHidden = false
|
||||
navigationController?.setToolbarHidden(true, animated: true)
|
||||
currentWebViewController?.additionalSafeAreaInsets.bottom = searchBar.frame.height
|
||||
searchBar.delegate = self
|
||||
searchBar.inputAccessoryView = searchBar
|
||||
searchBar.becomeFirstResponder()
|
||||
}
|
||||
|
||||
@objc func endFind(_ notification: Notification) {
|
||||
@objc func endFind(_ _: Any? = nil) {
|
||||
searchBar.resignFirstResponder()
|
||||
searchBar.isHidden = true
|
||||
navigationController?.setToolbarHidden(false, animated: true)
|
||||
|
@ -360,18 +354,25 @@ extension ArticleViewController {
|
|||
currentWebViewController?.endSearch()
|
||||
}
|
||||
|
||||
@objc func keyboardWillHide(_ _: Notification) {
|
||||
view.addSubview(searchBar)
|
||||
makeSearchBarConstraints()
|
||||
}
|
||||
|
||||
@objc func keyboardDidChangeFrame(_ notification: Notification) {
|
||||
if let frame = notification.userInfo?[UIWindow.keyboardFrameEndUserInfoKey] as? CGRect {
|
||||
currentWebViewController?.additionalSafeAreaInsets.bottom = frame.height
|
||||
@objc func keyboardWillChangeFrame(_ notification: Notification) {
|
||||
if !searchBar.isHidden,
|
||||
let duration = notification.userInfo?[UIWindow.keyboardAnimationDurationUserInfoKey] as? Double,
|
||||
let curveRaw = notification.userInfo?[UIWindow.keyboardAnimationCurveUserInfoKey] as? UInt,
|
||||
let frame = notification.userInfo?[UIWindow.keyboardFrameEndUserInfoKey] as? CGRect {
|
||||
|
||||
let curve = UIView.AnimationOptions(rawValue: curveRaw)
|
||||
let newHeight = view.safeAreaLayoutGuide.layoutFrame.maxY - frame.minY
|
||||
currentWebViewController?.additionalSafeAreaInsets.bottom = newHeight + searchBar.frame.height + 10
|
||||
self.searchBarBottomConstraint.constant = newHeight
|
||||
UIView.animate(withDuration: duration, delay: 0, options: curve, animations: {
|
||||
self.view.layoutIfNeeded()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
// MARK: WebViewControllerDelegate
|
||||
|
||||
extension ArticleViewController: WebViewControllerDelegate {
|
||||
|
|
|
@ -16,19 +16,16 @@
|
|||
<rect key="frame" x="0.0" y="0.0" width="414" height="896"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<view hidden="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="h1Q-FS-jlg" customClass="ArticleSearchBar" customModule="NetNewsWire" customModuleProvider="target">
|
||||
<rect key="frame" x="0.0" y="759" width="414" height="54"/>
|
||||
<view hidden="YES" contentMode="scaleToFill" ambiguous="YES" translatesAutoresizingMaskIntoConstraints="NO" id="h1Q-FS-jlg" customClass="ArticleSearchBar" customModule="NetNewsWire" customModuleProvider="target">
|
||||
<rect key="frame" x="0.0" y="777" width="414" height="36"/>
|
||||
<color key="backgroundColor" name="barBackgroundColor"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="54" id="FQw-KK-lT7"/>
|
||||
</constraints>
|
||||
</view>
|
||||
</subviews>
|
||||
<color key="backgroundColor" systemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
|
||||
<constraints>
|
||||
<constraint firstItem="h1Q-FS-jlg" firstAttribute="leading" secondItem="VUw-jc-0yf" secondAttribute="leading" id="2DV-em-ArG"/>
|
||||
<constraint firstItem="VUw-jc-0yf" firstAttribute="trailing" secondItem="h1Q-FS-jlg" secondAttribute="trailing" id="5aF-IN-1ff"/>
|
||||
<constraint firstItem="VUw-jc-0yf" firstAttribute="bottom" secondItem="h1Q-FS-jlg" secondAttribute="bottom" id="Kmv-Hg-0wL"/>
|
||||
<constraint firstItem="VUw-jc-0yf" firstAttribute="trailing" secondItem="h1Q-FS-jlg" secondAttribute="trailing" id="2Nt-fa-LhC"/>
|
||||
<constraint firstItem="h1Q-FS-jlg" firstAttribute="leading" secondItem="VUw-jc-0yf" secondAttribute="leading" id="Vgz-hA-Zrp"/>
|
||||
<constraint firstItem="VUw-jc-0yf" firstAttribute="bottom" secondItem="h1Q-FS-jlg" secondAttribute="bottom" id="XyH-A7-Trj"/>
|
||||
</constraints>
|
||||
<viewLayoutGuide key="safeArea" id="VUw-jc-0yf"/>
|
||||
</view>
|
||||
|
@ -103,6 +100,7 @@
|
|||
<outlet property="prevArticleBarButtonItem" destination="v4j-fq-23N" id="Gny-Oh-cQa"/>
|
||||
<outlet property="readBarButtonItem" destination="hy0-LS-MzE" id="BzM-x9-tuj"/>
|
||||
<outlet property="searchBar" destination="h1Q-FS-jlg" id="IQA-Wt-BB8"/>
|
||||
<outlet property="searchBarBottomConstraint" destination="XyH-A7-Trj" id="5gH-az-8vg"/>
|
||||
<outlet property="starBarButtonItem" destination="wU4-eH-wC9" id="Z8Q-Lt-dKk"/>
|
||||
</connections>
|
||||
</viewController>
|
||||
|
|
|
@ -349,15 +349,15 @@ function scrollParent(node) {
|
|||
elt = elt.parentElement;
|
||||
}
|
||||
}
|
||||
|
||||
function scrollToRect({top, height}, node, pad=0) {
|
||||
|
||||
function scrollToRect({top, height}, node, pad=20, padBottom=60) {
|
||||
const scrollToTop = top - pad;
|
||||
|
||||
let scrollBy = scrollToTop;
|
||||
|
||||
if (scrollToTop >= 0) {
|
||||
const visible = window.visualViewport;
|
||||
const scrollToBottom = top + height + pad - visible.height;
|
||||
const scrollToBottom = top + height + padBottom - visible.height;
|
||||
// The top of the rect is already in the viewport
|
||||
if (scrollToBottom <= 0 || scrollToTop === 0)
|
||||
// Don't need to scroll up--or can't
|
||||
|
|
Loading…
Reference in New Issue