该版本依旧存在性能问题 但相比上版本有点改善,凑合着用
把ScrollView改成recyclerlistview组件没有性能问题,详情看react native高性能组件recyclerlistview
子组件代码
/*
* @Author: Chenshy
* @Date: 2021-7-14 14:15:49
*/
import React, {useState, useEffect, useRef} from 'react';
import {
View,
Text,
Image,
ScrollView,
StyleSheet,
Pressable,
TouchableOpacity,
Dimensions,
} from 'react-native';
import {scale} from 'react-native-size-matters';
import {useNavigation} from '@react-navigation/native';
const {width, height} = Dimensions.get('window');
const EntryOfHealthData = 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,
unit2,
unit3,
title,
playback,
handleEmail,
determine,
handleEmailSbp,
handleEmailDpd,
} = props;
const navigation = useNavigation();
// const mulriple = 123.95; // 体重除数
// const mulriple2 = 12.395; // 血压/心率 除数
//适配
// const mulriple = scale(60.22); // 体重除数
const mulriple = scale(60.24); // 体重除数60.22-60.3
const mulriple2 = scale(609/50.72); // 心率 除数
const thisAddres = useRef();
const [xcontentOffset, setXcontentOffset] = useState(60);
const [xcontentOffset2, setXcontentOffset2] = useState(80);
const [xcontentOffsetSbp, setXcontentOffsetSbp] = useState(120);
const [xcontentOffsetDpd, setXcontentOffsetDpd] = useState(80);
const [rollData, setRollData] = useState(0);
const [rollDatass, setRollDatass] = useState(0);
const [rollDatasz, setRollDatasz] = useState(0);
const [clickJump, setClickJump] = useState({
x: playback ? (playback * 1 - dataNum.min * 1) * mulriple : 0,
y: 0,
animated: true,
duration: 1000,
}); //点击跳转指定地方
const [ss,setSs] = useState({ //x = d * (5/m)
x: 120*mulriple/5 , // 1488
y: 0,
animated: true,
duration: 1000,
}) // 收缩
const [sz,setSz] = useState({
x: 80*mulriple/5, // 993
y: 0,
animated: true,
duration: 1000,
}) //舒张
const [xl,setXl] = useState({
x: 80*mulriple2,
y: 0,
animated: true,
duration: 1000,
}) //心率
const [tz,setTz] = useState({
x: 60*mulriple,
y: 0,
animated: true,
duration: 1000,
}) //体重
const [datas, setDatas] = useState([
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39,
40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 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, 250,
]);
const [heart, setHeart] = useState([
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39,
40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 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,
]);
const [sbp, setSbp] = useState([
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39,
40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 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,
]);
const [dpd, setDpd] = useState([
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39,
40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 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,
]);
const [newData, setNewData] = useState([]);
useEffect(() => {
if (title == '录入心率') setNewData(heart);
if (title == '录入体重') setNewData(datas);
setTimeout(() => {
let newss = JSON.parse(JSON.stringify(ss))
newss.x = newss.x*1 + 0.001
let newsz = JSON.parse(JSON.stringify(sz))
newsz.x = newsz.x*1 + 0.001
let newxl = JSON.parse(JSON.stringify(xl))
newxl.x = newxl.x*1 + 0.001
let newtz = JSON.parse(JSON.stringify(tz))
newtz.x = newtz.x*1 + 0.001
setSs(newss)
setSz(newsz)
setXl(newxl)
setTz(newtz)
}, 100);
// console.log(props.dataNum);
// let arr = [];
// for (let i = dataNum.min * 1; i < dataNum.max * 1; i++) {
// arr.push(i);
// }
// setDatas(arr);
// console.log(arr);
}, []);
const getData = event => { // 心率 体重
console.log(event.nativeEvent.contentOffset.x); //水平滚动距离
// console.log(event.nativeEvent.contentOffset.y); //垂直滚动距离
let distance = 0;
if (title == '录入心率') {
distance = Math.round(
Math.round(event.nativeEvent.contentOffset.x) / mulriple2,
);
// distance = (event.nativeEvent.contentOffset.x / mulriple2).toFixed(0); //换算后当前所在的页面刻度
setXcontentOffset(distance * 1 );
setXcontentOffset2(distance * 1 );
handleEmail(distance * 1 );
setTimeout(() => {
handleEmail(distance * 1);
}, 100);
} else { //体重
// distance = (
// Math.round(event.nativeEvent.contentOffset.x) / mulriple*2
// ).toFixed(1); //换算后当前所在的页面刻度
distance = (event.nativeEvent.contentOffset.x / mulriple).toFixed(1); //换算后当前所在的页面刻度
setXcontentOffset(distance * 1); // 需加上dataNum.min才能显示真正所需刻度
handleEmail(distance * 1);
setTimeout(() => {
handleEmail(distance * 1);
}, 100);
}
// setXcontentOffset(distance * 1 + dataNum.min * 1); // 需加上dataNum.min才能显示真正所需刻度
// handleEmail(distance * 1 + dataNum.min * 1);
// setRollData(event.nativeEvent.contentOffset.x)
};
const getDataSbp = event => { //收缩压
let distance = Math.round( Math.round(event.nativeEvent.contentOffset.x) / mulriple*5, );
// d = x / m*5
// x = d*m/5
setXcontentOffsetSbp(distance * 1 );
handleEmailSbp(distance * 1 );
// setRollDatass(event.nativeEvent.contentOffset.x)
setTimeout(() => {
handleEmailSbp(distance * 1);
}, 100);
};
const getDataDpd = event => { //舒张压
let distance = Math.round(
Math.round(event.nativeEvent.contentOffset.x) / mulriple*5,
);
setXcontentOffsetDpd(distance * 1 );
handleEmailDpd(distance * 1 );
// setRollDatasz(event.nativeEvent.contentOffset.x)
setTimeout(() => {
handleEmailDpd(distance * 1);
}, 100);
};
const thisadd = (index, minIndex) => {
//点击跳转
// console.log(index,minIndex);
setClickJump({
// x: (index+1)*124-12+12*minIndex,
x: index * scale(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); // 当前组件距离顶部的距离
// });
};
// 暂时无用
const repeatCall = (title) =>{ //心率体重滑动结束后再动一次
// let newDatas
// setTimeout(() => {
// console.log('重复调用',title);
// if(title == '录入体重'){
// newDatas = JSON.parse(JSON.stringify(tz))
// newDatas.x = rollData*1+0.0001
// setTz(newDatas)
// }else{
// newDatas = JSON.parse(JSON.stringify(xl))
// newDatas.x = rollData*1+0.0001
// setXl(newDatas)
// }
// }, 300);
}
const repeatCallss = (title) =>{ //收缩滑动结束后再动一次
// let newDatas
// setTimeout(() => {
// console.log('收缩重复调用',title);
// newDatas = JSON.parse(JSON.stringify(ss))
// newDatas.x = rollDatass*1+0.0001
// setSs(newDatas)
// }, 300);
}
const repeatCallsz = (title) =>{ //舒张滑动结束后再动一次
// let newDatas
// setTimeout(() => {
// console.log('舒张重复调用',title);
// newDatas = JSON.parse(JSON.stringify(sz))
// newDatas.x = rollDatasz*1+0.0001
// setSz(newDatas)
// }, 300);
}
return title != '录入血压' ? (
<View style={styles.bigBox}>
<View style={styles.topBox}>
{/* <TouchableOpacity
style={styles.closeIco}
onPress={() => determine('close')}>
<Image
style={styles.closeImg}
source={require('../assets/images/common/icon-modal-close.png')}
/>
</TouchableOpacity> */}
<Text></Text>
<Text>{title}</Text>
<Text></Text>
{/* <TouchableOpacity
style={styles.closeIco}
onPress={() => determine('sure')}>
<Text style={{fontSize: scale(15), color: '#677FD5'}}>确定</Text>
</TouchableOpacity> */}
</View>
<View style={[styles.num, {justifyContent: 'center'}]}>
<Text
style={{fontSize: scale(18), color: '#677FD5', fontWeight: 'bold'}}>
{title == '录入心率'? xcontentOffset2 : xcontentOffset}
{unit ? unit : 'cm'}
</Text>
</View>
<View
style={{
width: scale(6),
height: scale(40),
backgroundColor: '#677FD5',
position: 'absolute',
zIndex: 9999999999,
bottom: scale(100),
borderRadius: scale(20),
}}></View>
<ScrollView
horizontal={true}
style={styles.keduchi}
onScroll={e => getData(e)}
scrollEventThrottle={1}
onMomentumScrollEnd={ e => repeatCall(title)}
// onMomentumScrollEnd={e =>getData(e)} // 滚动结束时调用
showsHorizontalScrollIndicator={false} // 滚动条
contentOffset={title == '录入体重' ? tz : xl} // 定位
pinchGestureEnabled={false} // 允许双指缩放 ios
directionalLockEnabled={true} // 锁定横向滚动 ios
>
<View style={{width: scale(175)}}></View>
{newData.map((item, index) => {
return (
title == '录入体重'?
<View
key={index}
style={[
styles.maxScale,{width: scale(60.25)},
datas.length == index + 1 ? {borderRightWidth: scale(1)} : null,
]}>
<Pressable
style={styles.kdText}
onPress={() => thisadd(index, 0)}>
<Text style={{color: '#333333', fontSize: scale(12)}}>
{item}
</Text>
</Pressable>
<Pressable
style={styles.minScale}
onPress={() => thisadd(index, 1)}></Pressable>
<Pressable
style={styles.minScale}
onPress={() => thisadd(index, 2)}></Pressable>
<Pressable
style={styles.minScale}
onPress={() => thisadd(index, 3)}></Pressable>
<Pressable
style={styles.minScale}
onPress={() => thisadd(index, 4)}></Pressable>
</View>
:
<View
key={index}
style={[
styles.maxScale2,
(item * 1) % 5 == 0?{height: scale(40)}:null,
]}>
<Pressable
style={styles.kdText}
onPress={() => thisadd(index, 0)}>
<Text style={{color: '#333333', fontSize: scale(12)}}>
{(item * 1 ) % 5 == 0 ? item : null}
</Text>
</Pressable>
</View>
);
})}
<View style={{width: scale(174)}}></View>
</ScrollView>
<View style={styles.sumbutBox}>
<TouchableOpacity
style={styles.sumbut}
onPress={() => determine('close')}>
<Text style={{fontSize: scale(15), color: '#677FD5'}}>取消</Text>
</TouchableOpacity>
<TouchableOpacity
style={[styles.sumbut, {backgroundColor: '#677FD5'}]}
onPress={() => determine('sure',title)}>
<Text style={{fontSize: scale(15), color: '#fff'}}>确定</Text>
</TouchableOpacity>
</View>
</View>
) : (
<View style={[styles.bigBox, {height: scale(400)}]}>
<View style={styles.topBox}>
<Text></Text>
<Text>{title}</Text>
<Text></Text>
</View>
<View style={styles.num}>
<Text style={{color: '#333333', fontSize: scale(18)}}>收缩压</Text>
<Text
style={{fontSize: scale(18), color: '#677FD5', fontWeight: 'bold'}}>
{xcontentOffsetSbp}
{unit2 ? unit2 : 'cm'}
</Text>
<View style={{width: scale(50)}}></View>
</View>
<View
style={{
width: scale(6),
height: scale(40),
backgroundColor: '#677FD5',
position: 'absolute',
zIndex: 9999999999,
bottom: scale(240),
borderRadius: scale(20),
}}></View>
<ScrollView
horizontal={true}
style={styles.keduchi}
onScroll={e => getDataSbp(e)}
scrollEventThrottle={1}
onMomentumScrollEnd={ e => repeatCallss(title)}
// onMomentumScrollEnd={e =>getData(e)} // 滚动结束时调用
showsHorizontalScrollIndicator={false} // 滚动条
contentOffset={ss} // 定位
pinchGestureEnabled={false} // 允许双指缩放 ios
directionalLockEnabled={true} // 锁定横向滚动 ios
>
<View style={{width: scale(175)}}></View>
{sbp.map((item, index) => {
return (
<View
key={index}
style={[
styles.maxScale2,
(item * 1) % 5 == 0?{height: scale(40)}:null,
]}>
<Pressable
style={styles.kdText}
onPress={() => thisadd(index, 0)}>
<Text style={{color: '#333333', fontSize: scale(12)}}>
{(item*1)%5==0?item:null}
</Text>
</Pressable>
</View>
);
})}
<View style={{width: scale(174)}}></View>
</ScrollView>
<View style={styles.num}>
<Text style={{color: '#333333', fontSize: scale(18)}}>舒张压</Text>
<Text
style={{fontSize: scale(18), color: '#677FD5', fontWeight: 'bold'}}>
{xcontentOffsetDpd}
{unit3 ? unit3 : 'cm'}
</Text>
<View style={{width: scale(50)}}></View>
</View>
<View
style={{
width: scale(6),
height: scale(40),
backgroundColor: '#677FD5',
position: 'absolute',
zIndex: 9999999999,
bottom: scale(86),
borderRadius: scale(20),
}}></View>
<ScrollView
horizontal={true}
style={styles.keduchi}
onScroll={e => getDataDpd(e)}
scrollEventThrottle={1}
onMomentumScrollEnd={ e => repeatCallsz(title)}
// onMomentumScrollEnd={e =>getData(e)} // 滚动结束时调用
showsHorizontalScrollIndicator={false} // 滚动条
contentOffset={sz} // 定位
pinchGestureEnabled={false} // 允许双指缩放 ios
directionalLockEnabled={true} // 锁定横向滚动 ios
>
<View style={{width: scale(175)}}></View>
{dpd.map((item, index) => {
return (
<View
key={index}
style={[
styles.maxScale2,
(item * 1) % 5 == 0?{height: scale(40)}:null,
]}>
<Pressable
style={styles.kdText}
onPress={() => thisadd(index, 0)}>
<Text style={{color: '#333333', fontSize: scale(12)}}>
{(item * 1 ) % 5 == 0 ? item : null}
</Text>
</Pressable>
</View>
);
})}
<View style={{width: scale(174)}}></View>
</ScrollView>
<View style={styles.sumbutBox}>
<TouchableOpacity
style={styles.sumbut}
onPress={() => determine('close')}>
<Text style={{fontSize: scale(15), color: '#677FD5'}}>取消</Text>
</TouchableOpacity>
<TouchableOpacity
style={[styles.sumbut, {backgroundColor: '#677FD5'}]}
onPress={() => determine('sure')}>
<Text style={{fontSize: scale(15), color: '#fff'}}>确定</Text>
</TouchableOpacity>
</View>
</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(16),
backgroundColor: '#fff',
borderTopWidth: scale(0.5),
borderColor: '#F0F0F0',
width: '100%',
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center',
borderTopColor: '#F0F0F0',
},
keduchi: {
// backgroundColor: 'red',
},
maxScale: {
width: scale(120.5),
height: scale(40),
borderColor: '#7a7a7a',
borderLeftWidth: scale(1),
// borderBottomWidth: scale(1),
flexDirection: 'row',
alignItems: 'flex-start',
},
maxScale2: {
width: scale(12.05),
height: scale(20),
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),
},
sumbutBox: {
// backgroundColor: 'red',
flexDirection: 'row',
justifyContent: 'space-around',
alignItems: 'flex-end',
width: width,
// borderTopWidth: scale(1),
// borderColor: '#ccc',
},
sumbut: {
width: scale(140),
height: scale(40),
borderRadius: scale(40),
borderColor: '#677FD5',
borderWidth: scale(1),
justifyContent: 'center',
alignItems: 'center',
},
});
export default EntryOfHealthData;
父组件代码
引入使用
<EntryOfHealthData
dataNum={{ min: 20, max: 200 }}
unit={activeTab == 2 ? 'kg' : '次/分'} //单位
title={
activeTab == 2
? '录入体重'
: activeTab == 1
? '录入心率'
: '录入血压'
} //标题title
// playback={0} //回显数据
handleEmail={data => handleEmail(data)} //传值
handleEmailSbp={data => handleEmailSbp(data)} //传值
handleEmailDpd={data => handleEmailDpd(data)} //传值
determine={(type, index) => determine(type, index)} // 确定 || 取消
/>
方法
const handleEmail = data => {
// console.log('从子组件拿值==', data);
};
const determine = (type, index) => {
};
const handleEmailSbp = data => {
console.log('高压', data);
};
const handleEmailDpd = data => {
console.log('低压==', data);
};