React

关注公众号 jb51net

关闭
首页 > 网络编程 > JavaScript > javascript类库 > React > ReactNative横向滑动条

ReactNative实现的横向滑动条效果

作者:xvzhengyang

本文介绍了ReactNative实现的横向滑动条效果,本文结合示例代码给大家介绍的非常详细,补充介绍了ReactNative基于宽度变化实现的动画效果,感兴趣的朋友跟随小编一起看看吧

ReactNative实现的横向滑动条

推荐文章

ReactNative实现弧形拖动条

OK,我们先看下效果图

注意使用到了两个库

1.react-native-linear-gradient

2.react-native-gesture-handler

ok,我们看下面的代码

import {Image, TouchableWithoutFeedback, StyleSheet, View} from 'react-native';
import LinearGradient from 'react-native-linear-gradient';
import React from 'react';
import {
  Gesture,
  GestureDetector,
  GestureHandlerRootView,
} from 'react-native-gesture-handler';
export class HorizntalSlider extends React.Component {
  shouldComponentUpdate(
    nextProps: Readonly<P>,
    nextState: Readonly<S>,
    nextContext: any,
  ): boolean {
    return false;
  }
  constructor(props) {
    super(props);
    this.progress = props.initValue;
    this.step = props.step;
    this.range = props.max - props.min;
    this.currentX = 0;
    this.enable = true;
  }
  _setValueChange(value) {
    this.currentX = value;
    this.selectedTrack.setNativeProps({
      style: {width: value},
    });
    let indicatorValue = value - 5 > 0 ? value - 5 : 0;
    this.indicator.setNativeProps({
      style: {left: indicatorValue - 1},
    });
  }
  componentDidMount(): void {
    if (this.props) {
      this.setPowerState(this.props.openState);
    }
  }
  _add() {
    if (!this.enable) {
      showToast(this.tips);
      const {onEnableClick} = this.props;
      if (onEnableClick) {
        onEnableClick();
      }
      return;
    }
    let tempValue = this.progress + this.step;
    this.progress =
      tempValue > this.props.max ? this.props.max : tempValue;
    let styleValue =
      ((this.progress - this.props.min) / this.range) * 250;
    this._setValueChange(styleValue);
    const {onLastChange, onChange} = this.props;
    onChange(this.progress);
    onLastChange(this.progress);
  }
  _reduce() {
    if (!this.enable) {
      const {onEnableClick} = this.props;
      if (onEnableClick) {
        onEnableClick();
      }
      showToast(this.tips);
      return;
    }
    let tempValue = this.progress - this.step;
    this.progress =
      tempValue < this.props.min ? this.props.min : tempValue;
    let styleValue =
      ((this.progress - this.props.min) / this.range) * 250;
    this._setValueChange(styleValue);
    const {onLastChange, onChange} = this.props;
    onChange(this.progress);
    onLastChange(this.progress);
  }
  _onValueChange(x, isFinalize = false) {
    if (x > 250) {
      x = 250;
    }
    if (x < 0) {
      x = 0;
    }
    this.currentX = x;
    this.progress = this.props.min + parseInt((x / 250) * this.range);
    // if (isFinalize) {
    //   const {onLastChange} = this.props;
    //   onLastChange(this.progress);
    // } else {
    //   const {onChange} = this.props;
    //   onChange(this.progress);
    // }
    this._setValueChange(x);
  }
  setPowerState(state) {
    if (!this.props) {
      return;
    }
    if (state === 1) {
      this.selectedTrack.setNativeProps({
        style: {
          width: this.currentX,
        },
      });
      this.indicator.setNativeProps({
        style: {opacity: 1},
      });
    } else {
      this.selectedTrack.setNativeProps({
        style: {width: 0},
      });
      this.indicator.setNativeProps({
        style: {opacity: 0},
      });
    }
  }
  setEnable(isEnable, tips) {
    if (!this.props) {
      return;
    }
    this.enable = isEnable;
    this.tips = tips;
  }
  gesture = Gesture.Pan()
    .onBegin(e => {
      this._onValueChange(e.x);
    })
    .onUpdate(e => {
      this._onValueChange(e.x);
    })
    .onFinalize(e => {
      this._onValueChange(e.x, true);
    });
  render() {
    this.currentX = ((this.progress - this.props.min) / this.range) * 250;
    this.currentX = this.currentX > 0 ? this.currentX : 0;
    return (
      <View style={[styles.mainContainer, this.props.style]}>
        <GestureHandlerRootView>
          <GestureDetector gesture={this.gesture}>
            <View style={styles.sliderContainer}>
              <LinearGradient
                start={{x: 0, y: 0}}
                end={{x: 1, y: 0}}
                colors={['#4372FF', 'white', '#FF4D4F']}
                style={{
                  width: 252,
                  height: 60,
                }}
              />
              <View
                style={{
                  flexDirection: 'row',
                  alignItems: 'center',
                  position: 'absolute',
                }}>
                <View
                  ref={c => (this.selectedTrack = c)}
                  style={{
                    width: this.currentX,
                    opacity: 0,
                    height: 60,
                  }}
                />
                <View
                  style={{
                    flex: 1,
                    backgroundColor: '#12161a',
                    opacity: 0.8,
                    height: 60,
                  }}
                />
              </View>
              <View
                ref={c => (this.indicator = c)}
                style={[styles.indicator, {left: this.currentX - 7}]}
              />
            </View>
          </GestureDetector>
        </GestureHandlerRootView>
      </View>
    );
  }
}
class Track extends React.Component {
  constructor(props) {
    super(props);
    this.unitViewArr = [];
    for (let i = 0; i < 42; i++) {
      this.unitViewArr[i] = i;
    }
  }
  shouldComponentUpdate(
    nextProps: Readonly<P>,
    nextState: Readonly<S>,
    nextContext: any,
  ): boolean {
    return false;
  }
  render() {
    return (
      <View style={styles.trackContainer}>
        {this.unitViewArr.map((item, index) => {
          return (
            <View
              key={index}
              style={{flexDirection: 'row', alignItems: 'center'}}>
              <View
                style={{
                  height: 60,
                  width: 2,
                  opacity: 0,
                  backgroundColor: '#12161a',
                  borderRadius: 100,
                }}
              />
              <View
                style={{height: 60, width: 4, backgroundColor: '#12161a'}}
              />
            </View>
          );
        })}
      </View>
    );
  }
}
const styles = StyleSheet.create({
  mainContainer: {
    flexDirection: 'row',
    justifyContent: 'center',
    alignItems: 'center',
  },
  sliderContainer: {
    position: 'relative',
    justifyContent: 'center',
    paddingVertical: 10,
    marginLeft: 10,
    marginRight: 8,
  },
  trackContainer: {
    width: 252,
    flexDirection: 'row',
    position: 'absolute',
  },
  actionImg: {
    width: 60,
    height: 60,
  },
  thumb: {
    height: 34,
    width: 7,
    backgroundColor: 'transparent',
  },
  indicator: {
    width: 0,
    height: 0,
    position: 'absolute',
    top: -2,
    borderLeftWidth: 4,
    borderTopWidth: 4,
    borderRightWidth: 4,
    left: -3,
    borderTopColor: '#FF6A6B',
    borderLeftColor: 'transparent',
    borderRightColor: 'transparent',
  },
});
export default HorizntalSlider;

使用代码如下

        <GestureHandlerHorizntalSlider
              model={{
                initValue: 20,
                step: 10,
                max: 100,
                min: 0,
              }}>
       </GestureHandlerHorizntalSlider>

拖动条:max(最大值),min(最小值),initValue(当前值),step(步调)

补充:

ReactNative基于宽度变化实现的动画效果

效果如上图所示,通过修改设备宽度实现动画效果

import React, {useRef, useEffect, useState} from 'react';
import {Animated, Text, View, Image} from 'react-native';
const FadeInView = props => {
  const fadeAnim = useRef(new Animated.Value(0)).current;
  React.useEffect(() => {
    Animated.timing(
      fadeAnim, // 动画中的变量值
      {
        toValue: props.currentWidth, // 
        duration: props.durationTime, // 让动画持续一段时间
        //  Style property 'width' is not supported by native animated module
        useNativeDriver: false,
      },
    ).start(); // 开始执行动画
  }, [props.currentWidth]);
  return (
    <Animated.View // 使用专门的可动画化的View组件
      style={{
        ...props.style,
        width: fadeAnim, // 将宽度绑定到动画变量值
      }}>
    </Animated.View>
  );
};
// 然后你就可以在组件中像使用`View`那样去使用`FadeInView`了
export default props => {
  return (
    <FadeInView
      durationTime={props.durationTime}
      currentWidth={props.currentWidth}
      style={{height: 310, backgroundColor: 'pink'}}></FadeInView>
  );
};

使用的代码如下

<LayoutAnimatedWidth
      currentWidth={this.state.currentWidth}
      durationTime={this.state.durationTime}>
</LayoutAnimatedWidth>

PS:注意上面的代码和截图不一致;但是代码是可以实现上面的效果的。

到此这篇关于ReactNative实现的横向滑动条的文章就介绍到这了,更多相关ReactNative横向滑动条内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文