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.
Related
I have a view controller, in the viewdidload method I call a function to make some calls to retrieve data online.
After I retrieve the data I append them into an array and reload the table view
at first, everything looks great however, when I scroll down I get to see what you see down below.
extension CastTableViewController : UITableViewDelegate, UITableViewDataSource {
func conigure_cast_table () {
castTable.translatesAutoresizingMaskIntoConstraints = false
castTable.delegate = self
castTable.dataSource = self
castTable.register(ActorCell.self, forCellReuseIdentifier: ActorCell.cellid)
view.addSubview(castTable)
castTable.frame = view.bounds
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return cast.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = castTable.dequeueReusableCell(withIdentifier: ActorCell.cellid, for: indexPath) as! ActorCell
let name = cast[indexPath.row].name
let character_name = cast[indexPath.row].character
let pic = cast[indexPath.row].picture_path
cell.configure(name: name, charName: character_name, pic_url: pic)
return cell
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 100
}
}
i fixed this by using prepareforreuse
// in the custom cell class
override func prepareForReuse() {
super.prepareForReuse()
for subview in stack.arrangedSubviews {
stack.removeArrangedSubview(subview)
}
actorPic.image = nil
realName.banner_title.text = nil
realName.info.text = nil
character.banner_title.text = nil
character.info.text = nil
}
I have a data set that has an inner array and I have to show that Inner array in Expand collapse fashion.
For that I have designed 2 nib files. One for the sections, and other for the cell in sections.
I have attached UitableView and the delegated methods. I am successful to show the Header view, I am registering the header view like this.
let nib = UINib.init(nibName: "headerItemSavedListCell", bundle: nil)
self.lvSavedList.register(nib, forCellReuseIdentifier: "headerItemSavedListCell")
and for cell I am doing in the following method
if(indexPath.row == 0){
let header = Bundle.main.loadNibNamed("headerItemSavedListCell", owner: self, options: nil)?.first as! headerItemSavedListCell
return header
}else{
let cell = Bundle.main.loadNibNamed("ItemSavedListCell", owner: self, options: nil)?.first as! ItemSavedListCell
return cell
}
But its not working.
**So my questions is: **
How to load the inner cell view ?
How to expand collapse cell view that lies inside the Sections?
Please help if you have any tutorial regarding expandable Uitableview
the class i am using here are connected to xibs
make xib of view and bind below class
so first you have to make headerview like below
protocol HeaderDelegate:class{
func didSelectHeader(Header:HeaderFooter,at index:Int)
}
class HeaderFooter: UITableViewHeaderFooterView {
#IBOutlet weak var lblTitle: UILabel!
weak var delegate:HeaderDelegate?
var Expand = false
override func awakeFromNib() {
let tap = UITapGestureRecognizer.init(target: self, action: #selector(didSelect(_:)))
self.addGestureRecognizer(tap)
self.isUserInteractionEnabled = true
}
#objc func didSelect(_ tap:UITapGestureRecognizer)
{
delegate?.didSelectHeader(Header: self, at: self.tag)
}
override func prepareForReuse() {
Expand = false
}
}
above i added tap gesture to detect touch on headerViews
next make cell like below
class ExpandableCell: UITableViewCell {
var isExpanded = false
override func awakeFromNib() {
super.awakeFromNib()
isExpanded = false
// Initialization code
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
}
in your view controller
tblView.register(UINib.init(nibName: "HeaderFooter", bundle: nil), forHeaderFooterViewReuseIdentifier: "HeaderFooter")
in tablview dataSorce and Delegate Method
func numberOfSections(in tableView: UITableView) -> Int {
return numberofsections
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return numberofrows
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let cell = tableView.dequeueReusableCell(withIdentifier: "ExpandableCell") as? ExpandableCell else {
return UITableViewCell()
}
//configure cell here
return cell
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
guard let header = tableView.headerView(forSection: indexPath.section) as? HeaderFooter
else {return 0}
if header.Expand
{
return UITableViewAutomaticDimension
}
else
{
return 0
}
}
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return UITableViewAutomaticDimension
}
func tableView(_ tableView: UITableView, estimatedHeightForHeaderInSection section: Int) -> CGFloat {
return 50
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
}
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
guard let headerView = tableView.dequeueReusableHeaderFooterView(withIdentifier: "HeaderFooter") as? HeaderFooter else {return nil}
//configure header View here
headerView.tag = section
return headerView
}
//MARK:-headerDelegate
func didSelectHeader(Header: HeaderFooter, at index: Int) {
Header.Expand = !Header.Expand
//comment below part if you dont want to collapse other rows when other section opened
for i in 0..<tblView.numberOfSections
{
if i != index
{
guard let header = tblView.headerView(forSection: i) as? HeaderFooter else {return}
header.Expand = false
for j in 0..<tblView.numberOfRows(inSection: i)
{
tblView.reloadRows(at: [IndexPath.init(row: j, section: i)], with: .automatic)
}
}
else
{
for j in 0..<tblView.numberOfRows(inSection: i)
{
tblView.reloadRows(at: [IndexPath.init(row: j, section: i)], with: .automatic)
}
}
}
}
I have a UITableViewController, which has a custom cell that I want to display an image and labels. screenshots can explain my problem very well, it looks like this
.
And when I select any cell it looks like
In tableviewcontroller cell is not visible in proper shape according to constraints
here is my custom cell with autolayout constraints
How I can fix this issue? ... I created this tableviewcontroller programmatically without using storyboard.
here is code sample of data source and delegates of tableviewcontroller
override func numberOfSections(in tableView: UITableView) -> Int {
var numOfSections: Int = 0
let count = conversations.count
if count > 0 {
// tableView.separatorStyle = .none
numOfSections = 1
tableView.backgroundView = nil
}
else
{
let frame = CGRect(x: 0,
y: 0,
width: tableView.bounds.size.width,
height: tableView.bounds.size.height)
let noDataLabel: UILabel = UILabel(frame: frame)
noDataLabel.text = "You don't have any messages. 🙃"
noDataLabel.textColor = UIColor.black
noDataLabel.textAlignment = .center
tableView.backgroundView = noDataLabel
tableView.separatorStyle = .none
}
return numOfSections
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return conversations.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "inboxCell", for: indexPath) as! InboxCell
cell.conversation = conversations[indexPath.row]
return cell
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let uids = conversations[indexPath.row].conversationUseruids
for uid in uids{
if uid == Account.account.user.uid{
}
else{
User.getUser(with: uid, completion: { (user) in
self.selectedUser.append(user!)
})
}
}
tableView.deselectRow(at: indexPath, animated: true)
let index = indexPath.row as Int
messageVC.conversationIndex = index
messageVC.conversation = self.conversations[index]
navigationController?.pushViewController(messageVC, animated: true)
}
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 80
}
it happen because your image not have upper lower constraint if not working than let me know
I have collapse and expand animation in UITableView. Tableview has two section in which first section data is collapse and expand. This thing perfectly working with ios 10 but in ios 11 Section view repeated or overlapped with cell data which is expanded.
Below is my code
//MARK: -Table View delegate Method
func numberOfSections(in tableView: UITableView) -> Int {
return read_Localizable("titleHelpSection").components(separatedBy: ",").count
}
//MARK: -Table View Datasource Method
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return UITableViewAutomaticDimension
}
func tableView(_ tableView: UITableView, estimatedHeightForHeaderInSection section: Int) -> CGFloat{
return 44.0
}
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
var headerView = tableView.dequeueReusableHeaderFooterView(withIdentifier: "headerView")
let arrSection = read_Localizable("titleHelpSection").components(separatedBy: ",")
if headerView == nil
{
headerView = UITableViewHeaderFooterView(reuseIdentifier: "headerView")
headerView?.contentView.backgroundColor = UIColor.white
let lblResult = UILabel()
lblResult.tag = 123456
lblResult.font = AppCommonSNMediumFont()
lblResult.textColor = UIColor.black
lblResult.translatesAutoresizingMaskIntoConstraints = false
headerView?.contentView.addSubview(lblResult)
let seperator = UIView()
seperator.translatesAutoresizingMaskIntoConstraints = false
seperator.backgroundColor = UIColor.black
headerView?.contentView.addSubview(seperator)
headerView?.contentView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|[seperator]|", options: [], metrics: nil, views: ["seperator":seperator]))
headerView?.contentView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|-[lable]-(>=8)-|", options: [], metrics: nil, views: ["lable":lblResult]))
headerView?.contentView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|-[lable]-[seperator(1)]|", options: [], metrics: nil, views: ["lable":lblResult,"seperator":seperator]))
}
if let lblResult = headerView?.contentView.viewWithTag(123456) as? UILabel
{
lblResult.text = arrSection[section]
}
return headerView
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableViewAutomaticDimension
}
func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
return 20.0
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if section == 0
{
return (arrHelpData.count)
}
else
{
return 1
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if indexPath.section == 0
{
var cell = tableView.dequeueReusableCell(withIdentifier: "HelpCell") as? CellHelp;
if cell == nil {
cell = CellHelp(style: .default, reuseIdentifier: "HelpCell")
cell?.selectionStyle = .none
cell?.txtContain.delegate = self
}
if let objModel = arrHelpData.object(at: indexPath.row) as? HelpModel
{
cell?.lblTitle.text = objModel.helpTitle
if objModel.isExpanded == true
{
cell?.txtContain.text = objModel.helpDesc
}
else
{
cell?.txtContain.text = ""
}
cell?.imgArrow.isHighlighted = !objModel.isExpanded
}
return cell!
}
else
{
var cell = tableView.dequeueReusableCell(withIdentifier: "DefultCell")
if cell == nil
{
cell = UITableViewCell(style: .default, reuseIdentifier: "DefultCell")
cell?.textLabel?.textColor = color1F87A3()
cell?.textLabel?.font = AppCommonSNRegularFont()
cell?.selectionStyle = .none
cell?.textLabel?.numberOfLines = 0
}
cell?.textLabel?.text = read_Localizable("titleSettings")
return cell!
}
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if indexPath.section == 0 && indexPath.row < (arrHelpData.count)
{
if let objModel = arrHelpData.object(at: indexPath.row) as? HelpModel
{
if objModel.isExpanded == true
{
objModel.isExpanded = false
}
else
{
objModel.isExpanded = true
}
tableView.reloadData()
}
}
}
Actual view
Section overlapped on cell data
This is very frustrating iOS11 issue, something to do around estimatedHeight issue, If you really want to keep the self sized row and header then u need to go with the below approach.
Declare variable which holds the height of the cell/header and store height into that and used it as below:
var cellHeightDictionary: NSMutableDictionary // To overcome the issue of iOS11.2
override func viewDidLoad() {
super.viewDidLoad()
tableView.rowHeight = UITableViewAutomaticDimension
tableView.estimatedRowHeight = 125
}
override func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
cellHeightDictionary.setObject(cell.frame.size.height, forKey: indexPath as NSCopying)
}
func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
if cellHeightDictionary.object(forKey: indexPath) != nil {
let height = cellHeightDictionary.object(forKey: indexPath) as! CGFloat
return height
}
return UITableViewAutomaticDimension
}
This is the only solution which worked for me for iOS11 issues with auto sizing cells. Otherwise people suggest to keep estimatedHeight 0 to get rid off such issues.
In your case first try doing this for cell and that doesn't solve the issue completely then do same for header height also. Hope this helps!
Don't forget to test in both iOS11.1 and iOS11.2.
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