I have a horizontal ScrollView
at the top of the screen. Underneath that, I have a vertical ScrollView
that fades out. I have now moved the faded vertical scrollView
to overlap the horizontal scrollView
at the top of the screen. The issue is, the vertical scrollView
now blocks the horizontal one from being able to be touched.
When there is no content from the vertical one blocking the horizontal one, how can I enable touch on the horizontal scrollView?
Reproducible Example ready to go on snack.io
~ In this example, I want to be able to interact with the green cards, when the orange cards are not overtop of them.
Edit
Any implementation where the vertical scrollView fades out on top of the screen is satisfactory, it doesn’t have to be my specific fadedView(MaskedElement/View) component. I originally had it working without the fadedView. I set overflow to visible on the vertical scrollView, and it worked just fine, being able to touch the horizontal scrollView when the overflow wasn’t overlapping, and couldn’t touch the horizontal view when the overflow was overlapping. When looking for a way to make the vertical ScrollView fade out on the top of the screen, overflow wasn’t enough.
Some of the code here as well:
App.js
<SafeAreaView style={styles.container}>
<View style={{height: 200, position: 'absolute'}}>
<ScrollView
horizontal
style={{height: 200, }}
>
<View style={{flexDirection: 'row'}}>
<View style={styles.cardStyles}>
<Text>item 1</Text>
</View>
<View style={styles.cardStyles}>
<Text>item 2</Text>
</View>
<View style={styles.cardStyles}>
<Text>item 3</Text>
</View>
</View>
</ScrollView>
</View>
<View style={{flex: 1, marginTop: 10}}>
<MaskedView element={<MaskedElement />}>
<View style={{top: 100, }}>
<VerticalScrollView />
</View>
</MaskedView>
</View>
</SafeAreaView>
);
VerticalScrollView.js
<View style={{flex: 1}}>
<ScrollView style={{overflow: 'visible'}}>
<View style={styles.cardStyles}>
<Text>item 1</Text>
</View>
<View style={styles.cardStyles}>
<Text>item 2</Text>
</View>
<View style={styles.cardStyles}>
<Text>item 3</Text>
</View>
<View style={styles.cardStyles}>
Text>item 4</Text>
</View>
<View style={styles.cardStyles}>
Text>item 5</Text>
</View>
</ScrollView>
</View>
MaskedView.js
export default ({element, children}) => <MaskedView
style={styles.container}
maskElement={element}
>
{children}
</MaskedView>
2
Answers
Just write like the following:
Write the
MaskedView
component like this:Then write your main
App.js
file like this:TL;DR: Put the horizontal inside the MaskedView, Or something like this.
To ensure that the vertical ScrollView does not obstruct touch events for the horizontal ScrollView when it does not overlap it in order to resolve this problem. We can use the pointer Events property to accomplish this. If there is no content obstructing the horizontal ScrollView, that guarantee that touch events flow through the view containing the vertical ScrollView by setting pointerEvents to ‘box-none’. These only functions, though, if the overlying material is transparent.
PointerEvents="box-none" is the explanation. In other words, touch events can now flow through the vertical ScrollView’s container unless something (such a view or other element) is obstructing the space. Touch events are blocked by overlapping vertical scroll content; when there is no overlap, the touch events flow through to the horizontal scroll.
zIndex on Horizontal ScrollView: To guarantee that the horizontal scroll is presented above any other content that may occur below it, I set zIndex: 1 on the View that contains it. This is useful when the vertical scroll’s content doesn’t overlap.