组件代码
/*
* @Author: Chenshy -- 自定义程度高 刻度尺如果不是很准确 自己挑一下
* 性能不好 但也能凑合用
*/
import React, {useState, useEffect, useRef} from 'react';
import {
View,
Text,
Image,
ScrollView,
StyleSheet,
Pressable,
TouchableOpacity,
} from 'react-native';
import {scale} from 'react-native-size-matters';
import {useDispatch} from 'react-redux';
import {useNavigation} from '@react-navigation/native';
import { changeLoading } from '../store/global/actions';
const ScaleAssembly = props => {
// dataNum={{min:50,max:250}} // 刻度尺 起点|| 终点
// unit={'cm'} //单位
// title={'选择身高'} //标题title
// playback={'60'} //回显数据
// handleEmail={(e)=>handleEmail(e)} //传值
// determine={(e)=>determine(e)} // 确定:sure || 取消:close
const {dataNum, unit, title, playback, handleEmail, determine} = props;
const navigation = useNavigation();
const dispatch = useDispatch();
// const mulriple = scale(120.55);
const mulriple = scale(120.5);
const thisAddres = useRef();
const [xcontentOffset, setXcontentOffset] = useState(0);
const [clickJump, setClickJump] = useState(); //点击跳转指定地方
const [datas, setDatas] = useState([
50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68,
// 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87,
// 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104,
// 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119,
// 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134,
// 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149,
// 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164,
// 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179,
// 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194,
// 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209,
// 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224,
// 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239,
// 240, 241, 242, 243, 244, 245, 246, 247, 248, 249,
]);
useEffect(() => {
dispatch(changeLoading({isShow:true,message:'my'}))
let arr = [];
setTimeout(()=>{
for (let i = dataNum.min; i < dataNum.max; i++) {
arr.push(i);
}
setDatas(arr);
},200)
setTimeout(() => {
let x = playback ? (playback * 1 - dataNum.min * 1) * mulriple : 0;
setClickJump({
x,
y: 0,
animated: true,
duration: 1000,
})
let num = ((Math.round(x / mulriple)).toFixed(1)) * 1 + dataNum.min * 1;
setXcontentOffset(num);
dispatch(changeLoading({isShow:false,message:''}))
}, 500);
}, []);
let timer = null;
const getData = event => {
clearTimeout(timer);
let x = event.nativeEvent.contentOffset.x;
timer = setTimeout(() => {
let distance = (Math.round(x) / mulriple).toFixed(1); //换算后当前所在的页面刻度
let num = distance * 1 + dataNum.min * 1;
setXcontentOffset(num); // 需加上dataNum.min才能显示真正所需刻度
handleEmail(num);
}, 200)
}
const thisadd = (index, minIndex) => {
setClickJump({
// x: (index+1)*124-12+12*minIndex,
x: index * 124 - 7,
y: 0,
animated: true,
duration: 1000,
});
// thisAddres.current.measure((frameX, frameY, frameWidth, frameHeight, pageX, pageY)=>{
// // console.log(frameX);
// // console.log(frameY);
// // console.log(frameWidth); // 当前组件的宽度
// // console.log(frameHeight); // 当前组件的高度
// console.log(pageX); // 当前组件距离左侧的距离
// // console.log(pageY); // 当前组件距离顶部的距离
// });
};
return (
<View style={styles.bigBox}>
<View style={styles.topBox}>
<TouchableOpacity
style={styles.closeIco}
onPress={() => {setDatas([]);determine('close')}}>
<Image
style={styles.closeImg}
source={require('../assets/images/common/icon-modal-close.png')}
/>
</TouchableOpacity>
<Text>{title}</Text>
<TouchableOpacity
style={styles.closeIco}
onPress={() => determine('sure', xcontentOffset)}>
<Text style={{fontSize: scale(15), color: '#677FD5'}}>确定</Text>
</TouchableOpacity>
</View>
<View style={styles.num}>
<Text style={{fontSize: scale(30), color: '#FE8441'}}>
{xcontentOffset}
{unit ? unit : 'cm'}
</Text>
</View>
<View
style={{
width: scale(1),
height: scale(68),
backgroundColor: '#FE8441',
position: 'absolute',
zIndex: 9999999999,
bottom: scale(32),
}}></View>
<ScrollView
horizontal={true}
style={styles.keduchi}
onScroll={e => getData(e)}
// onMomentumScrollEnd={e =>getData(e)} // 滚动结束时调用
showsHorizontalScrollIndicator={false} // 滚动条
contentOffset={clickJump} // 定位
pinchGestureEnabled={false} // 允许双指缩放 ios
directionalLockEnabled={true} // 锁定横向滚动 ios
>
<View style={{width: scale(175)}}></View>
{datas.map((item, index) => {
return (
<View
key={index}
style={[
styles.maxScale,
datas.length == index + 1 ? {borderRightWidth: scale(1)} : null,
]}>
<Pressable
style={styles.kdText}>
<Text style={{color: '#333333', fontSize: scale(12)}}>
{item}
</Text>
</Pressable>
<Pressable
style={styles.minScale}></Pressable>
<Pressable
style={styles.minScale}></Pressable>
<Pressable
style={styles.minScale}></Pressable>
<Pressable
style={styles.minScale}></Pressable>
<Pressable
style={[styles.minScale, {height: scale(40)}]}
ref={thisAddres}></Pressable>
<Pressable
style={styles.minScale}></Pressable>
<Pressable
style={styles.minScale}></Pressable>
<Pressable
style={styles.minScale}></Pressable>
<Pressable
style={styles.minScale}></Pressable>
</View>
);
})}
<View style={{width: scale(174)}}></View>
</ScrollView>
</View>
);
};
const styles = StyleSheet.create({
bigBox: {
flexDirection: 'column',
backgroundColor: '#fff',
height: scale(262),
borderRadius: scale(20),
alignItems: 'center',
// width:scale(500)
},
topBox: {
height: scale(54),
width: '100%',
backgroundColor: '#fff',
borderRadius: scale(20),
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center',
},
closeIco: {
marginLeft: scale(10),
marginRight: scale(10),
width: scale(40),
height: scale(40),
justifyContent: 'center',
alignItems: 'center',
},
closeImg: {
width: scale(15),
height: scale(15),
},
num: {
paddingTop: scale(38),
marginBottom: scale(58),
backgroundColor: '#fff',
borderTopWidth: scale(0.5),
borderColor: '#F0F0F0',
width: '100%',
justifyContent: 'center',
alignItems: 'center',
borderTopColor: '#F0F0F0',
borderTopWidth: scale(0.5),
},
keduchi: {
// backgroundColor: 'red',
},
maxScale: {
width: scale(120.5),
height: scale(40),
borderColor: '#7a7a7a',
borderLeftWidth: scale(1),
borderBottomWidth: scale(1),
flexDirection: 'row',
alignItems: 'flex-end',
},
kdText: {
position: 'absolute',
bottom: scale(-18),
left: scale(-16),
minWidth: scale(30),
alignItems: 'center',
},
minScale: {
borderRightWidth: scale(1),
borderColor: '#7a7a7a',
height: scale(20),
width: scale(12.1),
},
});
export default ScaleAssembly;
父组件
引用
import ScaleAssembly from '../../components/ScaleAssembly';
import ActionSheets from '../../components/common/ActionSheet';
ActionSheets是react native的弹窗动画组件
在html中使用
<ActionSheets
isShow={modalStateHeight}
height={300}
onHide={() => {
setModalStateHeight(false);
}}>
<ScaleAssembly
dataNum={{min: 50, max: 250}}
unit={'cm'} //单位
title={'选择身高'} //标题title
playback={heightValue} //回显数据
handleEmail={height => handleEmailHeight(height)} //传值
determine={e => determineHeight(e)} // 确定 || 取消
/>
</ActionSheets>