Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React native onPress with TouchableOpacity combined with elevation show ugly shadow

Using RN 0.63.4 and trying to implement a touchable card in Android environment.

The code is pretty simple:

<TouchableOpacity onPress={() => handlePress()}>
    <ArticleContainer>
        ....
    </ArticleContainer>
</TouchableOpacity>

This is the CSS for the ArticleContainer

const ArticleContainer = styled.View`
    height: 170px;
    width: 320px;
    border-radius: 11px;
    padding: 13px;
    margin: 20px 15px 10px 20px;
    elevation: 5;
    background-color: white;
`;

The UI looks fine when not touched, even the elevation looks pretty good:

enter image description here

But when trying to touch it, it becomes so ugly, look at the weird shadows and border:

enter image description here

Found only a few answers in StackOverflow and one in the official GitHub which both didn't work for me.

Is there is a way to solve that?

like image 657
SpazaM Avatar asked Mar 09 '26 08:03

SpazaM


2 Answers

Solution:

I recently faced similar issue. What worked for me was to apply shadows on TouchableOpacity instead of the View inside it.

What was causing the issue?

Not sure about it, but I think that when the shadows were applied on View, the TouchableOpacity will drop the opacity of its child i.e View on being pressed, which somehow did not effect its shadows, leaving them exposed.

That being said I am really not sure about why applying shadows to TouchableOpacity worked.

Other possible cause/solution

  • backgroundColor - In many cases not setting a background color on the component with shadows, causes shadows to not behave properly. Just set it to transparent if you don't want any background color.

Note:

The solution worked for me but I am not sure if it is the best solution or even if it will work for you as the behavior might be different depending on the platform and also if you are using expo.

  • I personally was NOT using expo and was testing my application on Android

Edit:

I tried to reproduce the issue and apply the solution on expo. Below images shows TouchableOpacity in a pressed state.

Shadow on child View Shadow on TouchableOpacity

like image 199
Harsh Kasodariya Avatar answered Mar 11 '26 09:03

Harsh Kasodariya


I've faced the exact same problem. Just found that it was caused by the elevation in the style. Removed it and solved.

Edit

elevation + TouchableOpacity = ugly.

Found a better solution. I use TouchableNativeFeedback for Android, and TouchableOpacity for iOS.

With TouchableNativeFeedback, you need to set background and useForeground props. Note that you also need to set overflow: hidden to the inner view. More details here.

Here's my card view:

interface Props extends TouchableWithoutFeedbackProps {
  style?: ViewStyle;
  children?: React.ReactNode;
}

export default function CardView({style, children, onPress}: Props) {
  const card = (
    <View
      style={{
        shadowColor: 'gery',
        backgroundColor: 'white',
        padding: 18,
        overflow: Platform.OS === 'android' ? 'hidden' : 'visible',

        // iOS
        shadowOffset: {width: 0, height: 2},
        shadowRadius: 18,
        shadowOpacity: 0.2,
        borderRadius: 12,

        // Android
        elevation: 8,

        ...style,
      }}>
      {children}
    </View>
  );

  if (Platform.OS === 'android') {
    return (
      <TouchableNativeFeedback
        onPress={e => onPress?.call(undefined, e)}
        background={TouchableNativeFeedback.Ripple('#00000040', false)}
        useForeground={true}>
        {card}
      </TouchableNativeFeedback>
    );
  } else {
    return (
      <TouchableOpacity
        onPress={e => onPress?.call(undefined, e)}
        activeOpacity={0.5}>
        {card}
      </TouchableOpacity>
    );
  }
}

like image 45
Potados Avatar answered Mar 11 '26 09:03

Potados



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!