我正在尝试创建一个在键盘出现时向上滑动的视图,并且在此视图中是一个文本字段,用作搜索栏和集合视图以保存搜索结果。视图在键盘上方滑动得很好,但是一旦我点击其中一个单元格进行曲面滚动,视图就会消失。可能导致这种情况的原因。
我认为可能导致问题的代码
var offsetY:CGFloat = 0
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
NotificationCenter.default.addObserver(self, selector: #selector(ViewController.keyboardFrameChangeNotification(notification:)), name: NSNotification.Name.UIKeyboardWillChangeFrame, object: nil)
}
@objc func keyboardFrameChangeNotification(notification: Notification) {
if let userInfo = notification.userInfo {
let endFrame = userInfo[UIKeyboardFrameEndUserInfoKey] as? CGRect
let animationDuration = userInfo[UIKeyboardAnimationDurationUserInfoKey] as? Double ?? 0
let animationCurveRawValue = (userInfo[UIKeyboardAnimationCurveUserInfoKey] as? Int) ?? Int(UIViewAnimationOptions.curveEaseInOut.rawValue)
let animationCurve = UIViewAnimationOptions(rawValue: Int(animationCurveRawValue))
if let _ = endFrame, endFrame!.intersects(self.myView.frame) {
self.offsetY = self.myView.frame.maxY - endFrame!.minY
UIView.animate(withDuration: animationDuration, delay: TimeInterval(0), options: animationCurve, animations: {
self.myView.frame.origin.y = self.myView.frame.origin.y - self.offsetY
}, completion: nil)
} else {
if self.offsetY != 0 {
UIView.animate(withDuration: animationDuration, delay: TimeInterval(0), options: animationCurve, animations: {
self.myView.frame.origin.y = self.myView.frame.origin.y + self.offsetY
self.offsetY = 0
}, completion: nil)
}
}
}
}
完整的代码
import UIKit
class SearchCollectionViewController: UIViewController,UICollectionViewDelegate,UICollectionViewDelegateFlowLayout, UITextFieldDelegate, UICollectionViewDataSource {
@IBOutlet weak var searchBar: UITextField!
@IBOutlet weak var collectionView: UICollectionView!
@IBOutlet weak var myView: UIView!
var genericArray:[String] = ["A","B","C","D","E","F","G","Ab","Abc"]
var currentGenericArray:[String] = [String]()
override func viewDidLoad() {
super.viewDidLoad()
collectionView.delegate = self
collectionView.dataSource = self
let layout: UICollectionViewFlowLayout = UICollectionViewFlowLayout()
layout.sectionInset = UIEdgeInsets(top: 0, left: 0, bottom: 10, right: 0)
layout.itemSize = CGSize(width: (UIScreen.main.bounds.width-1)/2, height: (UIScreen.main.bounds.width-1)/2)
layout.minimumInteritemSpacing = 1
layout.minimumLineSpacing = 1
layout.scrollDirection = .horizontal
self.collectionView.collectionViewLayout = layout
searchBar.delegate = self
currentGenericArray = genericArray
searchBar.addTarget(self, action: #selector(TableSearchViewController.textFieldDidChange), for: .editingChanged)
}
@objc func textFieldDidChange(){
guard(!(searchBar.text?.isEmpty)!) else{
currentGenericArray = genericArray
collectionView.reloadData()
return
}
currentGenericArray = genericArray.filter({letter -> Bool in
letter.lowercased().contains(searchBar.text!)
})
collectionView.reloadData()
}
func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return currentGenericArray.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "collectionViewCell", for: indexPath) as! CollectionCell
cell.collectionLabel.text = currentGenericArray[indexPath.row]
return cell
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
return 0
}
var offsetY:CGFloat = 0
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
NotificationCenter.default.addObserver(self, selector: #selector(ViewController.keyboardFrameChangeNotification(notification:)), name: NSNotification.Name.UIKeyboardWillChangeFrame, object: nil)
}
@objc func keyboardFrameChangeNotification(notification: Notification) {
if let userInfo = notification.userInfo {
let endFrame = userInfo[UIKeyboardFrameEndUserInfoKey] as? CGRect
let animationDuration = userInfo[UIKeyboardAnimationDurationUserInfoKey] as? Double ?? 0
let animationCurveRawValue = (userInfo[UIKeyboardAnimationCurveUserInfoKey] as? Int) ?? Int(UIViewAnimationOptions.curveEaseInOut.rawValue)
let animationCurve = UIViewAnimationOptions(rawValue: UInt(animationCurveRawValue))
if let _ = endFrame, endFrame!.intersects(self.myView.frame) {
self.offsetY = self.myView.frame.maxY - endFrame!.minY
UIView.animate(withDuration: animationDuration, delay: TimeInterval(0), options: animationCurve, animations: {
self.myView.frame.origin.y = self.myView.frame.origin.y - self.offsetY
}, completion: nil)
} else {
if self.offsetY != 0 {
UIView.animate(withDuration: animationDuration, delay: TimeInterval(0), options: animationCurve, animations: {
self.myView.frame.origin.y = self.myView.frame.origin.y + self.offsetY
self.offsetY = 0
}, completion: nil)
}
}
}
}
}
class CollectionCell:UICollectionViewCell{
@IBOutlet weak var collectionLabel: UILabel!
override func awakeFromNib() {
collectionLabel.textAlignment = .center
}
}
答案 0 :(得分:1)
您的代码有点混乱,但我没有看到textField
除didChange
之外的searchBar
函数。尝试添加shouldReturn
和didEndEditing
,以及更新滑块。这是我要做的一个例子。试一试,看看它是否有所作为。
生命周期
let keyboardSlider = KeyboardSlider()
override func viewDidLoad() {
super.viewDidLoad()
keyboardSlider.subscribeToKeyboardNotifications(view: view)
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
keyboardSlider.unsubscribeFromKeyboardNotifications()
}
的TextField
// MARK: TextFieldDelegate
func textFieldDidBeginEditing(_ textField: UITextField) {
// Add Done button for Keyboard Dismissal
let toolBar = UIToolbar()
toolBar.sizeToFit()
toolBar.barStyle = .default
let doneButton = UIBarButtonItem(barButtonSystemItem: .done, target: self, action: #selector(self.didStopEditing))
let space = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: self, action: nil)
toolBar.setItems([space, doneButton], animated: false)
textField.inputAccessoryView = toolBar
}
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
textField.resignFirstResponder()
return true
}
/// Helper to dismiss keyboard
@objc func didStopEditing() {
textFieldShouldReturn(phoneNumberTextField)
}
func textFieldDidEndEditing(_ textField: UITextField) {
UIView.setAnimationCurve(UIViewAnimationCurve.easeInOut)
UIView.animate(withDuration: 0.2) {
self.view.frame.origin.y = 0
}
}
键盘滑块
class KeyboardSlider: NSObject {
// variables to hold and process information from the view using this class
weak var view: UIView?
@objc func keyboardWillShow(notification: NSNotification) {
// method to move keyboard up
view?.frame.origin.y = 0 - getKeyboardHeight(notification as Notification)
}
func getKeyboardHeight(_ notification:Notification) -> CGFloat {
// get exact height of keyboard on all devices and convert to float value to return for use
let userInfo = notification.userInfo
let keyboardSize = userInfo![UIKeyboardFrameEndUserInfoKey] as! NSValue
return keyboardSize.cgRectValue.height
}
func subscribeToKeyboardNotifications(view: UIView) {
// assigning view to class' counterpart
self.view = view
// when UIKeyboardWillShow do keyboardWillShow function
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow(notification:)), name: .UIKeyboardWillShow, object: nil)
}
func unsubscribeFromKeyboardNotifications() {
NotificationCenter.default.removeObserver(self, name: .UIKeyboardWillShow, object: nil)
}
}
这个答案主要是清理你的代码
我觉得您的问题出现在键盘解雇的didChange
方法中。清理代码并单步执行断点将有助于找到问题所在。