如何设置滚动指示器的样式以反应原生滚动条

时间:2018-06-08 06:02:40

标签: react-native scrollview

我想在我的滚动指示器中添加一些样式用于反向原生的垂直滚动条。我想让滚动指示器比默认大小更宽,以便用户清楚地看到滚动指示器。我想改变滚动指示器中的颜色和其他一些东西。

我该怎么办?是否有可能在垂直滚动视图中对滚动指示器进行反应本机..

也应该在任何平台兼容

3 个答案:

答案 0 :(得分:3)

您可以使用ScrollView的indicatorStyle道具来改变颜色,但它只支持三种颜色白色,黑色或默认颜色。您可以使用scrollIndicatorInsets道具设置指标的插图。要获得更多自定义样式,您可以使用react-native-scroll-indicator

答案 1 :(得分:2)

您应该在滚动条上添加侦听器,然后创建一个自定义视图,并通过scrollListener和不可见的滚动指示器对其进行转换,这是您想要实现的简单实现:

class CustomScrollview extends PureComponent {
    state = {
        indicator: new Animated.Value(0),
        wholeHeight: 1,
        visibleHeight: 0
    }
    render() {
        const indicatorSize = this.state.wholeHeight > this.state.visibleHeight ?
            this.state.visibleHeight * this.state.visibleHeight / this.state.wholeHeight :
            this.state.visibleHeight

        const difference = this.state.visibleHeight > indicatorSize ? this.state.visibleHeight - indicatorSize : 1
        return (
            <View >
                <ScrollView
                    showsVerticalScrollIndicator={false}
                    onContentSizeChange={(width, height) => {
                        this.setState({ wholeHeight: height })
                    }}
                    onLayout={({ nativeEvent: { layout: { x, y, width, height } } }) => this.setState({ visibleHeight: height })}
                    scrollEventThrottle={16}
                    onScroll={Animated.event(
                        [{ nativeEvent: { contentOffset: { y: this.state.indicator } } }]
                    )}>


                </ScrollView >
                <View style={styles.indicatorWrapper} />
                <Animated.View style={[
                    styles.indicator, {
                        height: indicatorSize,
                        transform: [{
                            translateY: Animated.multiply(this.state.indicator, this.state.visibleHeight / this.state.wholeHeight).interpolate({
                                inputRange: [0, difference],
                                outputRange: [0, difference],
                                extrapolate: 'clamp'
                            })
                        }]
                    }]} />

            </View>
        )
    }
}

希望获得帮助!

答案 2 :(得分:0)

您可以使用 ScrollView 中的 Animated from react-nativeonLayoutonContentSizeChangeonScroll 以及一些数学方法来完成此操作。

基本上,您可以将 ScrollView 的可见高度与内容的实际完整大小(可见和隐藏)进行比较,从而知道滚动条的高度。然后你只需要在用户滚动时更新那个栏的位置。

请参阅以下带有反应钩子的代码示例:

const CustomScrollBarComponent = () => {
  const [completeScrollBarHeight, setCompleteScrollBarHeight] = useState(1);
  const [visibleScrollBarHeight, setVisibleScrollBarHeight] = useState(0);
  const scrollIndicator = useRef(new Animated.Value(0)).current;

  const scrollIndicatorSize =
    completeScrollBarHeight > visibleScrollBarHeight
      ? (visibleScrollBarHeight * visibleScrollBarHeight)
        / completeScrollBarHeight
      : visibleScrollBarHeight;

  const difference =
    visibleScrollBarHeight > scrollIndicatorSize
      ? visibleScrollBarHeight - scrollIndicatorSize
      : 1;

  const scrollIndicatorPosition = Animated.multiply(
    scrollIndicator,
    visibleScrollBarHeight / completeScrollBarHeight,
  ).interpolate({
    extrapolate: 'clamp',
    inputRange: [0, difference],
    outputRange: [0, difference],
  });

  const onContentSizeChange = (_, contentHeight) => 
    setCompleteScrollBarHeight(contentHeight);

  const onLayout = ({
    nativeEvent: {
      layout: { height },
    },
  }) => {
    setVisibleScrollBarHeight(height);
  };

  return (
    <View style={styles.scrollContainer}>
      <ScrollView
        contentContainerStyle={{ paddingRight: 14 }}
        onContentSizeChange={onContentSizeChange}
        onLayout={onLayout}
        onScroll={Animated.event(
          [{ nativeEvent: { contentOffset: { y: scrollIndicator } } }],
          { useNativeDriver: false },
        )}
        scrollEventThrottle={16}
        showsVerticalScrollIndicator={false}
        style={styles.petItemListContainer}
      >
        {/* Your ScrollView content here */}
      </ScrollView>
      <View style={styles.customScrollBarBackground}>
        <Animated.View
          style={[
            styles.customScrollBar,
            {
              height: scrollIndicatorSize,
              transform: [{ translateY: scrollIndicatorPosition }],
            },
          ]}
        />
      </View>
    </View>
  );
};

风格:

const styles = StyleSheet.create({
  scrollContainer: {
    flexDirection: 'row',
    width: '100%',
  },
  petItemListContainer: {
    width: '100%',
  },
  customScrollBar: {
    backgroundColor: '#ccc',
    borderRadius: 3,
    width: 6,
  },
  customScrollBarBackground: {
    backgroundColor: '#232323',
    borderRadius: 3,
    height: '100%',
    width: 6,
  },
});