UNPKG

react-native-segment-control

Version:

A React Native swipeable SegmentedControl component for iOS and Android <img src="https://github.com/ainurb/react-native-segment-control/blob/master/example/example1.gif" width="30%" /> <img src="https://github.com/ainurb/react-native-segment-control/blob

161 lines (146 loc) 3.85 kB
import React, { Component } from "react"; import { View, ScrollView, Animated, StyleSheet, ViewProperties, TouchableOpacity } from "react-native"; class SegmentControl extends Component { state = { scrollX: new Animated.Value(0), containerWidth: 0 }; render() { const { segments = [], color = "#4549D1" } = this.props; const numberOfSegments = segments.length; const { containerWidth } = this.state; const activeMargin = this.state.scrollX.interpolate({ inputRange: [0, (numberOfSegments - 1) * containerWidth], outputRange: [ 0, (numberOfSegments - 1) * containerWidth / numberOfSegments ] }); return ( <View style={styles.card} onLayout={event => { const { width } = event.nativeEvent.layout; this.setState({ containerWidth: width }); }} > <View style={styles.container}> <View style={styles.headerContainer}> {segments.map((segment, index) => this.renderSegment(numberOfSegments, segment.title, index) )} </View> <Animated.View style={[ styles.animatedSeparator, { width: containerWidth / numberOfSegments, marginLeft: activeMargin, backgroundColor: color } ]} /> <View style={styles.separatorStyle} /> <ScrollView scrollEventThrottle={16} onScroll={this.handleOnScroll} horizontal={true} pagingEnabled={true} showsHorizontalScrollIndicator={false} ref={ref => (this.scrollView = ref)} > {segments.map((segment, index) => { return ( <View style={{ width: containerWidth }} key={index}> {segment.view(segment.viewProps)} </View> ); })} </ScrollView> </View> </View> ); } renderSegment = (numberOfSegments, title, index) => { const input = Array.from( { length: numberOfSegments }, (value, key) => key ).map(key => key * this.state.containerWidth); const output = Array.from( { length: numberOfSegments }, (value, key) => key ).map(key => (key === index ? "black" : "#828282")); if (output.length < 2) { return <View key={index} />; } const color = this.state.scrollX.interpolate({ inputRange: input, outputRange: output, extrapolate: "clamp" }); return ( <TouchableOpacity style={styles.headerItem} onPress={() => { this.scrollView.scrollTo({ x: index * this.state.containerWidth, y: 0, animated: true }); }} key={index} > <Animated.Text style={[styles.title, { color }]}>{title}</Animated.Text> </TouchableOpacity> ); }; handleOnScroll = x => { const mover = Animated.event([ { nativeEvent: { contentOffset: { x: this.state.scrollX } } } ]); mover(x); }; } const styles = StyleSheet.create({ card: { width: "100%", backgroundColor: "white", borderRadius: 6, shadowColor: "black", shadowOffset: { height: 4, width: 0 }, shadowOpacity: 0.1, elevation: 3 }, separatorStyle: { height: 1, backgroundColor: "#E0E0E0" }, container: { overflow: "hidden" }, headerContainer: { flexDirection: "row", justifyContent: "space-between" }, headerItem: { flex: 1, alignItems: "center", paddingVertical: 16 }, title: { fontWeight: "600", fontSize: 16, textAlign: "center" }, animatedSeparator: { height: 2 } }); export default SegmentControl;