I have complex view that contains Image slider(collectionView),List of offers(tableView) and List of Services (TableView), The main Content View should be scrollable and all subviews should not be scrollable.
I tried to make the parent view UIScrollView but i got a problem that when the first tableview items exceeds the screen limit its not showing the exceeded elements.
I tried also to force full tableview height but i had a problem with scrolling
self.tableView.frame.size = CGSize(width: self.tableView.contentSize.width,
height: self.tableView.contentSize.height)
Is there a way to force showing all the tableview elements ,or should i use another type than UIScrollView?
Here is an image for what i want to display
For this you need to disable your UITableview scroll like:
tableView.scrollEnabled = false
then all you need to get count of tableview element multiply it by the height of your tableview cell and set that height to tableview like:
tableViewHeight.constant = count * z
Where z is height of tableview cell.
All set now.
I'm trying to give a tableView and searchBar (tableView.tableHeaderView = searchBar) the same behavior as in the Messages and Mail apps i.e. hide the searchBar off the top of the parent view and scroll to show it.
The problem is the search bar is shown/hidden differently when the tableView has a different number of cells. How do I hide the search bar every time?
Not enough cells to fill the view
Just enough cells to fill the view
More than enough cells to fill the view
The method I'm using is tableView.scrollToRow(at: IndexPath(row: 0, section: 0), at: .top, animated: true)
IMPORTANT: My problem is not that I'm implementing didDeelectRowAt instead of didSelectRowAt. Already checked that :)
I have a UITableView that is shown on part of the screen in a modally presented view controller. When the user is dragging it resizes to full screen and back to some defined min height. I'm doing this by implementing the following methods from the UIScrollViewDelegate:
func scrollViewDidScroll(_ scrollView: UIScrollView) {
guard !scrollView.isDecelerating else { return }
let contentOffset = scrollView.contentOffset.y
if tableViewHeightConstraint.constant < view.frame.height && contentOffset > 0.0 {
tableViewHeightConstraint.constant = min(contentOffset + tableViewHeightConstraint.constant, view.frame.height)
scrollView.contentOffset.y = 0.0
return
}
if tableViewHeightConstraint.constant > minViewHeight && contentOffset < 0.0 {
tableViewHeightConstraint.constant = max(tableViewHeightConstraint.constant + contentOffset, minViewHeight)
scrollView.contentOffset.y = 0.0
}
}
func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) {
// Here I have some calculations if depending the dragging end position and the velocity the end size should be full screen or `minViewHeight`
// After calculating what the end size should be I'm animating the size change
heightConstraint.constant = newConstraintHeight
UIView.animate(withDuration: TimeInterval(calculatedAnimationDuration), delay: 0.0, options: .curveEaseOut, animations: {
self.view.layoutIfNeeded()
}, completion: nil)
}
Everything about the resizing and the scrolling works fine, but there is a problem that I cannot figure out why it's happening. It's the following:
When the view controller with the table view is shown for the first time with the min height and I tap on a cell it works fine.
If I drag to expand the table view to full screen height and tap on a cell, again it works fine.
If I drag to expand the table view to full screen height and then drag again to return it to the min height and then tap on a cell, nothing is happening, no UIScrollViewDelegate or UITableViewDelegate method is called at all. If I tap once more on a cell everything works fine.
One thing that I noticed is that after dragging the table view back to the min height the scroll indicator does not hide. On the first tap it hides, and on the second tap the didSelectRowAt is called.
UPDATE:
Here is a test repo for the problem: https://github.com/nikmin/DragTest
Please don't mind if the dragging doesn't work perfectly, I just put something so anyone can try it out, but I think the problem is easily reproducible.
Also one more thing... If you drag from full size all the way to the bottom so the table view reaches min height and you continue dragging so the content offset is < 0 and the you release, the problem is not happening.
Drag TableView to return it to the min height and then tap on a cell, nothing is happening because:
When you drag to expand the table view to full screen, scrollView.isDecelerating is true. So the code inside scrollViewDidScroll method will run.
But when you drag TableView to return it to the min height, scrollViewDidScroll is false. So the code inside scrollViewDidScroll method won't run. It's make the first tap do nothing.
Simply remove guard !scrollView.isDecelerating else { return } from scrollViewDidScroll. You will tap cell normally after drag TableView down.
But you need change logic a little, animation will go wrong after remove above line.
Hope it can help you ;)
After trying to figure out a solution to this without result, we (me and a UX designer) decided to change the behaviour a bit.
So in the real scenario in the app I'm implementing this in, the table view is inside another view that has also a title label and some other views above the table view. We decided to add a pan gesture recognizer to this root view and disable the scrolling of the table view when the view has the min size. This way the pan gesture recognizer will take over whenever the user tries to drag anywhere inside the view (including the table view), so the expanding of the view works. And the tap in the cell still works.
When the view has the max height the table view scroll is enabled so the user can scroll. The downside of this approach is that when the user scrolls to the top of the table view and continues scrolling the view will not decrease the size. But he still has the option to drag it down by dragging any of the views above the table view. When dragging down in this way, only the size of the table view changes, and the content offset isn't, which is the root of the problem (changing both at the same time).
It looks like incorrectly set content offset. The first touch cancels incorrect position(unscroll), this is why it is not registered. It might be better if we got an access to the full code to check it, because I can't tell you where exactly the problem lies, but I guess it is in method scrollViewDidScroll.
I have a UITableView that should show a particular row in its middle when it is first displayed. In viewDidLoad, I use scrollToRowAtIndexPath to achieve this:
// Center vertically on current row
let scrollIndexPath = NSIndexPath(forRow: currentRow, inSection: 0)
tableView.scrollToRowAtIndexPath(scrollIndexPath, atScrollPosition: UITableViewScrollPosition.Middle, animated: false)
This makes the top of the current row aligned with the middle of the table view meaning that the content of the row looks lower than it should be. How can I make the middle of the row align with the middle of the table view?
UITableView is a subclass of UIScrollView so you can use:
scrollRectToVisible:<#(CGRect)#> animated:<#(BOOL)#>
and calculate CGRect yourself, this way you have way more control than with using:
scrollToRowAtIndexPath
I'm looking to expand the height of the top cell in my collectionview with animation. The problem is when I detect a tap on the cell, I try animating the height and set the new height in the delegate: - collectionView:layout:sizeForItemAtIndexPath:indexPath. The issue I see an instant refresh after invalidating my collection flow layout and the animation happens afterwords. The effect I want is for the top cell to animate the expansion to the new height and push the rows beneath it along with the animation.
I'm only using one section with multiple rows. Should I try to use two sections and put the top cell in the first section and the remaining in the second section? Could I then animate the second section along with the height of the first section?
You need to do this three steps:
1.Invalidate your collectionViewLayout
self.collectionView.collectionViewLayout.invalidateLayout()
2.Reload desired indexPath or all the data inside a performBatchUpdates block
collectionView.performBatchUpdates({
self.collectionView.reload(at: DESIRED_INDEXPATH)
}, completion: nil)
3.Return the new height calculated in sizeForItemAtIndexpath delegate method