Swift UITableView: How to remove space under the last cell - ios

I have a normal UITableView with two cells. Every cell has a height of view.frame.size.height - 250 in the heighForRowAt method.
But under the last cell a white space appears. Look:
But I would like that it is like that:
Does anyone know how to do this?
Warm greetings
PS: The bottom constraint of my tableview is 0 = superview

Add tableview bottom constraint with superview rather than with Safe Area.
The issue is because of tableview bottom constraint with Safe Area.

Related

Resize ScrollView based on TableView size

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

iOS - Move TableView before scrolling

I have a view with an image and a tableview. The image is in the first half of the screen (portrait) and the tableview in the second half. And now I want to move the tableview over the image until it reaches the top and covers the image. Then it should start the "real scrolling".
But what's the best way to do this? Can I like replace the touchesMove of the variable tableView? I could create an extension of the UITableView and override the function, but then I don't have access to the view of my Controller to move the tableView.
Any answer? Thanks!
The imageView should be behind the tableView with constraints top, leading, trailing to superview and height to superview with a multiplier of 0.5. The tableView should fill its superview.
The trick is that you add a tableViewHeader that is invisible and equal to half the height of the screen. This has the effect of pushing the initial content of the tableView off the screen. In interface builder add a UIView to the tableView as header and make it transparent. Also make the background of your tableView transparent. Take an outlet to the headerView and the tableView. In viewDidLayoutSubviews set your headerView.frame.size.height = tableView.frame.size.height / 2.
Apart from what Josh answered, what you can try is:
What you can do is make the UIImageView's height decrease based on the scroll amount until the UIImageView's height is 0 and then start the scrolling otherwise force the contentOffSet of the UITableView to always remain 0. That being said, here is how to do it:
Make an enum to keep track of the various states of the UIImageView like:
enum Layout {
case ImageExpanding,
case ImageDefaultHeight,
case ImageDiminishing,
case ImageNotVisible
}
In your storyboard, add a top, leading and trailing constraint to the superview for your UIImageView and fixed height constraint of lets say 200(don't worry you will change this later). To your UITableView add a leading, trailing and bottom constraint to the superview and a top the UIImageView. Now drag and drop a constraint outlet for the UIImageView height into your UIViewController.
In your viewDidLoad set your heightConstraint to be 1/2 of the total screen height and set the enum state to initially be ImageDefaultHeight
Now in your scrollViewDidScroll you will have to check the direction of the scroll and based on that while checking the current state of the image, increase or decrease the heightConstraint based on the amount a user scrolls by and always check:
func scrollViewDidScroll(_ scrollView: UIScrollView) {
if(/*up*/){
//just telling you about this if condition as this will ensure that
//if your table view is large and if tableview isn't at the top,
//the image shouldn't expand
if layout == .ImageNotVisible{
if scrollView.contentOffset.y <= 0 {
//start expanding once you reach top of tableview
layout = .ImageExpanding;
}
}
//keep track of other enum states and update your uiimageview
//appropriately after calculating the user scroll amount
//until the height reaches your initialDefaultHeight and
//then do nothing. You will have to figure out the code
//for this on your own
}else if(/*down*/){
//make image smaller
}
//dont let table view scroll until image height is 0 when use is scrolling down
if layout != ImageNotVisible{
scrollView.contentOffset = CGPoint(x: 0, y: 0)
}
}

How to Add Margin Between UITableViewCells Without Being Hacky

A lot of the solutions I've seen here include changing the cell's background to an image and using sections for rows rather than just rows themselves. I'm looking to have only two sections and have each cell expand in height on tap, so neither of those solutions would work.
I saw one solution includes setting the frame of the cell in the layoutSubviews() function like so:
override func layoutSubviews() {
super.layoutSubviews()
self.frame = CGRectOffset(self.frame, 0, 10);
}
When I do this however, it only gives margin to one cell and that's only when I tap on the cell.
Is there a surefire way to add spacing in between UITableViewCells without being hacky and breaking the cell layouts in the process?
I did this yesterday pretty easily with auto layout.
I set the background of the cell and it's content view to clear, then I created a new view and setup constraints all around it and put my labels inside of it. The height changes dynamically based on the label so I needed to use UITableViewAutomaticDimension for the row height and give it an estimated row height as well.
I don't see why this wouldn't work for expanding it on a tap as well, you just might have to reload the cell.
make the cell and it's contentView transparent
contentView addSubview customContentView and layout your cell on customContentView
customContentView pin to contentView top leading trailing with offset 0 but pin to bottom with offset 10 //the margin height

How to manually change UICollectionView height in Swift

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.

keep TextLabel for tableviewcell at top

I am using UITableView in my project. i am increasing and decreasing the height of UITableView cell on the continuous taps. In other words i am toggling the height of UITableViewCell on taps. Now i want to keep the UITableViewCell textLabel at the same place which is at the top. But when i increase the height of UITableViewCell the textLabel come in the middle of the cell.
To avoid this is am using sizeToFit for cell.textLabel but it not working... any help...
The easiest way to do this is add Auto-Layout constraints to the default TextLabel programmatically. I would pin it from the leading edge, trailing edge, and bottom edge of the Superview (in this case being the cell).
try
label.autoresizingMask = UIViewAutoresizingFlexibleBottomMargin;
and don't do the size to fit. What this will do is change the distance from the bottom of your label to the bottom of the cell. In other words, it will keep the distance from the top constant.

Resources