React Native UI Component for ViewPager with TabLayout design pattern in Android

Madhu
4 min readMar 17, 2017

--

ViewPager w/ TabLayout in action.

Tab based swiping is a common pattern in Android. We were recently working on a grocery store application; our Android design included tabs to show multiple sub categories of a category. For example category food would have beverages, breakfast cereals, ready to eat, ready to cook, staples , etc., as sub categories. On an average there were about at least 5 sub categories for a given category.

We are using ReactNative to build our grocery store application. There are many open source libraries out there which provide RN components to implement tab pattern.

One of the most popular of these libraries is react-native-scrollable-tab-view. It's a pure javascript implementation. The behaviour comes very close to material design pattern and has extensive props to gain complete control. The library started showing performance issues when complexity of our networking code and db queries increased. Since it was a pure JS implementation, there were latencies communicating touch interactions across the bridge and user experience suffered.

Another approach we have used is to pair native ViewPagerAndroid that is part of RN framework itself with react-native-android-tab-layout library. This was much better than the first approach and also felt more native as both the widgets involved had native implementation. There were two problems we have identified. First, the movement of tab strip was not synchronised with ViewPager’s swiping. Tab strip would animate to selected tab only after ViewPager’s swipe completed. Second, when the bridge is busy with networking/db query code, the communication code between ViewPager and TabLayout suffered latency issues.

So to address above mentioned concerns, we have decided to build a component on native side that would wrap both ViewPager and TabLayout into a single component so that all the communication between those two components is handled on native side and bridge does not become bottleneck. The result was react-native-tabbed-view-pager-android.

Implementation

Coming from a strong Android background, I knew that this should be a simple exercise because TabLayout view already has a very handy setupWithViewPager method. In the process of writing this component I wanted to ensure that I retain all the properties of ViewPagerAndroid and make sure that tabs is just a decorative component on top of it. Here is what I have done

  1. Pull sources from react-native’s ViewPager implementation. Override implementations for pager adapters page title method. Change event dispatch callbacks to parent id instead of view id.

2. Create a LinearLayout with TabLayout view and ReactViewPager view.

3. Expose #2 as native view module and delegate all ViewPager props to ReactViewPager.

Provide all tab based properties with ReactProp annotated methods in the view manager class and we are done. Currently the library only supports text based tabs, as that is common pattern for tabs exceeding count of 5.

Here is the final usage that you will see in JSX

import TabbedViewPager from 'react-native-tabbed-view-pager-android';

<TabbedViewPager
tabMode={"scrollable"}
tabGravity={"center"}
tabBackground={"#008B7D"}
tabIndicatorColor={"#FFB90B"}
tabIndicatorHeight={4}
tabTextColor={"#ffffffa0"}
tabSelectedTextColor={"#ffffff"}
tabElevation={4}
tabNames={this.state.tabNames}
style={styles.viewPager}
initialPage={0}
onPageSelected={(event) => this.onPageSelected(event.nativeEvent.position)}
onPageScrollStateChanged={(state) => this.onPageScrollStateChanged(state)}
onPageScroll={(event) => this.onPageScroll(event.nativeEvent)}>
{
this.state.tabNames.map((tabName) => {
return(
<View style={styles.pageStyle} key={tabName}>
<Text>{tabName}</Text>
</View>
)
})
}
</TabbedViewPager>

Head to react-native-tabbed-view-pager-android for detailed instructions on installation and usage. Feel free to raise issues or send PRs.

Although not very fully featured as libraries mentioned in the beginning of the post, this library solves the most common use-case with view pagers on Android in the most performant manner.

Want to work together?

Looking for an experienced team to help you with your next big idea? We love creating beautiful, performant mobile applications. Simply write to us at hello@uncommon.is.

--

--