我有一个UITableView,其动态大小的原型单元格使用自动布局来适应其内容。在我的一个原型单元格中,我有一个UITextView,我已将其配置为动态更改其高度,并在TextViews高度达到阈值(6行文本)后变为可滚动。当低于阈值时,此过程也可以反向,缩小并变为不可滚动。
截至目前,当我选择UITextView输入文本时,TableView会向上滚动以便为键盘腾出空间,但最后一行文字被键盘部分隐藏。
我最初的想法是让TableView向上滚动,每次输入新的文本行,以便TextView的下边缘始终位于键盘顶部的正上方。
这样做的首选/正确方法是什么?我一直在阅读很多关于调整TextView大小和这些单词的矛盾(contentInset,scrollRectToVisible)
我找到了一个similar问题,说明了问题,但出现的答案是iOS 7中的错误。我正在使用iOS 10.3
TableView.swift
upper component
TextViewCell.swift
class NewRecipe: UITableViewController, UIPickerViewDataSource, UIPickerViewDelegate, UITextFieldDelegate, ExpandingCellDelegate {
@IBOutlet weak var uiTable: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
self.tableView.separatorStyle = .none
self.tableView.allowsSelection = false
}
func updateCellHeight(_ indexPath: IndexPath, comment: String) {
UIView.setAnimationsEnabled(false)
self.uiTable.beginUpdates()
self.uiTable.endUpdates()
UIView.setAnimationsEnabled(true)
}
// To enable self-sizing table view cells
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
//print("setting automatic dim 1")
//return UITableViewAutomaticDimension
if (indexPath.row == 4) {
//setting cell size for the image
let screenSize = UIScreen.main.bounds
let screenHeight = screenSize.height
return screenHeight/2
} else {
// set each row to be self sizing!
return UITableViewAutomaticDimension
}
}
// To enable self-sizing table view cells
override func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
//print("setting automatic dim 2")
return UITableViewAutomaticDimension
}
// determine number of rows
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
//print("returning number of rows = 7")
return 9
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
switch (indexPath.row) {
case 4:
let cell = tableView.dequeueReusableCell(withIdentifier: "Image Cell", for: indexPath) as! ImageTableViewCell
cell.foodImage.image = UIImage(named: "defaultPhoto")
return cell
case 0, 1, 2, 3:
let cell = tableView.dequeueReusableCell(withIdentifier: "Label-Text Field Split Cell", for: indexPath) as! LabelTextFieldSplitCell
if (indexPath.row == 1) {
cell.label.text = "Recipe Title "
} else if (indexPath.row == 2) {
cell.label.text = "Quantity / Servings "
} else if (indexPath.row == 3) {
cell.label.text = "Prep Time "
} else {
cell.label.text = "Cook Time "
}
return cell
case 5:
let cell = tableView.dequeueReusableCell(withIdentifier: "Stack-Label Split Cell", for: indexPath) as! StackLabelSplitCell
return cell
case 6:
let cell = tableView.dequeueReusableCell(withIdentifier: "Buttons Cell", for: indexPath) as! ButtonsCell
return cell
case 7:
let cell = tableView.dequeueReusableCell(withIdentifier: "Picker-Text View Split Cell", for: indexPath) as! PickerTextViewCell
cell.picker.delegate = self
cell.cellIndexPath = indexPath
cell.delegate = self as ExpandingCellDelegate
return cell
case 8:
let cell = tableView.dequeueReusableCell(withIdentifier: "Text View Cell", for: indexPath) as! TextViewCell
cell.cellIndexPath = indexPath
cell.delegate = self as ExpandingCellDelegate
return cell
default:
let cell = tableView.dequeueReusableCell(withIdentifier: "Single Text Field Cell", for: indexPath) as! SingleTextFieldCell
return cell
}
}
//MARK: UIPickerViewDelegate
// set number of columns
func numberOfComponents(in pickerView: UIPickerView) -> Int {
//print("measurement count is " , measurements.count)
return measurements.count
}
func pickerView(_ pickerView: UIPickerView, widthForComponent component: Int) -> CGFloat {
return 35.0
}
// set number of rows for each column
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return (measurements[component] as [AnyObject]).count + 1
}
func pickerView(_ pickerView: UIPickerView, viewForRow row: Int, forComponent component: Int, reusing view: UIView?) -> UIView {
// set the first item in picker to -- then set all other items to the strings in the array @ measurements[component][row-1]
let string = row == 0 ? "--" : "\((measurements[component] as [AnyObject])[row - 1])"
// styling the picker labels
let pickerLabel = UILabel()
pickerLabel.text = string
pickerLabel.textColor = UIColor.black
pickerLabel.font = UIFont(name: "Helvetica Neue", size: 17)
pickerLabel.textAlignment = .left
return pickerLabel
}
// retreiving the values out of the picker
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
/*
switch (component) {
case (0):
let wholeNum = row == 0 ? 0 : measurements[component][row-1] as? Int
case (1):
let fraction = row == 0 ? "" : measurements[component][row-1] as? String
case (2):
let unit = row == 0 ? "" : measurements[component][row-1] as? String
default: ()
}
*/
}
//MARK: UITextFieldDelegate
func textFieldDidBeginEditing(_ textField: UITextField) {
//This code disables the Save button while the user is editing the text field.
//saveButton.isEnabled = false
//self.view.bounds.origin.y = 60
}
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
// Hide the keyboard when the user presses Done.
textField.resignFirstResponder()
return true
}
func textFieldDidEndEditing(_ textField: UITextField) {
// The first line calls updateSaveButtonState() to check if the text field has text in it, which enables the Save button if it does. The second line sets the title of the scene in the nav bar to that text.
//updateSaveButtonState()
//navigationItem.title = textField.text
}
// func textViewDidBeginEditing(_ textView: UITextView)
// {
// if UIScreen.main.bounds.height < 568 {
// UIView.animate(withDuration: 0.75, animations: {
// self.view.bounds.origin.y = 60
// })
// }
// }
//
// func textViewDidEndEditing(_ textView: UITextView)
// {
// if UIScreen.main.bounds.height < 568 {
// UIView.animate(withDuration: 0.75, animations: {
// self.view.bounds.origin.y = 0
// })
// }
// }
}