Collapse/Expand HeaderView With Tabs Part 2

yusef naser
SwiftCairo
Published in
4 min readMay 17, 2020

In the previous part
https://medium.com/@yusefnaser93_79870/collapse-expand-headerview-with-tabs-part1-3fbad61d9028
We created Collapse/Expand header with two tabs

In this article, we will see some cases with bugs and how to solve it.
Let’s get started:

Case 1:

in the first tab, if scroll to bottom and go to the second tab, then scroll to top then return to the first tab and try to scroll to top
you can see the height of the header is changed like this:

We can solve this problem by set contentOffSet of scrollView to zero when trying to select the cell

in the function “cellForItemAt” for cell CellScrollView add this code

cell.scrollView.setContentOffset(.zero , animated: false )

and for cell CellTableView add this code

cell.tableView.setContentOffset(.zero , animated: false )

Now you can see when selecting every cell, scrollView start from the top and that is it 🤩🥳

Case 2:

If you remove second, third, fourth views from scrollView in cell and run the app, the scroll is not working because the height of the container in scrollView is less than the height of scrollView, so to solve this bug we will do two things.
1- we must set the height of the container in scrollView is more than the height of scrollView
2- set a bottom constraint for the last view in the container is less than or equal -50 (for example).

if you see the figure (A) we set the bottom Anchor is less than or equal -50, so it’s work fine,
but if you see figure (B) and when we add more views into the container, the bottom anchor become -50 and height of the container is increasing

Note:

if you design coding you use positive value when you set [leading, top] and
a negative value when you set[trailing, bottom], and if you design using storyboard, you use a positive value only

Let’s do it in our project.
First remove second, third, fourth views from the stack in cell and
In cell “CellScrollView”, inside scrollView Block we will add this line:

containerView.heightAnchor.constraint(greaterThanOrEqualTo: s.heightAnchor , multiplier: 1.01).isActive = true

this makes the height of the container in scrollView is greater than the scrollView by multiplier 1.01.

and replace this constraint for stackView :

stackViews.bottomAnchor.constraint(equalTo: containerView.bottomAnchor , constant: -8 ).isActive = true

to this line:

stackViews.bottomAnchor.constraint(lessThanOrEqualTo: containerView.bottomAnchor , constant: -8).isActive = true

this makes the bottom constraint is less than or equal -8

When you run the app you can see the scrollView become scrollable.
And that is it. 🤩🥳💪

Case 3:

When the height of cells in tableView is less than the hight of tableView and trying to scroll to collapse header, you can see tableView scroll is unsmooth scrollable.
to try to see this bug you just set the number of cells equal 5 for tableView.

To fix this bug we need to create custom TableView and use it in the cell instead of UITableView.

import UIKit
class CustomTableView : UITableView {
override var adjustedContentInset: UIEdgeInsets {
if self.frame.height > contentSize.height {
let heightBottom =
( self.frame.height - contentSize.height ) + 0.5
return UIEdgeInsets(
top: self.contentInset.top + 0.5 ,
left: self.contentInset.left ,
bottom: heightBottom ,
right: self.contentInset.right )
}
return UIEdgeInsets(
top: self.contentInset.top + 0.5 ,
left: self.contentInset.left ,
bottom: self.contentInset.right ,
right: self.contentInset.right )
}
}

the solution is similar to Bug2, we check if the height of tableView is greater than the height of the contentSize then set bottom padding to make it scrollable and if you run the app you can see.

Case 4:

You can collapse header by scrolling scrollView or tableView but you can’t by gesture on viewHeader, so we will add panGesture on view to allow scrolling.
first thing we need to take object from viewHeader

@IBOutlet weak var viewHeader: UIView!

in viewDidLoad function add panGesture on viewheader

viewHeader.isUserInteractionEnabled = true
viewHeader.addGestureRecognizer(UIPanGestureRecognizer(target: self , action: #selector(handlePanGesture(_:))))

we need to implement the function handlePanGesture(_:)

@objc private func handlePanGesture (_ gesture : UIPanGestureRecognizer ) {
let translation = gesture.translation(in: viewHeader)
gesture.setTranslation(CGPoint(x: translation.x , y: 0.0), in:
viewHeader )
if translation.y > 0 &&
heightView.constant == headerViewMaxHeight {
return
}
if translation.y < 0 &&
heightView.constant == headerViewMinHeight {
return
}
if let cell = collectionView.visibleCells.first as?
CellScrollView {
cell.scrollView.contentOffset.y =
cell.scrollView.contentOffset.y - translation.y
}else if let cell = collectionView.visibleCells.first as?
CellTableView {
cell.tableView.contentOffset.y =
cell.tableView.contentOffset.y - translation.y
}
}

Case 5 :

this bug is for RTL direction and we fixed it by add function
flipsHorizontallyInOppositeLayoutDirection in our custom flowLayout
Thanks for Abdoelrhman Mohamed for article

Thanks for Reading, Tap the 👏 button if you found this article useful!

Sources code

Follow Me :
Twitter
Linkedin

--

--