Skip to content

Commit

Permalink
feat: scroll on header
Browse files Browse the repository at this point in the history
related: #28
  • Loading branch information
PedroBern authored Dec 29, 2020
1 parent 08c079f commit e02660f
Show file tree
Hide file tree
Showing 4 changed files with 116 additions and 5 deletions.
13 changes: 12 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
- [Features](#features)
- [Installation](#installation)
- [Quick Start](#quick-start)
- [Scroll on header](#scroll-on-header)
- [API reference](#api-reference)
- [CollapsibleTabView](#collapsibletabview)
- [useCollapsibleScene](#usecollapsiblescene)
Expand Down Expand Up @@ -120,8 +121,10 @@ const SecondScene = () => <SomeRoute routeKey="second" color="black" />;

const HEADER_HEIGHT = 250;

// set pointerEvents="none" to allow scroll on header
// see the docs for more information
const renderHeader = () => (
<View style={styles.header}>
<View pointerEvents="none" style={styles.header}>
<Text style={styles.headerText}>COLLAPSIBLE</Text>
</View>
);
Expand Down Expand Up @@ -194,6 +197,14 @@ const styles = StyleSheet.create({
export default WithReactNavigation;
```

## Scroll on header

If you want to allow scrolling from the header:

- If `renderHeader` **doesn't** contain touchables set `pointerEvents='none'`
- If `renderHeader` **does** contain touchables set `pointerEvents='box-none'` for them to work.
_Note: With this setting any child component that should **not** respond to touches (e.g. `<Image />`) needs to have `pointerEvents` set to `'none'`. Otherwise it can become the target of a touch gesture on iOS devices and thereby preventing scrolling._

## API reference

The package has 3 main exports:
Expand Down
5 changes: 2 additions & 3 deletions example/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import {
Text,
TouchableOpacity,
View,
YellowBox,
I18nManager,
} from 'react-native';
import { registerRootComponent } from 'expo';
Expand All @@ -18,6 +17,7 @@ import Constants from 'expo-constants';
import { Ionicons } from '@expo/vector-icons';
import AsyncStorage from '@react-native-community/async-storage';
import CollapsibleTabViewExample from './CollapsibleTabViewExample';
import CollapsibleTabViewScrollOnHeaderExample from './CollapsibleTabViewScrollOnHeaderExample';
import CollapsibleTabViewSmallContentExample from './CollapsibleTabViewSmallContentExample';
import CollapsibleTabViewNoSnapExample from './CollapsibleTabViewNoSnapExample';
import CollapsibleTabViewResizeExample from './CollapsibleTabViewResizeExample';
Expand All @@ -35,8 +35,6 @@ type State = {

I18nManager.forceRTL(false);

YellowBox.ignoreWarnings(['bind():']);

const PERSISTENCE_KEY = 'index_persistence';

const EXAMPLE_COMPONENTS: ExampleComponentType[] = [
Expand All @@ -48,6 +46,7 @@ const EXAMPLE_COMPONENTS: ExampleComponentType[] = [
CollapsibleTabViewNoUpfrontHeightExample,
MaterialTopTabsCollapsibleTabViewDemoExample,
CollapsibleTabViewCenteredEmptyListExample,
CollapsibleTabViewScrollOnHeaderExample,
];

const KeepAwake = () => {
Expand Down
101 changes: 101 additions & 0 deletions example/src/CollapsibleTabViewScrollOnHeaderExample.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
import * as React from 'react';
import { StyleSheet, View, Text } from 'react-native';
import { SceneMap } from 'react-native-tab-view';

import {
CollapsibleTabView,
useCollapsibleScene,
CollapsibleTabViewProps,
} from 'react-native-collapsible-tab-view';

import { AnimatedAlbums } from './Shared/Albums';
import { AnimatedArticle } from './Shared/Article';
import { AnimatedContacts } from './Shared/Contacts';
import { ExampleComponentType } from './types';

type Route = {
key: string;
title: string;
};

export const ContactsScene = () => {
const scenePropsAndRef = useCollapsibleScene('contacts');
return <AnimatedContacts {...scenePropsAndRef} />;
};

export const ArticleScene = () => {
const scenePropsAndRef = useCollapsibleScene('article');
return <AnimatedArticle {...scenePropsAndRef} />;
};

export const AlbumsScene = () => {
const scenePropsAndRef = useCollapsibleScene('albums');
return <AnimatedAlbums {...scenePropsAndRef} />;
};

export const HEADER_HEIGHT = 550;

const renderHeader = () => (
<View pointerEvents="none" style={styles.header}>
<Text style={styles.headerText}>
You can set pointerEvents=&quot;none&quot; | &quot;box-none&quot; to allow
scrolling on the header. It works as expected, but you can also consider
using disableSnap if your header is too large (like in this example).
</Text>
</View>
);

const renderScene = SceneMap({
albums: AlbumsScene,
contacts: ContactsScene,
article: ArticleScene,
});

const CollapsibleTabViewExample: ExampleComponentType<Partial<
Partial<CollapsibleTabViewProps<Route>>
>> = (props) => {
const [index, setIndex] = React.useState(0);
const [routes] = React.useState<Route[]>([
{ key: 'article', title: 'Article' },
{ key: 'contacts', title: 'Contacts' },
{ key: 'albums', title: 'Albums' },
]);

const handleIndexChange = (index: number) => {
setIndex(index);
};

return (
<CollapsibleTabView<Route>
navigationState={{ index, routes }}
renderScene={renderScene}
onIndexChange={handleIndexChange}
renderHeader={renderHeader}
headerHeight={HEADER_HEIGHT}
disableSnap
{...props}
/>
);
};

CollapsibleTabViewExample.title = 'Scroll on header';
CollapsibleTabViewExample.backgroundColor = '#2196f3';
CollapsibleTabViewExample.appbarElevation = 0;

export default CollapsibleTabViewExample;

const styles = StyleSheet.create({
header: {
height: HEADER_HEIGHT,
backgroundColor: '#2196f3',
justifyContent: 'center',
alignItems: 'center',
elevation: 4,
},
headerText: {
color: 'white',
fontSize: 18,
padding: 16,
textAlign: 'center',
},
});
2 changes: 1 addition & 1 deletion src/CollapsibleTabView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,6 @@ const CollapsibleTabView = <T extends Route>({
offset,
animated: false,
});

listOffset.current[item.key] = offset;
} else if (itemOffset < headerHeight || !itemOffset) {
scrollScene({
Expand Down Expand Up @@ -354,6 +353,7 @@ const CollapsibleTabView = <T extends Route>({
): React.ReactNode => {
return (
<Animated.View
pointerEvents="box-none"
style={[
styles.headerContainer,
{ transform: [{ translateY }] },
Expand Down

0 comments on commit e02660f

Please sign in to comment.