Giter Site home page Giter Site logo

eric013 / react-native-collapsible-tab-view Goto Github PK

View Code? Open in Web Editor NEW

This project forked from pedrobern/react-native-collapsible-tab-view

0.0 2.0 0.0 81.66 MB

A cross-platform Collapsible Tab View component for React Native

License: MIT License

JavaScript 1.70% TypeScript 98.30%

react-native-collapsible-tab-view's Introduction

react-native-collapsible-tab-view

Downloads Build Status Version MIT License runs with expo

Expo app

If you are looking for the integration with react-native-tab-view and/or react-navigation, you need to use the v2.

Collapsible Tab View for React Native, with Reanimated.

Credits

The react-native-tab-view example app was used as template for the demos.

Demo

Default Snap revealHeaderOnScroll revealHeaderOnScroll + Snap

Features

  • Animations and interactions on the UI thread
  • Highly customizable
  • Fully typed with TypeScript
  • Lazy support with fade-in animation
  • DiffClamp header
  • Interpolated header
  • Scroll snap (with interpolated header)
  • Animated snap (with diffClamp header)
  • Scrollable tabs, inspired by the react-native-tab-view tab bar
  • Support horizontal and vertical window

Installation

Open a Terminal in the project root and run:

yarn add react-native-collapsible-tab-view@next

Then, add Reanimated v2, follow the official installation guide.

Quick Start

import React from 'react'
import { View, StyleSheet, ListRenderItem } from 'react-native'
import { Tabs } from 'react-native-collapsible-tab-view'

const HEADER_HEIGHT = 250

const Header = () => {
  return <View style={styles.header} />
}

const Example: React.FC = () => {
  const renderItem: ListRenderItem<number> = React.useCallback(({ index }) => {
    return (
      <View style={[styles.box, index % 2 === 0 ? styles.boxB : styles.boxA]} />
    )
  }, [])

  return (
    <Tabs.Container
      renderHeader={Header}
      headerHeight={HEADER_HEIGHT} // optional
    >
      <Tabs.Tab name="A">
        <Tabs.FlatList
          data={[0, 1, 2, 3, 4]}
          renderItem={renderItem}
          keyExtractor={(v) => v + ''}
        />
      </Tabs.Tab>
      <Tabs.Tab name="B">
        <Tabs.ScrollView>
          <View style={[styles.box, styles.boxA]} />
          <View style={[styles.box, styles.boxB]} />
        </Tabs.ScrollView>
      </Tabs.Tab>
    </Tabs.Container>
  )
}

const styles = StyleSheet.create({
  box: {
    height: 250,
    width: '100%',
  },
  boxA: {
    backgroundColor: 'white',
  },
  boxB: {
    backgroundColor: '#D8D8D8',
  },
  header: {
    height: HEADER_HEIGHT,
    width: '100%',
    backgroundColor: '#2196f3',
  },
})

export default Example

Guides

Scroll on header

If you want to allow scrolling from the header:

  • If the HeaderComponent doesn't contain touchables set pointerEvents='none'

  • If HeaderComponent 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

Core

Tabs.Container

Basic usage looks like this:

import { Tabs } from 'react-native-collapsible-tab-view'

const Example = () => {
   return (
     <Tabs.Container renderHeader={MyHeader}>
       <Tabs.Tab name="A">
         <ScreenA />
       </Tabs.Tab>
       <Tabs.Tab name="B">
         <ScreenB />
       </Tabs.Tab>
     </Tabs.Container>
   )
}

Props

name type default description
HeaderComponent ((props: TabBarProps<T>) => React.ReactElement) | null | undefined @obsolete use renderHeader instead. This property will be removed in 5.0.0
TabBarComponent ((props: TabBarProps<T>) => React.ReactElement) | null | undefined MaterialTabBar @obsolete use renderTabBar instead. This property will be removed in 5.0.0
cancelLazyFadeIn boolean | undefined
cancelTranslation boolean | undefined
containerStyle StyleProp<ViewStyle>
headerContainerStyle StyleProp<AnimateStyle<ViewStyle>>
headerHeight number | undefined Is optional, but will optimize the first render.
initialTabName string | number | undefined
lazy boolean | undefined If lazy, will mount the screens only when the tab is visited. There is a default fade in transition.
minHeaderHeight number | undefined Header minimum height when collapsed
onIndexChange ((index: number) => void) | undefined Callback fired when the index changes. It receives the current index.
onTabChange (data: { prevIndex: number index: number prevTabName: T tabName: T }) => void Callback fired when the tab changes. It receives the previous and current index and tabnames.
pagerProps Omit<FlatListProps<number>, 'data' | 'keyExtractor' | 'renderItem' | 'horizontal' | 'pagingEnabled' | 'onScroll' | 'showsHorizontalScrollIndicator' | 'getItemLayout'> Props passed to the horiztontal flatlist. If you want for example to disable swiping, you can pass { scrollEnabled: false }
renderHeader (props: TabBarProps<TabName>) => React.ReactElement | null
renderTabBar (props: TabBarProps<TabName>) => React.ReactElement | null (props: TabBarProps<TabName>) => MaterialTabBar
revealHeaderOnScroll boolean | undefined Reveal header when scrolling down. Implements diffClamp.
snapThreshold number | null | undefined null Percentage of header height to define as the snap point. A number between 0 and 1, or null to disable snapping.
tabBarHeight number | undefined Is optional, but will optimize the first render.

Tabs.Tab

Wrap your screens with Tabs.Tab. Basic usage looks like this:

<Tabs.Container ...>
  <Tabs.Tab name="A" label="First Tab">
   <ScreenA />
  </Tabs.Tab>
  <Tabs.Tab name="B">
   <ScreenA />
  </Tabs.Tab>
</Tabs.Container>

Props

name type
label string | undefined
name T

Tabs.Lazy

Typically used internally, but if you want to mix lazy and regular screens you can wrap the lazy ones with this component.

Props

name type
cancelLazyFadeIn boolean | undefined
startMounted boolean | undefined

Tabs.FlatList

Use like a regular FlatList.

Tabs.ScrollView

Use like a regular ScrollView.

Ref

You can pass a ref to Tabs.Container.

const ref = React.useRef()
<Tabs.Container ref={ref}>
method type
jumpToTab (name: T) => boolean
setIndex (index: number) => boolean
getFocusedTab () => T
getCurrentIndex () => number

Hooks

useCollapsibleStyle

Hook to access some key styles that make the whole think work. You can use this to get the progessViewOffset and pass to the refresh control of scroll view.

const {
  contentContainerStyle,
  progressViewOffset,
  style,
} = useCollapsibleStyle()

Values

name type
contentContainerStyle { minHeight: number; paddingTop: number; }
progressViewOffset number
style { width: number; }

useAnimatedTabIndex

Returns an animated value representing the current tab index, as a floating point number.

const tabIndex = useAnimatedTabIndex()

useFocusedTab

Returns the currently focused tab name.

const focusedTab = useAnimatedTabIndex()

useHeaderMeasurements

Returns the top distance and the header height. See the animated header example in the example folder.

const { top, height } = useHeaderMeasurements()

Default Tab Bar

MaterialTabItem

Any additional props are passed to the pressable component.

Props

name type default description
activeColor string | undefined null Color applied to the label when active
inactiveColor string | undefined null Color applied to the label when inactive
inactiveOpacity number | undefined 0.7
index number
indexDecimal SharedValue<number>
label string
labelStyle StyleProp<AnimateStyle<TextStyle>> Style to apply to the tab item label
name T
onLayout (((event: LayoutChangeEvent) => void) & ((event: LayoutChangeEvent) => void)) | undefined Invoked on mount and layout changes with {nativeEvent: { layout: {x, y, width, height}}}.
onPress (name: T) => void
pressColor string | undefined #DDDDDD
pressOpacity number | undefined Platform.OS === 'ios' ? 0.2 : 1
scrollEnabled boolean | undefined
style StyleProp<ViewStyle> Either view styles or a function that receives a boolean reflecting whether the component is currently pressed and returns view styles.

Known issues

Android FlatList pull to refresh

See this open issue. We use scrollTo to synchronize the unfocused tabs, it's supposed to work only with ScrollView, but works great with FlatList, until the RefreshControl is added. Note that this happens only to android.

Workaround: see the Android Shared Pull To Refresh example in the expo app. You can have a single pull to refresh for the Tabs.Container.

iOS FlatList stickyHeaderIndices

When you use the stickyHeaderIndices prop on a FlatList, the sticky elements don't scroll up when the header collapses. This happens only on iOS.

See #136.

ref.setIndex

This isn't an issue, but you need to know. When using containerRef.current.setIndex(i), if setting to the current index, the screen will scroll to the top. You can prevent this behavior like this:

const index = pageRef.current?.getCurrentIndex()
if (index !== nextIndex) {
  pageRef.current?.setIndex(nextIndex)
}

Alternative libraries

If you don't need a full-featured tab view, check out the other option, a simple segmented control / material tab bar without swiping or snapping, using just the react native Animated API.

Contributing

While developing, you can run the example app to test your changes.

Please follow the angular commit message format.

Make sure your code passes TypeScript and ESLint. Run the following to verify:

yarn typescript
yarn lint

To fix formatting errors, run the following:

yarn lint -- --fix

Remember to add tests for your change if possible.

Documentation changes

Edit the README_TEMPLATE, or update the docstrings inside the src folder, and run:

yarn docs

react-native-collapsible-tab-view's People

Contributors

alexpchin avatar andreialecu avatar dependabot[bot] avatar pedrobern avatar sayem314 avatar tcorreiaubi avatar

Watchers

 avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.