【问题标题】:React native onPress with TouchableOpacity combined with elevation show ugly shadowReact native onPress with TouchableOpacity 结合海拔显示丑陋的阴影
【发布时间】:2021-05-17 18:37:00
【问题描述】:

使用RN 0.63.4 并尝试在Android 环境中实现可触摸卡片。

代码很简单:

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

这是ArticleContainer的CSS

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

不触摸时 UI 看起来还不错,甚至海拔看起来也不错:

但是当试图触摸它时,它变得如此丑陋,看看奇怪的阴影和边框:

在 StackOverflow 中只找到了几个答案,在官方 GitHub 中找到了一个,这两个都对我不起作用。

有办法解决吗?

【问题讨论】:

    标签: reactjs react-native styled-components


    【解决方案1】:

    解决办法:

    我最近遇到了类似的问题。对我有用的是在TouchableOpacity 上而不是在其中的View 上应用阴影。

    导致问题的原因是什么?

    不确定,但我认为当在View 上应用阴影时,TouchableOpacity 将降低其子元素的不透明度,即在按下时View,不知何故不会影响它的阴影,离开他们暴露了。

    话虽如此,我真的不确定为什么将阴影应用到 TouchableOpacity 有效。

    其他可能的原因/解决方案

    • backgroundColor - 在许多情况下,没有在带有阴影的组件上设置背景颜色,会导致阴影无法正常运行。如果您不想要任何背景颜色,只需将其设置为透明即可。

    注意:

    该解决方案对我有用,但我不确定它是否是最佳解决方案,或者即使它是否适合您,因为行为可能会因平台以及您使用 expo的不同而有所不同>.

    • 我个人使用 expo 并且正在 Android 上测试我的应用程序

    编辑:

    我试图重现该问题并将解决方案应用于 expo。下图显示处于按下状态的TouchableOpacity

    【讨论】:

      【解决方案2】:

      我也遇到过同样的问题。刚发现是样式里的elevation引起的。删除并解决。

      编辑

      elevation + TouchableOpacity = 丑陋。

      找到了更好的解决方案。我在 Android 上使用 TouchableNativeFeedback,在 iOS 上使用 TouchableOpacity

      使用TouchableNativeFeedback,您需要设置backgrounduseForeground 属性。请注意,您还需要将overflow: hidden 设置为内部视图。更多详情here.

      这是我的卡片视图:

      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>
          );
        }
      }
      
      

      【讨论】:

        【解决方案3】:

        您可以使用 TouchableOpacity 的 activeOpacity 属性(默认值为 0.2)并将 backfaceVisibility: 'hidden' 添加到您的 ArticleContainer 样式中。 或者您可以使用 touchablewithoutfeedback,这应该可以解决问题。

        【讨论】:

        • activeOpacity with backfaceVisibility: 'hidden' 看起来仍然很难看。并且 touchablewithoutfeedback 对我没有帮助,因为现在我没有按下的迹象。
        • 那我会尝试使用TouchableHighlight,它可能看起来比使用TouchableOpacity 更好。它们之间有什么区别: TouchableHighlight:它使按下时元素的背景变暗或变亮 - 取决于定义的 activeOpacity。 TouchableOpacity:按下时减轻整个元素的不透明度。
        猜你喜欢
        • 2016-10-18
        • 2015-08-22
        • 2015-02-13
        • 1970-01-01
        • 2015-02-14
        • 2016-11-11
        • 1970-01-01
        • 2016-02-03
        • 2018-08-20
        相关资源
        最近更新 更多