问题描述
这是我目前得到的结果(不需要):https://vimeo.com/459984986。
这是我使用一种解决方法(几乎是我想要的)得到的结果:https://vimeo.com/459986233。
我的问题的摘要如下:(1)我已经安装了“ IQKeyboardManagerSwift” cocoapod,(2) >我的UITableViewController中有一个自定义单元格,它是FolingCell(另一个cocoapod),并且包含一个文本字段(3),当我在文本字段中点击时,我希望视图自动向上滚动以使可见的文本字段(在键盘上方),应由 IQKeyboardManager 自动处理(是的,我在AppDelegate中添加了“启用”代码)。
如上面的“ 不需要的”结果视频所示,该视图似乎试图滚动,但最终最终只是在上下方向抖动,然后才结束键盘向上滑动并意外覆盖文本字段时的原始位置。
此外,我发现我不想解决的小“ 解决方法”是将以下行添加到文本字段的IBAction editDidEnd出口/操作函数中:“ sender.becomeFirstResponder()”。在运行和测试我的应用程序的iPhone上更新到XCode 12和iOS 14之前,我不必麻烦使用“ .becomeFirstResponder()”或“ .resignResponder()”,因为这就是 IQKeyboardManager em>自动执行。现在,添加上述代码行允许UITableViewController将视图移动到键盘上方。 但是,如果您仔细观察,它将位于键盘上方的文本字段,这显然不是 IQKeyboardManager 完成的,因为 IQKeyboardManager 具有默认设置CGFloat(10)在文本字段和键盘之间的偏移量。
我认为代码的相关部分是我的自定义单元格(称为“ SavedImageFoldingImageCell”),因为这是我创建相关文本字段和 UITableViewController的地方(称为“ SavedImageTableViewController”)。
请提供您的任何帮助,建议和建议,将为我提供帮助,并倍受赞赏。谢谢!
是的,我的代码看上去很恐怖,因为我没有进行编码方面的最佳实践或一般编码方面的适当培训。建议也将不胜感激!如果您发现我可以缩短和组织代码的方式,则一定要泄露您的秘密!
import UIKit
import FoldingCell
import LGButton
import TextFieldEffects
import SCLAlertView
class SavedImageFoldingImageCell: FoldingCell,UITextFieldDelegate {
// CLOSED
@IBOutlet weak var enteraGreetingLabelClosed: UILabel!
@IBOutlet weak var savedImageView1Closed: UIImageView!
@IBOutlet weak var savedImageView2Closed: UIImageView!
@IBOutlet weak var openCellButton: LGButton!
// OPEN
@IBOutlet weak var confirmlabelOpen: UILabel!
@IBOutlet weak var englishLabelOpen: UILabel!
@IBOutlet weak var spanishLabelOpen: UILabel!
@IBOutlet weak var savedImageView1Open: UIImageView!
@IBOutlet weak var savedImageView2Open: UIImageView!
@IBOutlet weak var enteraGreetingLabelOpen: UILabel!
@IBOutlet weak var enteraGreetinTextFieldOpen: HoshiTextField!
@IBOutlet weak var barViewOpen: UIView!
// 'Continue' Button
@IBOutlet weak var continueButton: LGButton!
// Hamburger Button
@IBOutlet weak var hamburgerButton: UIButton!
// MARK: - Setting-up Labels
// CLOSED Labels
var enteraGreetingClosed: String = "" {
didSet {
enteraGreetingLabelClosed.text = String(enteraGreetingClosed)
}
}
// OPEN Labels
var englishOpen: String = "" {
didSet {
englishLabelOpen.text = String(englishOpen)
}
}
var spanishOpen: String = "" {
didSet {
spanishLabelOpen.text = String(spanishOpen)
}
}
var enteraGreetingOpen: String = "" {
didSet {
enteraGreetingLabelOpen.text = String(enteraGreetingOpen)
}
}
var confirmOpen: String = "" {
didSet {
confirmlabelOpen.text = String(confirmOpen)
}
}
override func awakeFromNib() {
barViewOpen.layer.maskedCorners = [.layerMaxXMinYCorner,.layerMinXMinYCorner] // Top right corner,Top left corner respectively
barViewOpen.clipsToBounds = true
foregroundView.layer.cornerRadius = 10
foregroundView.layer.masksToBounds = true
super.awakeFromNib()
// Initialization code
enteraGreetinTextFieldOpen.delegate = self
}
override func animationDuration(_ itemIndex: NSInteger,type: FoldingCell.AnimationType) -> TimeInterval {
let durations = [0.26,0.2,0.2]
return durations[itemIndex]
}
@IBAction func enteraGreetingTextFieldEditingDidBegin(_ sender: HoshiTextField) {
print("@enteraGreetingTextFieldEditingDidBegin -> cell.swift: does nothing as of Now.")
}
@IBAction func enteraGreetingTextFieldEditingDidEnd(_ sender: HoshiTextField) {
if sender.text!.isEmpty != true {
// Activates and shows the 'Continue' button
continueButton.isEnabled = true
continueButton.alpha = 1
print("enteraGreetingTextFieldEditingDidEnd@Cell -> cell.swift: activated 'Continue' button because textField contained text after editing ended.")
} else if sender.text!.isEmpty == true {
// Deactivates and hides the 'Continue' button
continueButton.isEnabled = false
continueButton.alpha = 0.5
print("enteraGreetingTextFieldEditingDidEnd@Cell: deactivated 'Continue' button because textField was empty after editing ended.")
}
}
// JUST FYI,THIS DOES NOT GET CALLED
private func textFieldShouldReturn(_ textField: HoshiTextField) -> Bool {
let storyboard = UIStoryboard.init(name: "Main",bundle: nil)
let savedImageTableVC = storyboard.instantiateViewController(withIdentifier: "SavedImageTableViewController") as! SavedImageTableViewController
savedImageTableVC.loadViewIfNeeded()
if textField.text?.isEmpty == false {
savedImageTableVC.liveGreeting = textField.text!
savedImageTableVC.savedImageTableView.reloadData()
print(".CELL @textFieldShouldReturn() -> savedImageTableVC.savedImagesArray: \(savedImageTableVC.savedImagesArray).")
let indexPathRow = textField.tag
StructOperation.globalVariable.tappedCellIndexRow = indexPathRow
print(".CELL @textFieldShouldReturn() -> StructOperation.globalVariable.tappedCellIndexRow: \(StructOperation.globalVariable.tappedCellIndexRow).")
savedImageTableVC.goToSend()
print("User entered a greeting in enteraGreetingTextField: \(savedImageTableVC.liveGreeting).")
} else if textField.text?.isEmpty == true {
savedImageTableVC.liveGreeting = ""
SCLAlertView().showError("Error",subTitle: "To send an image,a greeting must also be specified.",closeButtonTitle: "Done",timeout: nil,colorStyle: SCLAlertViewStyle.error.defaultColorInt,colorTextButton: 0xFFFFFF,circleIconImage: nil,animationStyle: .topToBottom)
print("User did not enter a greeting in enteraGreetingTextField.")
}
return true
}
}
// MARK: - Actions ⚡️
extension SavedImageFoldingImageCell {
@IBAction func openCellButtonTapped() {
// print("The open-cell button was tapped (just a downward arrow).")
}
@IBAction func enteraGreetingTextfieldOpenEditingDidEnd() {
// print("'enteraGreetingTextField' finished editing.")
}
@IBAction func continueButtonTapped(_: AnyObject) {
// print("The 'Continue' button was tapped.")
}
@IBAction func hamburgerButtonTapped(_: AnyObject) {
// print("The hamburger button was tapped.")
}
}
UITableViewController的代码:
import UIKit
import TextFieldEffects
import SCLAlertView
import MessageUI
import FoldingCell
import MLKitTranslate
class SavedImageTableViewController: UITableViewController,UIImagePickerControllerDelegate,UINavigationControllerDelegate,MFMessageComposeViewControllerDelegate,UITextFieldDelegate,UIContextMenuInteractionDelegate {
@IBOutlet var savedImageTableView: UITableView!
*** Omitted other irrelevant outlets,vars,& constants ***
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(true)
activityIndicator() // Omitted because nothing regarding the textfield is called here
refresh() // Omitted ""
}
override func viewDidLoad() {
super.viewDidLoad()
setup() // Omitted ""; (assigned self to tableview's delegate and dataSource here)
checkIfSavedImages() // Omitted ""
getDeadlineInSeconds() // Omitted ""
// For deadline countdown timer
countdownTimer = Timer.scheduledTimer(timeInterval: 1,target: self,selector: #selector(updateCounter),userInfo: nil,repeats: true)
// Stops loading spinner and hides view
self.indicator.stopAnimating()
self.indicator.hidesWhenStopped = true
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(true)
}
@IBAction func enteraGreetingTextFieldEditingDidEnd(_ sender: HoshiTextField) {
let cell = savedImageTableView.dequeueReusableCell(withIdentifier: "SavedImageFoldingImageCell") as! SavedImageFoldingImageCell
if sender.text?.isEmpty == true {
sender.text = ""
cell.continueButton.isEnabled = false
cell.continueButton.alpha = 0.5
// sender.resignFirstResponder()
} else if sender.text?.isEmpty == false {
self.liveGreeting = sender.text!
cell.continueButton.isEnabled = true
cell.continueButton.alpha = 1
}
}
@IBAction func enteraGreetingTextFieldEditingDidBegin(_ sender: HoshiTextField) {
sender.becomeFirstResponder() // Fixes IQKeyboardManager (rather,allows UITableViewController to properly scroll)
let indexPathRow = sender.tag
StructOperation.globalVariable.tappedCellIndexRow = indexPathRow
print("enteraGreetingTextFieldEditingDidEnd()@ViewController -> StructOperation.globalVariable.tappedCellIndexRow: \(StructOperation.globalVariable.tappedCellIndexRow).")
}
//MARK: - TableView Functions
override func tableView(_ tableView: UITableView,willdisplay cell: UITableViewCell,forRowAt indexPath: IndexPath) {
guard case let cell as SavedImageFoldingImageCell = cell else {
return
}
cell.enteraGreetingClosed = "Enter a Greeting"
cell.enteraGreetingOpen = "Enter a Greeting"
cell.englishOpen = "English"
cell.spanishOpen = "Spanish"
cell.confirmOpen = "Confirm"
// Greeting TextField
cell.enteraGreetinTextFieldOpen.delegate = self
cell.enteraGreetinTextFieldOpen.tag = indexPath.row
// Open-cell button (downward arrow)
cell.openCellButton.tag = indexPath.row
// 'Continue' button
cell.continueButton.tag = indexPath.row
cell.continueButton.isEnabled = false
cell.continueButton.alpha = 0.5
// Hamburger button
cell.hamburgerButton.tag = indexPath.row
// Closed/Open Images (English,Spanish)
let calculatedindex = (indexPath.row * 2) + 1
cell.savedImageView1Closed.image = savedImagesArray[calculatedindex - 1]
cell.savedImageView2Closed.image = savedImagesArray[calculatedindex]
cell.savedImageView1Open.image = savedImagesArray[calculatedindex - 1]
cell.savedImageView2Open.image = savedImagesArray[calculatedindex]
cell.backgroundColor = .clear
if cellHeights[indexPath.row] == Constants.closeCellHeight {
cell.unfold(false,animated: false,completion: nil)
} else {
cell.unfold(true,completion: nil)
}
// Allows recognition of tapping the 'Continue' button by connecting that button's outlet to a newly created function down below a little
cell.continueButton.addTarget(self,action: #selector(SavedImageTableViewController.continueButtonTapped(_:)),for: .touchUpInside)
// Allows recognition of tapping the 'open cell' button (just a downward arrow) by connecting that button's outlet to a newly created function down below a little
cell.openCellButton.addTarget(self,action: #selector(openCellButtonTapped(_:)),for: .touchUpInside)
// Allows recognition of tapping the 'hamburger' button (just three horizontal lines as a button) by connecting that button's outlet to a newly created function down below a little
cell.hamburgerButton.addTarget(self,action: #selector(hamburgerButtonTapped(_:)),for: .touchUpInside)
}
override func tableView(_ tableView: UITableView,cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = savedImageTableView.dequeueReusableCell(withIdentifier: "SavedImageFoldingImageCell",for: indexPath) as! FoldingCell
let durations: [TimeInterval] = [0.26,0.2]
cell.durationsForExpandedState = durations
cell.durationsForCollapsedState = durations
return cell
}
override func tableView(_ tableView: UITableView,didSelectRowAt indexPath: IndexPath) {
guard case let cell as FoldingCell = tableView.cellForRow(at: indexPath) else {
return
}
if cell.isAnimating() {
return
}
var duration = 0.0
let cellIsCollapsed = cellHeights[indexPath.row] == Constants.closeCellHeight
if cellIsCollapsed {
cellHeights[indexPath.row] = Constants.openCellHeight
cell.unfold(true,animated: true,completion: nil)
duration = 0.5
} else {
cellHeights[indexPath.row] = Constants.closeCellHeight
cell.unfold(false,completion: nil)
duration = 0.8
}
UIView.animate(withDuration: duration,delay: 0,options: .curveEaSEOut,animations: {
tableView.beginUpdates()
tableView.endUpdates()
// fix https://github.com/Ramotion/folding-cell/issues/169
if cell.frame.maxY > tableView.frame.maxY {
tableView.scrollToRow(at: indexPath,at: UITableView.ScrollPosition.bottom,animated: true)
}
},completion: nil)
// Provide haptic Feedback of success
let generator = UINotificationFeedbackGenerator()
generator.notificationOccurred(.success)
}
***Rest is Omitted because I think its irrelevant to the problem***
解决方法
我通过简单地从 UITableViewController-> UIViewController 切换类来解决了自己的问题。我在 IQKeyboardManager的 Github页面上浏览了已解决的问题,发现由于Apple的UITableViewController自动处理视图和键盘的移动,因此 IQKeyboardManager的开发人员选择忽略文本字段。在UITableViewController中。因此,必须将类更改为UIViewController或其他受支持的类,以使文本字段被 IQKeyboardManager 识别。