TableView inside TableView cell, adjust cell height automatically - ios

A list of content needs to be displayed in each tableviewcell, So here I used tableview inside Tableview cell. But the problem is main tableview cell height is not changing according to the content. I don't want to fix the UITableViewCell height, I want it to be adjusted dynamically based on the content.
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableView.automaticDimension
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 10
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell") as! SubCell
if indexPath.row%2==0{
cell.backgroundColor = .orange
}else{
cell.backgroundColor = .green
}
return cell
}
class SubCell: UITableViewCell, UITableViewDelegate,UITableViewDataSource {
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableView.automaticDimension
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 4
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell2") as! SubCell2
cell.titleLabel.text = "asdf asdf asdf asdf asdf adfs asdf asdf asdf asdf asdf asdf asd fasd fasd fasd fasd fasd fasd f asdf asdf asdf asdf asd fasd fasd fasd fasd fasd fasdf asdf asd fasd 1234"
return cell
}
#IBOutlet weak var tablView2: UITableView!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
}
}
class SubCell2: UITableViewCell {
#IBOutlet weak var titleLabel: UILabel!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
}
Expected Output :
Actual Output:
Constraints:

Solution:
make your label constraint Bottom space to container to its superview(content view).
Now select "yourTableView" in size inspector make it "Row height as Automatic"
Now select "yourTableViewCell" in size inspector make it "Row height as Automatic"
As based on label height, the content view will be Resized, And the allocation of height tableViewcell & tableview is automatically adjusted.
i have posted the above answer only for StoryBoard & Xib.

You don't have any height settings for your Title Label. If you set one, your cells will act dynamically.
You can add another constraint to the Title Label and set the height to "greater than or equal to" whatever number you want to start with (30, for example). So long as you have that title label's number of lines set to 0, then the title label should dynamically grow in height and still maintain the same padding you've had with the rest of your constraints.

In the case of dynamic content where we need to place a UITableView inside a UITableViewCell, Automatic Dimension doesn’t seem to work because the outer UITableView needs to have a height for every cell it has. By the time this height is needed, the child UITableView hasn’t loaded its own cells yet, and therefore compiler cannot get the height in runtime.
So how do we achieve this ? One way is to use a vertical axis UIStackView (instead of a UITableView) inside the parent cell with leading, trailing, top and bottom constraints with respect to the cell’s content view without any need for height constraint. Instead of UITableViewCell create a custom view with necessary UI components and add as addArrangedSubview to the UIStackView. As each view is added to the stack view, the stack view’s height dynamically increases which in turn expands the height of the outer UITableViewCell thereby achieving dynamic height with automatic dimension of the outer table.

Related

ios scrollview with a full screen video as main content

this is the layout i want to acheive
I am trying to figure out how to make this layout work on different screens. i have tried to get the screen height and programatically set the video layer height equal to it. The volume button constrains are 25 from the right margin and 25 from the bottom of the video. The problem is that when i try to run the app the volume button shows in the middle right of the screen instead on the right of the bottom corner. Also the image views are overlapping the video instead of showing up under it. My assumption is that the constrains of these elements see the height of the video layer in the story board, not the height that i set programatically in the ViewController.swift.
You can achieve a more coherent layout with a table view and having a section for your full screen video and the rest of the image views in another section. The section for your video will have UIScreen.main.bounds.height for the cell height so that you can have a dynamic full screen height regardless of the device.
class ViewController: UITableViewController {
var arr: [[String]] = {
var arr = [[String]]()
arr.append(["Video"])
var imageArr = [String]()
for index in 1...20 {
imageArr.append(String(index))
}
arr.append(imageArr)
return arr
}()
override func viewDidLoad() {
super.viewDidLoad()
tableView.register(UITableViewCell.self, forCellReuseIdentifier: "cell")
}
override func numberOfSections(in tableView: UITableView) -> Int {
return arr.count
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return arr[section].count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
cell.textLabel?.text = arr[indexPath.section][indexPath.row]
return cell
}
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
if indexPath.section == 0 {
return UIScreen.main.bounds.height
} else {
return 100
}
}
}
As for the volume button, you can create a custom cell for the video section and load it in the cellForRowAt method. Make sure you're using Autolayout and not CGRect to position it.
first of all you are working with ScrollView so you need to give each item in you screen a height so you will give the video screen height "Fixed Height" then you will give your button a fixed height as well and connect it from trailing, leading, bottom and Top and I think it will work with you, and if there is any issue appeared feel free to comment with it

UITableViewCell with StackView not dynamically sizing height

I have a custom UITableViewCell that contains a StackView with top, bottom, leading and trailing constraints to the content view of the cell.
When I set up my tableView, I give it an estimated height and also set the rowHeight to UITableViewAutomaticDimension.
In my cellForRowAt datasource method, I dequeue the cell and then call cell.setup() which adds any given number of views to my cell's stackView.
The problem is: My cell is always being sized to the estimated height of 80p. No matter how many views I add to the cell's stackView, it all crams into 80p height. The stackView, and thus the cell, isn't growing with each new item I insert into the cell before returning it in cellForRowAt datasource method.
I tried different distribution settings for my stackView, but I'm not sure what I'm doing wrong here.
Here is a simple demonstration of adding buttons to a stack view inside an auto-sizing table view cell:
class StackOfButtonsTableViewCell: UITableViewCell {
#IBOutlet var theStackView: UIStackView!
func setup(_ numButtons: Int) -> Void {
// cells are reused, so remove any previously created buttons
theStackView.arrangedSubviews.forEach { $0.removeFromSuperview() }
for i in 1...numButtons {
let b = UIButton(type: .system)
b.setTitle("Button \(i)", for: .normal)
b.backgroundColor = .blue
b.setTitleColor(.white, for: .normal)
theStackView.addArrangedSubview(b)
}
}
}
class ViewController: UITableViewController {
override func viewDidLoad() {
super.viewDidLoad()
tableView.rowHeight = UITableViewAutomaticDimension
tableView.estimatedRowHeight = 100
}
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 6
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "StackOfButtonsTableViewCell", for: indexPath) as! StackOfButtonsTableViewCell
cell.setup(indexPath.row + 1)
return cell
}
}
Assuming you have created a prototype cell, and its only content is a UIStackView configured as:
Axis: Vertical
Alignment: Fill
Distribution: Equal Spacing
Spacing: 8
and you have it constrained Top/Leading/Trailing/Bottom to the cell's content view, this is the result:
No need for any height calculations, and, since buttons do have intrinsic size, no need to set height constraints on the buttons.

UITableViewCell Auto Sizing Issue Swift

This is the custom UITableViewCell I've designed In a xib. The selected element is a UILabel, which is required to be expand with respect to amount of text.
In storyboard cell each element has a constant height with spacing.
Here's the code that I have in a UITableViewController:
class TableViewController: UITableViewController {
private var exampleContent = ["This is a short text.", "This is another text, and it is a little bit longer.", "Wow, this text is really very very long! I hope it can be read completely! Luckily, we are using automatic row height!, Wow, this text is really very very long! I hope it can be read completely! Luckily, we are using automatic row height!"]
override func viewDidLoad() {
super.viewDidLoad()
self.tableView.delegate = self
self.tableView.dataSource = self
tableView.estimatedRowHeight = 224.0
tableView.rowHeight = UITableViewAutomaticDimension
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = Bundle.main.loadNibNamed("DescriptionOnlyCell", owner: self, options: nil)?.first as! DescriptionOnlyCell
cell.label.numberOfLines = 0
cell.label.text = exampleContent[indexPath.row]
return cell
}
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return exampleContent.count
}
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableViewAutomaticDimension
}
Output of the code is same exactly as the storyboard cell, no dynamic resizing.
I've read a few threads on stackover and most of them explains same like the code posted above. Though I suspect there's some issue with the storyboard constraints. Any hint would be really helpful.
Instead of setting the constant height values for your labels, set the top and the bottom spacing constraints for all elements and remove height constraints or set their priority lower.
Do the following for the selected label :
Set number of lines = 0
Set lineBreak mode = WordWrap
Set height constraint to >= 15
I am relying on the info you shared that vertical spacing for all UI components is set.
I hope this would fix your resizing.
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
tableView.layoutIfNeeded()
}

Two label align vertically in tableView cell auto resizing swift

Try to auto resizing two labels align vertically within a cell, is that possible?
In the storyboard, we have to set autolayout, since I want to auto resizing two labels(one is on top of another).
I can't set each height so that the storyboard doesn't know what is the height of these two labels so it shows an error for autolayout.
if I click "Add Missing Constraints" button it will add a height for "subtitle"
or I can set height for "title" rather than "subtitle",
or make "title" equal to "subtitle" it will still accept.
here is the result:
A workaround will be separate these two to a different cell.
Any better solution? or am I just simply forget to do anything?
P.S. I'm using Xcode 8 with iOS 10.3.
Try setting out Proper constraints for both the labels-:
Storyboard-:
Constraints for first label-:
Constraints for second label-:
Controller class(use Automatic Dimensions for table view)-:
class ViewController1: UIViewController {
var dataForTableView:[ProductImage]?
#IBOutlet weak var secondTable: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
secondTable.estimatedRowHeight = 96
secondTable.rowHeight = UITableViewAutomaticDimension
// CHECK FOR DATA
//print(dataForTableView?[0].url as Any)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
extension ViewController1 : UITableViewDelegate,UITableViewDataSource{
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int{
return 1
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell{
let cell = tableView.dequeueReusableCell(withIdentifier: "cell1") as! testingCell2
cell.backgroundColor = UIColor.blue;
cell.secondLabel.text = "agfhjsgfhjsgdshgfhjsfjhvhssajs hjfbvhjfbvjhfgafgfhlgkaghkfakfhkflbvhfbvhfvbhfv ah fvfhbvfjhvbfhdavhfvhv"
return cell
}
// Number of sections in table
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}// Default is 1 if not implemented
public func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat{
return UITableViewAutomaticDimension
}
}
Output-:
I hope that is what you looking for, let me know if any issues.Thanks

Autosizing UITableView inside custom UIView for section

I have created UIViewController and added UITableView on it (pinned to all four edges with autolayout).
Then I set estimatedRowHeight (44) and rowHeight (UITableViewAutomaticDimension) and returned 5 custom cells. And it worked.
Now, I want to add custom UITableViewHeaderFooterView that would have dynamic height.
I'm doing next:
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return 88.0
}
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
return R.nib.orderStatusHeaderView.firstView(owner: self)!
}
My OrderStatusHeaderView is a xib view that has UITableView on it pinned to all 4 edges with autolayout.
OrderStatusHeaderView:
final class OrderStatusHeaderView: UITableViewHeaderFooterView {
#IBOutlet weak var tableView: UITableView! {
didSet {
tableView.dataSource = self
tableView.delegate = self
tableView.rowHeight = 44.0
}
}
}
extension OrderStatusHeaderView: UITableViewDataSource, UITableViewDelegate {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 2
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = UITableViewCell(style: .default, reuseIdentifier: "\(indexPath.row)")
cell.textLabel?.text = "\(indexPath.row)"
cell.backgroundColor = .red
return cell
}
}
This displays like:
And when I tap or scroll, all red cells disappears. What could it be? And how to make UITableView dynamically load content and UITableViewHeaderFooterView will size itself so it fit UITableView.contentSize. Is it possible?
Check out:
tableView(_:estimatedHeightForFooterInSection:)
and
tableView(_:heightForFooterInSection:)
You also have the equilavant for headerInSection.
Since you are asking for a table's header and footer view, you can skip the delegate methods you describe. Those (as the name implies) are for SECTION headers and footers.
When you set a view that is using AutoLayout as the table's header or footer, the its frame still has a zero height (That's why buttons in such view for example won't work as they are not receiving the touches).
To correctly size a table's header or footer views using AutoLayout you have to apply a trick to actually calculate the height yourself, and set the headerView again. It is described in detail in many posts like these:
https://stackoverflow.com/a/28102157/756039
https://gist.github.com/marcoarment/1105553afba6b4900c10
http://collindonnell.com/2015/09/29/dynamically-sized-table-view-header-or-footer-using-auto-layout/
http://roadfiresoftware.com/2015/05/how-to-size-a-table-header-view-using-auto-layout-in-interface-builder/
Hope this helps.

Resources