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(步调)