問題:
我正在嘗試創建自己的自定義搜索欄位,其中包含所需的增長影片(如果單擊它),以及用戶點擊時的縮小影片。
影片的行為很奇怪,因為它在收縮時會移出右側螢屏邊界,即使文本欄位/搜索欄的右側錨點沒有被修改。
像這樣:

請注意搜索欄的右側在影片期間是如何短暫移動到可見螢屏邊界之外的。
預期行為:
搜索欄應該平滑地增長/收縮,而不移動文本欄位的右邊緣位置,即右錨點保持固定。
您在上面的 gif 中看到的內容是使用以下代碼構建的(通過子類化 a UITextField):
public class MySearchBar: UITextField {
private var preAnimationWidth: NSLayoutConstraint?
private var postAnimationWidth: NSLayoutConstraint?
public override init(frame: CGRect) {
super.init(frame: frame)
self.backgroundColor = Theme.GRAY800
self.borderStyle = .roundedRect
self.layer.masksToBounds = true
self.clipsToBounds = true
self.autocorrectionType = .no
self.font = FontFamily.ProximaNova.regular.font(size: 16)
self.textColor = .white
self.attributedPlaceholder = NSAttributedString(string: "Search", attributes: [.foregroundColor : Theme.GRAY400, .font: FontFamily.ProximaNova.regular.font(size: 16)])
// some further appearance configurations
}
public func setupGrowAnimation(initialWidth: NSLayoutConstraint, grownWidth: NSLayoutConstraint, height: CGFloat) {
preAnimationWidth = initialWidth
postAnimationWidth = grownWidth
self.layer.borderWidth = 0
self.layer.cornerRadius = height / 2
}
// growButton is called when the textfield becomes active, i.e. the user taps on it.
public func growButton() {
guard let preAnimationWidth = preAnimationWidth, let postAnimationWidth = postAnimationWidth else { return }
UIView.animate(withDuration: 0.2) {
preAnimationWidth.isActive = false
postAnimationWidth.isActive = true
self.layer.borderColor = Theme.GRAY600.cgColor
self.layer.borderWidth = 2
self.layer.cornerRadius = 8
self.layoutIfNeeded()
}
}
// shrinkButton is called whenever the textfield resigns its first responder state, i.e. the user clicks out of it.
public func shrinkButton() {
guard let preAnimationWidth = preAnimationWidth, let postAnimationWidth = postAnimationWidth else { return }
UIView.animate(withDuration: 0.2) {
postAnimationWidth.isActive = false
preAnimationWidth.isActive = true
self.layer.borderWidth = 0
self.layer.borderColor = .none
self.layer.cornerRadius = self.frame.height / 2
self.layoutIfNeeded()
}
}
}
這就是我的搜索欄的初始化方式viewDidLoad:
override func viewDidLoad() {
let containerView = UIView()
let searchBar = MySearchBar()
searchBar.addTarget(self, action: #selector(searchBarChangedEntry(_:)), for: .editingChanged)
searchBar.addTarget(self, action: #selector(searchBarEndedEditing(_:)), for: .editingDidEnd)
searchBar.translatesAutoresizingMaskIntoConstraints = false
let initialWidth = searchBar.widthAnchor.constraint(equalToConstant: 100)
let expandedWidth = searchBar.widthAnchor.constraint(equalTo: containerView.widthAnchor, constant: -32)
searchBar.setupGrowAnimation(initialWidth: initialWidth, grownWidth: expandedWidth, height: 44)
containerView.addSubview(searchBar)
stackView.insertArrangedSubview(containerView, at: 0)
NSLayoutConstraint.activate([
containerView.heightAnchor.constraint(equalToConstant: 44),
containerView.widthAnchor.constraint(equalTo: self.stackView.widthAnchor),
searchBar.heightAnchor.constraint(equalTo: containerView.heightAnchor),
initialWidth,
searchBar.rightAnchor.constraint(equalTo: containerView.rightAnchor, constant: -16)
])
self.stackView.setCustomSpacing(12, after: containerView)
}
safeAreaLayout搜索欄是容器視圖的一部分,容器視圖又是覆寫整個螢屏矩形的堆疊視圖的第一個(頂部)排列子視圖
我已經嘗試過的:
我必須使用約束來執行影片,并且我嘗試在不使用寬??度錨的情況下對其進行影片處理(例如,通過影片 leftAnchor 的常量)。到目前為止沒有任何效果。
谷歌搜索后,我真的找不到任何有用的東西來幫助我找到解決這個問題的方法,這就是我在這里碰運氣的原因。
我不得不承認我根本不精通 iOS 的影片——所以如果這是一個需要解決的簡單錯誤,請多多包涵。
那么,為什么搜索欄會這樣呢?我該如何解決這個問題?
uj5u.com熱心網友回復:
有點難說,因為您發布的代碼缺少很多資訊(例如,您沒有顯示 的??創建stackView,也沒有顯示它被添加到視圖層次結構的位置)。
但是,您可以通過這個簡單的更改來解決您的問題...
在 yourgrowButton()和shrinkButton()funcs 中,更改影片塊中的這一行:
self.layoutIfNeeded()
對此:
self.superview?.layoutIfNeeded()
編輯-一點解釋......
為了影片約束更改,我們想要呼叫將受到影響.layoutIfNeeded()的最頂層視圖。
呼叫時:
UIView.animate(withDuration: 0.5) {
self.someView.layoutIfNeeded()
}
我們告訴自動布局計算變化,然后生成并運行影片......但僅限于someView及其子視圖。
如果我們的操作將影響someView.superview- 或者,例如,約束更改將移動/調整 的同級或someView的同級someView.superview,我們還沒有告訴自動布局將這些視圖包含在其布局計算中。
我希望有特定的實作/布局層次結構,人們希望從布局/影片中專門排除一些視圖......但是......
就個人而言,我這樣做:
UIView.animate(withDuration: 0.5) {
self.view.layoutIfNeeded()
}
因為我想要影片的約束可能在視圖層次結構深處的子視圖上 - 并且可能有 4 或 5 或 6 個等超級視圖 - 所有這些都可能受到更改的影響。
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/521065.html
