Inside the ScrollView are two Labels (multilateral), and below it the TableView (in which the number of rows may be different).
The height of both Label and TableView is not set.
All outlets set constraints on the indents from each other above and below, including a View of the container.
In summary: both Labels height correct, but TableView is obtained with a height of 0 (not visible). It is only visible if the height is explicitly set. The number of rows of the TableView is determined correctly.
How can I programmatically set the height of the TableView to show it? ("row height" x "number of cells")? I know the height of row in TableView.
You are referring to the contentSize's height of the table view.
First you need to add a height constraint for the table view.
Then after the table finishes loading, do this :
self.tableViewHeightConstraint.constant = self.tableView.contentSize.height;
Related
I'm trying to create layout that it structured like this:
- View
-- ScrollView
--- ContentView
---- CustomView
---- CustomView
---- TableView
---- CustomView
The tableView itself is auto-resizable using "invalidateIntrinsicContentSize" and when I add items - the height of the tableview changes, pushing the custom view below it further down.
Once enough items are added I the bottom custom view is hidden and the scroll doesn't work.
important fact - the bottom custom view doesn't have a bottom constraint. It is pushed down by the it's top constraint to the tableView.
If I do set a bottom constraint - the table view will no longer be dynamically resized.
The intended behaviour:
When a user adds items to the list and the list gets too big the ContentView will be scrollable so the user can scroll to see the bottom view.
The actual behaviour:
When a user adds items to the list and the list gets too big, the bottom view is pushed down and outside of sight and content is not scrollable.
What is happening and how can I fix it?
Below is what I think what is happening.
Since you are using UITableView, it has its own scroll view. So when the UITableView list gets too big, UITableView itself becomes scrollable rather than ScrollView's contentView becoming scrollable.
To achieve what you need, you would have to make the UITableView not scrollable and use the intrinsicHeight of the UITableView to get the actual height of UITableView along with all the items. If you have items with varying heights, it will be a problem because you won't know the height before rendering. With same height for all the rows, you can get the total height of the UITableView and set the height constraint to that value. This will increase the contentSize of the outer ScrollView, making it scrollable.
Apart from UITableView, you can also use UIStackView. This is because you are not using the reusing capabilities of UITableView anyways. Managing the datasource and delegates should not be a big problem.
You can create a constraint for tableview height, And take its reference to your swift file, by dragging it as you take other views. Now in your code, Just do this
tableViewHeightConstraint.constant = tableViewNoOfItems * tableViewCellHeight;
if you have set other constraints perfectly inside scrollview, It should work perfectly. Means TableView should have top, bottom, left, right margined constraints from the ScrollView.
try this code
tblViewHeight.constant = CGFloat( tableview row count * 45 )
var size = contentView.systemLayoutSizeFitting(UILayoutFittingCompressedSize)
if size.height < scrollView.frame.size.height
{
size = scrollView.frame.size
}
contenViewHeight.constant = size.height - scrollView.frame.size.height
scrollView.contentSize.height = contenViewHeight.constant
What I think you could do is:
Disable tableView's scroll tableView.isScrollEnabled = false
Every time a user adds items to the list, reload the tableView
Also using UIStackView with vertical axis and .fillEqually distribution as a Content View would be much more convenient as you won't need to set any positional constraints to your views, but may need to set height constraints if intrinsic content size can't be determined by the engine
Problem example: https://github.com/hecode/problem-example
using method 3 mentioned below
sorry for the rushed code.
the view is very complex but i will try to explain as much as i can.
the view looks something like this:
******full height parent table**************
******parent cell*************************
* static content
* variable height label
*** full height inner tableview*****
*** inner cell *****
* static content
* variable height label
********************
************************************
*****************************************
********************************************
both cells are variable height using:
tableView.estimatedRowHeight = 90
tableView.rowHeight = UITableViewAutomaticDimension
and both tableviews are full height. for the parent i am using an observer on contentsize and updating it there which is working correctly.
my current problem is that the inner cell's tableview, its contentsize doesn't return the correct contentsize.
i tried:
1.using an observer on contentsize and changing the tableview's height constraint to the new value
2.changing the tableview's height constraint in overriden layoutSubviews with contentsize
3.changing the tableview's height constraint in overriden willDisplay with contentsize in the last cell and making the tableview's bottom constraint 750 instead of 1000, if it's 1000 then clipping happens
the first two methods result in clipping in most cases, and sometimes extra variable size space at the bottom.
the third methods has extra variable size space.
in the third method i tried printing the cell frame heights and compare them with the values in the xcode uidebugger and found that they are different.
btw the inner cell gets the data from the parent table and is the delegate and data source for the inner tableview
can someone give me any ideas? is there a way to get actual content size for the inner tableview to set the table's height constraint to it?
removing height constraint and using a bottom constraint to parent view results in clipping and also the innertableview is supposed to visible sometimes not all of the time so the height constraint is used to set it to 0 for the times it isn't needed.
i am using ios10.3, swift 3
In storyBoard i have given top, bottom, leading and trailing constraints to tableview in a view.
i have given tableview height as contentSize.height. As per tableview height, no of cells that can visible in tableview 3 or 4 or etc(depending upon content size it may vary). But the problem is table view height is increasing as per content size.
if no of cells are more, then it should compare actual height of the table view with content size and if contentSize is lesser than tableview Actual height then only it should change the height of tableview.
if tableViewActualHeight > contentSize {
// then only change tableview height
tableViewActualHeight = contentSize
}
How can we get & where to place that code?
OK here is an idea for that
First get height of tableview by yourTableView.frame.size.height.
Now calculate height of your tableView cells.
Lets assume the cases.
Assuming cell is of height 50 and tableview if height 200
First case
If you have 2 cell, then total cell height is 100. Now check if 100<200
bottomConstraint of tableView will be 200 - 100, that is 100.So here tableView height becomes 100
Second Case
If you have 5 cells ,then total cell height is 250 .Now check if 250<200
bottomConstraint will be ZERO
Please let me know if its helps you or having trouble to understand
You need to set one more constraint to your tableview - Fixed height.
Now take(or connect) outlet of that constraint and then set constant of that outlet as per your condition. If your content size is greater then your tableview do nothing else set your height constraint's constant as content size like,
heightConstraint.constant = 20 // Your contentsize instead of 20
You need to do that after your tableview successfully reload, other wise it will not give correct content size.
If your cell or row's height is fixed then you can count content height your self. You can multiply row height with number of row (array count)!
I am resizing my UITableView as per its number of rows in cellForRowAtIndexPath:, that's why the next part of the UITableView was not visible, and for the part of the UITableView which is not visible, cellForRowAtIndexPath: is never called.
But I need to manage TableView frame according to number of rows, please suggest how can i implement this.
Thanks
If you are using autoLayout
To your UITableView add a leading, trailing, top and bottom constraint >=0. Also add a fixed height constraint with a priority of 750. Create an IBOutlet for this height constraint to your UIViewController. Now you can calculate your height using. This will allow your UITableView to only become scrollable once the total height exceeds your screen bounds.
//dataArray = array of your data source
tableViewHeightConstraint.constant = dataArray.count * rowHeight;
Now this height constraint will break as soon as the UITableView becomes scrollable so if you are adding the ability to delete the rows, you will have to create a new height constraint to the UITableViewas soon the number of rows of doesn't take up the entire screen bounds and update the new height constraint appropriately.
You can do using UITableView's content size property .
[tableView reloadData]; // you need to reload data first before set frame
tableView.frame =CGRectMake(tableView.frame.origin.x,tableView.frame.origin.x, tableView.frame.size.width, tableView.contentSize.height);
I'm hiding rows that are completed in a collectionView.
I call cell.hidden = isCellHidden in cellForItemAtIndexPath when needed.
After I hide 10 rows there is plenty of empty space left and I'd like to trim down the size of the collectionView to only fit the rows that are not hidden.
The collectionView's design is kind of like a tableView.
I know with the tableView all I had to do to achieve this is set:
func section1VisibilityButton(sender: UIButton){
isCellHidden = !isCellHidden
self.tableView.reloadData()
self.tableView.contentSize.height = CGFloat(500)
}
with a collectionView when I try this it will resize it correctly but as soon as I try to scroll down it resizes itself back to the original height including the cells hidden (the cells layer is still hidden but there's tons of empty space bellow the last visible row as if they were visible)
For your issue, there are two options to change the frame of your collectionView/tableView.
If you are using autolayout, you need to create IBOutlet of bottom constraint or IBOutlet of constant height constraint of your tableView (anyone of these constraints, which you are using).
After reload tableView data you need to update constraint by calculating its height.
Suppose you are using constant height constraint and your calculated height is 150(e.g. 3 rows and 50 height of each row).
constraintTableViewHeight.constant = 150;//this will change height
self.view.layoutIfneed(); // this will apply updated constraints to whole view
If you are not using autolayout, you can manually change the height by changing tableView.frame property.