Skip to content
This repository has been archived by the owner on Nov 27, 2022. It is now read-only.

Collapsible Header With Tab View #1079

Closed

Conversation

jehartzog
Copy link

@jehartzog jehartzog commented Sep 26, 2020

Motivation

The UI of having a collapsible header above a Tab View is a commonly requested pattern (#411), but it is surprisingly challenging for newer RN devs to implement. Creating a wrapper for this functionality and some examples for using the wrapper will help allow them to have a baseline for how to add this pattern into their own apps.

Prior Examples

@satya164 Provided https://snack.expo.io/@satya164/collapsible-header-with-tabview as an example. It's a valuable start for understanding how to work on this, but the snack itself can't be used without significant additional work due to the additional of large amounts of padding above the content when switching tabs in certain cases #441.

This example appears to be complete, but it's a rather larger example that is challenging to quickly bring into a different projects that just wants the minimum code needed to reproduce the baseline effect.

@JungHsuan Provided a medium article on his approach, which was practically production ready and had the exact UI flow that was buttery smooth and consistent in all cases. I started with this approach, and converted it into something more re-usable in different situations, trying to make it quicker for other developers to pull into their projects.

UI Animation

Sep-26-2020 13-36-27

Current known limitations/issues

  1. Since the collapsible header view becomes absolutely positioned and is animated, you'll need to adjust zIndex of the headers above it (see example code)

  2. In order to support scrolling the TabBar up, we must set a minimum height for the scrollable content. If you have one tab with only a small amount of content in there, it will be allowed to scroll up with large padding below it. This maybe be possible fix via measuring the content, but that would be an enhancement. Edit: Discussed possible fix here.

  3. The CollapsibleHeader prop structure I initially proposed may not be ideal. It basically forces use to create an array of renderItem and data, which is used by each tab separately to draw its content. But the idea behind this even for non-virtualized content, we need a ScrollView or FlatList wrapper in there to drive this behavior, so we want to bake this functionality into the wrapper while still making implementation lightweight. This also has the side effect of fully supporting both tab content that are rendered at once, or using FlatList virtualized rendering.

  4. I attempted to use SectionList to drive this, but challenges with measuring scroll distances shut down my early attempts.

  5. If you scroll tab 1 all the way down, swap to tab 2, scroll it up any amount, and come back to tab 1, you'll notice tab 1 is now at the top, with the collapsible header being set at the same height. This isn't a real 'limitation' as it's simply necessary for the UI to be smooth, but it's good to be aware of.

Test plan

This is an early draft version of the PR. I am submitting in this state to see if there is interest in me polishing it up.

TODO's:

  • Stricter typings (I used any in many places where it can be better typed)
  • Removal of inline functions
  • Adding example of correctly using underlying FlatList
  • There is some warning spam right now that needs to be cleaned up

@satya164 satya164 changed the base branch from master to main October 7, 2020 08:23
@hejun041
Copy link

hejun041 commented Oct 15, 2020

When the header's height > screen height or i want to handle the header, it cant work
because the header cant scroll

@zyslife
Copy link

zyslife commented Nov 2, 2020

@jehartzog @hejun041 @sagrawalcb @sjmueller @fantattitude
You can try the react-native-head-tab-view.
(tabs with collapsible header)

@jehartzog
Copy link
Author

@zyslife Thanks for putting that together. In this case, I'm hoping to add the functionality as an optional inclusion to react-native-tab-view as I think that will help the larger base of devs who already use react-native-tab-view in their RN project and what to support this behavior.

Is there any interest in merging this in? I'm still happy to clean this up some more, write docs, but I've learned to wait until I hear back from maintainers.

@alexco2
Copy link

alexco2 commented Nov 2, 2020

I´m trying to implement this solution with SectionList right now. Regarding the limitations of point 4, are you referring to the fact that the only scrollTo function that is supportted in sectionList is the scrollToLocation one?

@jehartzog
Copy link
Author

@alexco2 Yes, that is what I saw. I only looked for ~10 minutes into it, as I suspected the scrollToLocation would be more complicated due to being dependent on what kind of data was added. I didn't really look into it deeply though.

@alexco2
Copy link

alexco2 commented Nov 2, 2020

@jehartzog scrollToLocation expects itemIndex and sectionIndex. Both can be set to 0 though. With viewOffset you can then control the scrolling position with the use of pixel like in your example with the flatlist. Two problems then came up.

First, if the sectionlist of the inactive route doesn´t have enough rows so that the header can not be completely collapsed, the function syncScrollOffset somehow updates the header of the active route with the amount of translateY the inactive route can be scrolled with. So, if the active route was scrolled with 50 pixel but the inactive route can just be scrolled 5 pixel because of to little rows, the active collapsible header gets updated with a translateY value of 5. My workaround is to dynamically extend a listfooter so that the list can alwas be scrolled to collapse the header completly.

Also, if the inactive route does not have any data in it, the scrollToLocation function throws an out of bounds error because the itemIndex = 0 and sectionIndex = 0 do not exist. Weirdly using -1 each does not fix this. My workaround is to just deactivate the second route if there is no data, since it does not have any information for the user anyways.

@zyslife
Copy link

zyslife commented Nov 3, 2020

@zyslife Thanks for putting that together. In this case, I'm hoping to add the functionality as an optional inclusion to react-native-tab-view as I think that will help the larger base of devs who already use react-native-tab-view in their RN project and what to support this behavior.

Is there any interest in merging this in? I'm still happy to clean this up some more, write docs, but I've learned to wait until I hear back from maintainers.

Thanks for your invitation,If I have enough energy, I should be able to react-native-tab-view add this feature. But not right now. I can only make react-native- head-tab-View work right now ,out of my working hours. I hope I can do something in the future.

@PedroBern
Copy link

Hi folks I'm coming late to the conversation but was also working on this, I've just made a PR, let me know if you guys see how to improve it :)

@jehartzog
Copy link
Author

We've been using the code based on this PR successfully in our prod app for a while, but going forward I'd probably pickup the outside packages published by #1096 rather than continue to maintain our fork. Just throwing this in for anyone looking to add these features.

On the other hand, repo owners decide they want to pull in this PR, I will be happy to spend the time to clean it up, get it back up to date, and get it merged. Just need someone w/ review authority to give thumbs up or down.

@alantoa
Copy link

alantoa commented Jul 9, 2021

@jehartzog thanks for you solve my issue!!

@KrisLau
Copy link

KrisLau commented Aug 8, 2022

On the other hand, repo owners decide they want to pull in this PR, I will be happy to spend the time to clean it up, get it back up to date, and get it merged. Just need someone w/ review authority to give thumbs up or down.

@satya164

@okwasniewski
Copy link
Collaborator

After consulting this with @satya164 we decided that we want to keep the library as small as possible (and easy to maintain) so I suggest you to publish this as a separate library.

@KrisLau
Copy link

KrisLau commented Aug 31, 2022

@okwasniewski Would this feature be a huge increase in size to the library? This feature would be extremely useful but i definitely understand the reasoning haha

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Tabs With Different height. Extra space in the shorter tab
9 participants