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
| import React, { useMemo, useState } from "react" import { ScrollView, View } from "react-native"
const Demo: React.FC = () => { const [contentSize, setContentSize] = useState(0) const [scrollViewSize, setScrollViewSize] = useState(0) const [scrollPosition, setScrollPosition] = useState(0)
const indicatorWidth = useMemo(() => { if (contentSize > 0 && scrollViewSize > 0) { return (scrollViewSize / contentSize) * scrollViewSize }
return 0 }, [contentSize, scrollViewSize])
const indicatorPosition = useMemo(() => { if (contentSize > 0 && scrollPosition > 0) { return (scrollPosition / contentSize) * scrollViewSize }
return 0 }, [contentSize, scrollPosition, scrollViewSize])
return ( <View> <ScrollView // disable default scroll indicator showsHorizontalScrollIndicator={false} onLayout={(event) => { setScrollViewSize(event.nativeEvent?.layout?.width ?? 0) }} onContentSizeChange={(w) => { setContentSize(w) }} horizontal // set horizontal scroll scrollEventThrottle={16} // throttle scroll event to improve performance onScroll={(event) => { // change scroll position here const { contentOffset } = event.nativeEvent
const { x = 0 } = contentOffset const max = contentSize - scrollViewSize const min = 0
if (x > max) { setScrollPosition(max) } else if (x < min) { setScrollPosition(min) } else { setScrollPosition(x) } }} > {/* Content here */} </ScrollView>
{/* custom scroll indicator */} <View style={{ bottom: 0, height: 4, width: indicatorWidth, position: "absolute", left: indicatorPosition, borderRadius: 4, backgroundColor: "#EEEEEE", }} /> </View> ) }
export default Demo
|