I have Text views inside a static table. I want them to resize when there is need for a line break. How do i do this? This is my code so far.
override func viewDidLoad() {
super.viewDidLoad()
table.estimatedRowHeight = 40.0 // Replace with your actual estimation
table.rowHeight = UITableViewAutomaticDimension
// Tap to dismiss keyboard
let tap: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(EditInfoViewController.dismissKeyboard))
view.addGestureRecognizer(tap)
}
func dismissKeyboard() {
view.endEditing(true)
// Save data
}
func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return UITableViewAutomaticDimension
}
override func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableViewAutomaticDimension
}
Swift 3 & Xcode 8.3.2
Use UILabel instead of UITextView, and set numberOfLine = 0, so it will automatic resize according to its content
or
if you want to keep UITextView instead UILabel, here is the code
class YourClass: UITableViewController, UITextViewDelegate {
var yourCustomCell: UITableViewCell = UITableViewCell()
override func viewDidLoad() {
super.viewDidLoad()
table.estimatedRowHeight = 40.0 // Replace with your actual estimation
table.rowHeight = UITableViewAutomaticDimension
// Tap to dismiss keyboard
let tap: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(EditInfoViewController.dismissKeyboard))
view.addGestureRecognizer(tap)
// Add tableView delegate
tableView.dataSource = self
tableView.delegate = self
// Add textView delegate
yourTextView.delegate = self
}
// Text view delegate, dont forget to add yourTextView.delegate = self in viewDidLoad
func textViewDidChange(_ textView: UITextView) {
if textView == yourTextView {
let newHeight = yourCustomCell.frame.size.height + textView.contentSize.height
yourCustomCell.frame.size.height = newHeight
updateTableViewContentOffsetForTextView()
}
}
// Animate cell, the cell frame will follow textView content
func updateTableViewContentOffsetForTextView() {
let currentOffset = tableView.contentOffset
UIView.setAnimationsEnabled(false)
tableView.beginUpdates()
tableView.endUpdates()
UIView.setAnimationsEnabled(true)
tableView.setContentOffset(currentOffset, animated: false)
}
// UITableViewDelegate, UITableViewDataSource
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableViewAutomaticDimension
}
override func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return UITableViewAutomaticDimension
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = yourCustomCell
cell.selectionStyle = .none
return cell
}
}
The result is here:
Result after using textViewDelegate, and custom resizing function
Related
I have an UITableView and inside UITableViewCell, I have added view and trying to set the height of that view or height of the cell according to screen height or UITableView's height. Initially, I was able to do it but when in the viewWillAppear reloading table, not able to set the proper height for that view or height of the cell. It's the height or some other problem, not able to identify. Any help would be appreciated and Thanks for the reply. The title of the question may be confusing or do you find any unrelated code then suggestions(edits) are welcome.
Code:
import UIKit
class PageViewController: UIViewController {
#IBOutlet weak var tblPager: UITableView!
let screenHeight = UIScreen.main.bounds.size.height
let vColors: [UIColor] = [.red, .blue, .orange, .brown, .cyan, .darkGray, .green, .red, .blue, .orange, .brown, .cyan, .darkGray, .green]
var pageSizeHeight: CGFloat = 0
override func viewDidLoad() {
super.viewDidLoad()
pageSizeHeight = screenHeight - (getTopSafeArea() + getBottomSafeArea() + 54)
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
delay(interval: 10.0) {
print("Reload table after 10 seconds")
self.tblPager.reloadData()
}
}
}
//MARK:- TableView Delegate
extension PageViewController: UITableViewDelegate, UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return vColors.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "PageCell", for: indexPath) as! PageCell
cell.backgroundColor = vColors[indexPath.row]
cell.viewHeight.constant = pageSizeHeight
return cell
}
}
class PageCell: UITableViewCell {
#IBOutlet weak var vwPage: UIView!
#IBOutlet weak var viewHeight: NSLayoutConstraint!
}
func getTopSafeArea() -> CGFloat {
let window = UIApplication.shared.keyWindow
let topPadding = window?.safeAreaInsets.top ?? 0
return topPadding
}
func getBottomSafeArea() -> CGFloat {
let window = UIApplication.shared.keyWindow
let bottomPadding = window?.safeAreaInsets.bottom ?? 0
return bottomPadding
}
func delay(interval: TimeInterval, closure: #escaping () -> Void) {
DispatchQueue.main.asyncAfter(deadline: .now() + interval) {
closure()
}
}
Output:
Link it to tableView's height, your table view has all sizes you need.
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) {
// ...
cell.viewHeight.constant = tableView.frame.size.heigh
// ...
}
or remove viewHeight constraint and use delegate method to set row height
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return tableView.frame.size.height
}
UPD:
TableView using estimatedRowHeight to calculate its scroll offsets. This does create an issue during reload if we have enabled paging and do not configure estimatedRowHeight.
Solution 1:
Implement estimatedHeightForRowAt delegate
func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
return tableView.frame.size.height
}
Solution 2:
Set tableView.estimatedRowHeight = 0 and use heightForRowAt delegate instead of viewHeight constraint
if all cells will have the same height, why don't you set the rowHeight property inside viewWillLayoutSubviews method?
override func viewWillLayoutSubviews() {
super.viewWillLayoutSubviews()
tblPager.rowHeight = tblPager.frame.height
}
Thanks to #Desdenova for correcting me
By setting dataSource and delegate of tblPager to self in PageViewController's viewDidLoad and setting the rowHeight property in viewDidLayoutSubviews, tableView behaves as expected.
override func viewDidLoad() {
super.viewDidLoad()
tblPager.register(UINib(nibName: "PageTableViewCell", bundle: nil), forCellReuseIdentifier: "PageCell")
tblPager.dataSource = self
tblPager.delegate = self
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
tblPager.rowHeight = tblPager.frame.size.height
}
I have a table view that is inside a viewcontroller, the tableview resizes according to the dynamic cells, sometimes there are only 1 rows, sometimes more, the problem is that the footer of the tableview occupies a lot of space, i want the footer to hide, i tries using the delegate method viewForFooterInSection, and also setting the footer height to 0 in viewdidload method, and to 1.0 in heightForFooterInSection, and the footer is still showing, here is a photo of the tableview, i made the footer background black to check where is it
this is the code i use in viewdidload:
override func viewDidLoad() {
super.viewDidLoad()
let notificationName = Notification.Name(rawValue: "ErrorGettingReportDetail")
NotificationCenter.default.addObserver(self, selector: #selector(self.mostrarErrorDetalle), name: notificationName, object: nil)
// Do any additional setup after loading the view.
/*self.backView.layer.cornerRadius = 10
self.backView.layer.masksToBounds = true*/
self.backScrollView.layer.cornerRadius = 10
self.backScrollView.layer.masksToBounds = true
self.commentTextView.delegate = self
let tap: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: "dismissCommentsPopUp")
view.addGestureRecognizer(tap)
self.tagsTableView.dataSource = self
self.commentTextView.autocorrectionType = .no
self.tagsTableView.estimatedRowHeight = 40
self.tagsTableView.rowHeight = UITableViewAutomaticDimension
}
and this is the code i use for the tableview:
//MARK: -TagsTableView
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if(self.reporte != nil){
if((self.reporte?.atributosInfo?.count)! > 0){
return (self.reporte?.atributosInfo?.count)!
}else{
//self.tagsTableView.isHidden = true
return 0
}
}else{
return 0
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if(KRProgressHUD.isVisible){
KRProgressHUD.dismiss()
}
if(self.reporte != nil){
let cell = tableView.dequeueReusableCell(withIdentifier: "atributoCell") as! AtributoTableViewCell
let atributosInfo = self.reporte?.atributosInfo![indexPath.row]
cell.configureCellWith(atributoInfo: atributosInfo!)
cell.atributo = atributosInfo
print(indexPath.row)
let height = cell.frame.height
self.tagsTableViewHeight.constant += height
return cell
}else{
let cell = UITableViewCell()
//self.tagsTableViewHeight.constant -= cell.frame.height
return cell
}
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 100
}
//MARK END
any help will be appreciated.
please use this
func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {
return .leastNonzeroMagnitude
}
You can use:
tableView.tableFooterView?.isHidden = true
Try this in viewDidLoad:
tagsTableView.tableFooterView = UIView()
There is a section footer and a tableView footer.
I have a UItableview cell that is contain a UItableview, I need to make height of that cell equal to height of it's child UItableview.
Image below explain what I need to do.
First see my ViewController,which has one tableview(tblview) and UITableViewCell(CustomTableViewCell) ,
class ViewController: UIViewController {
#IBOutlet var tblview:UITableView!
override func viewDidLoad() {
super.viewDidLoad()
self.tblview.delegate = self
self.tblview.dataSource = self
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
extension ViewController:UITableViewDelegate,UITableViewDataSource{
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 5
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: CustomTableViewCell.identifier) as! CustomTableViewCell
return cell
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableViewAutomaticDimension
}
func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableViewAutomaticDimension
}
}
Then see my CustomTableViewCell which has one table view and one label in a cell.See,
class CustomTableViewCell: UITableViewCell {
static let identifier = "CustomTableViewCell"
#IBOutlet var tblviewCell:UITableView!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
self.tblviewCell.delegate = self
self.tblviewCell.dataSource = self
tblviewCell.isScrollEnabled = false
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
override func systemLayoutSizeFitting(_ targetSize: CGSize, withHorizontalFittingPriority horizontalFittingPriority: UILayoutPriority, verticalFittingPriority: UILayoutPriority) -> CGSize {
let heighToReturn = self.tblviewCell.contentSize.height + 20 // upper and down space
return CGSize(width: self.tblviewCell.contentSize.width, height: heighToReturn)
}
}
extension CustomTableViewCell:UITableViewDelegate,UITableViewDataSource{
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
return 5
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: customCell.identifier) as! customCell
cell.lblname?.text = "Vikas"
return cell
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 80
}
}
class customCell: UITableViewCell {
static let identifier = "customCell"
#IBOutlet weak var lblname :UILabel?
}
So, if you give tableview content size height in systemLayoutSizeFitting method then problem will be solve.
I hope this will help.
Here's how to do table header cells. The cell needs to be prototyped in the storyboard and subclassed (if needs to be configured). Then override the following funcs in the table view delegate. Alternatively, you can generate a view on the fly and return that from viewForHeaderInSection.
override func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return 150
}
override func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let headerCell = tableView.dequeueReusableCell(withIdentifier: "ConferenceHeaderCell") as! ConferenceDetailHeaderCell
// configure cell
return headerCell
}
For the cells themselves, it's very similar:
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "ConferenceUserCell", for: indexPath) as! ConferenceDetail_TVCell
// Configure the cell...
return cell
}
and depending, you may to implement 'heightForRowAtIndexPath'
So I want to change the default animation duration of UITableView's beginUpdates() & endUpdates(), which I think is 0.3s.
I tried placing them inside a UIView animation block, then I got abrupt animation.
To see what I am talking about, create a new iOS "Single View Application" Project, and replace ViewController.swift with the following code:
class ViewController: UIViewController {
var tableView = UITableView()
var isExpanded = false
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(tableView)
tableView.frame = view.bounds
tableView.dataSource = self
tableView.delegate = self
let changeHeightButton = UIBarButtonItem(title: "Change Height", style: .plain, target: self, action: #selector(changeHeight))
navigationItem.rightBarButtonItem = changeHeightButton
}
func changeHeight() {
isExpanded = !isExpanded
UIView.animate(withDuration: 0.5, animations: {
self.tableView.beginUpdates()
self.tableView.endUpdates()
}, completion: nil)
}
}
extension ViewController: UITableViewDataSource, UITableViewDelegate {
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell") ?? UITableViewCell(style: .default, reuseIdentifier: "cell")
cell.textLabel?.text = "Section \(indexPath.section), Row \(indexPath.row)"
return cell
}
func numberOfSections(in tableView: UITableView) -> Int{
return 4
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 3
}
func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return "Section: \(String(section))"
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
if isExpanded && indexPath == IndexPath(row: 0, section: 0) { return 300 }
else { return 44 }
}
}
I am trying to expand my cell when there is extra text inputed. I do not want "..." at the end I would like the cell to automatically expand. I have taken these two steps below but it is not working.
Step 1
self.tableView.dataSource = self
self.tableView.delegate = self
tableView.estimatedRowHeight = 44
tableView.rowHeight = UITableViewAutomaticDimension
Step 2
messageLabel.numberOfLines = 0
For some reason my cell is not expanding what am I doing wrong?
import UIKit
import Foundation
struct postStruct {
let username : String!
let message : String!
let photoURL : String!
}
class GeneralChatroom: UIViewController, UITableViewDataSource, UITableViewDelegate, UITextFieldDelegate {
#IBOutlet weak var messageTextField: UITextField!
#IBOutlet weak var tableView: UITableView!
var generalRoomDataArr = [postStruct]()
override func viewDidLoad() {
super.viewDidLoad()
self.tableView.dataSource = self
self.tableView.delegate = self
tableView.estimatedRowHeight = 44
tableView.rowHeight = UITableViewAutomaticDimension
}
#IBAction func backButtonPressed(_ sender: UIButton) {
self.performSegue(withIdentifier: "BackToRoom", sender: nil)
}
//Message Send button is pressed data uploaded to firebase
#IBAction func sendButtonPressed(_ sender: UIButton) {
let message : String = self.messageTextField.text!
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return generalRoomDataArr.count // your number of cell here
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell")
//Set message label to display message
let messageLabel = cell?.viewWithTag(2) as! UILabel
messageLabel.text = generalRoomDataArr[indexPath.row].message
messageLabel.numberOfLines = 0
// your cell coding
return cell!
}
}//END CLASS
UPDATE:
I have the current constraints but my dynamic cell growth is not working. My cell is still showing "..." Can anyone help me understand why? I tried reset to suggested constraints but it is not working.
Make sure you've auto layout for the custom UITableViewCell. Change the estimatedRowHeight, try this:
tableView.estimatedRowHeight = 200
You can use the delegate method of UITableView:
func tableView(_ tableView: UITableView,heightForRowAt indexPath: IndexPath) -> CGFloat
{
return .AutomaticDimension
}
func tableView(_ tableView: UITableView,estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat
{
return 60
}
But first you must set the autolayout constraint for the label w.r.t to the content view of TableViewCell.
Swift 2.3
// MARK: - TableViewDelegate Setup
extension NotificationVC : UITableViewDelegate,UITableViewDataSource {
func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return UITableViewAutomaticDimension
}
func tableView(tableView: UITableView, estimatedHeightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return UITableViewAutomaticDimension
}
}