React Native 中的聊天气泡

Posted

技术标签:

【中文标题】React Native 中的聊天气泡【英文标题】:Chat Bubble in React Native 【发布时间】:2018-11-01 02:10:03 【问题描述】:

我目前正在 react-native 中制作聊天气泡。由于我是 react-native 的新手,我首先尝试在浏览器上制作聊天气泡,然后尝试在 react-native 中复制相同的内容。我正在努力在 react-native 中复制箭头。有什么想法/建议吗?

普通 HTML/CSS:

<div>
  <p class="to-me">Hey!</p>
</div>

div 
  padding:20px;
  justify-self: center;
  align-self: center;
  text-align: left;
  display: flex;
  flex-direction: column;
  width: 450px;

div p 
  font-size: 16px;
  line-height: 1.4;
  margin: 1px 0;
  padding: 8px 17px 6px 13px;
  max-width: 380px;
  position: relative;
  border-radius: 18px;

div p:after 
  position: absolute;
  content: "";
  top: 0;
  bottom: 0;
  right: 0;
  left: 0;
  z-index: -1;

div p.to-me 
  color: black;
  align-self: flex-start;
  background-color: #E5E5EA;

div p.to-me:after 
  background: url("data:image/svg+xml;charset=utf-8,<svg xmlns='http://www.w3.org/2000/svg' x='0px' y='0px' width='15.515px' height='17.5px' viewBox='32.484 17.5 15.515 17.5' enable-background='new 32.484 17.5 15.515 17.5'><path fill='#E5E5EA' d='M38.484,17.5c0,8.75,1,13.5-6,17.5C51.484,35,52.484,17.5,38.484,17.5z'/></svg>") left bottom no-repeat;
  left: -6px;

结果:

React-Native 版本:

<View style=[styles.balloon, backgroundColor: '#1084ff']>
      <Text style=paddingTop: 5, color: 'white'>Hey!</Text>
      <View
      style=[
        styles.arrowContainer,
        styles.arrowLeftContainer,
      ]
    >
      <View style=styles.arrowLeft />
    </View>
    </View>
  </View>


item: 
   marginVertical: 14,
   flexDirection: 'row'
,
itemIn: 
    marginLeft: 10
,
itemOut: 
   alignSelf: 'flex-end',
   marginRight: 10
,
balloon: 
   maxWidth: scale(250),
   paddingHorizontal: 15,
   paddingTop: 10,
   paddingBottom: 15,
   borderRadius: 20,
,
arrowContainer: 
    position: 'absolute',
    top: 0,
    left: 0,
    right: 0,
    bottom: 0,
    zIndex: -1
    // backgroundColor: 'red'
,
arrowLeftContainer: 
    justifyContent: 'center',
    alignItems: 'flex-start',
    // backgroundColor: 'green'
,

arrowLeft: 
    left: -20,

结果:

我几乎复制了泡沫。只是在箭头部分挣扎。有什么想法/建议吗?

【问题讨论】:

我很确定这是不可行的 atm 或者这将是一个很大的痛苦...原因是 androidios 在溢出等方面的行为不同。也许这个组件会帮助你@ 987654323@ 但即使你让它不能 100% 相同。我建议不要带箭头 是的,你是对的。它看起来不一样。检查我的答案:) 【参考方案1】:

让箭头出现比我想象的要难,尤其是考虑到不同的屏幕尺寸、不同的平台(iOS 和 android)。是的,@Panagiotis Vrs 提到它在两个平台上看起来不会 100% 相同时是正确的。尽管如此,我还是尝试使用react-native-svg 和react-native-size-matters 来达到同样的效果。

我正在分享我的代码,也许有人可以即兴创作并让它变得更好。

HTML 部分

<View style=[styles.item, styles.itemIn]>
        <View style=[styles.balloon, backgroundColor: 'grey']>
          <Text style=paddingTop: 5, color: 'white'>Hey! How are you?</Text>
          <View
          style=[
            styles.arrowContainer,
            styles.arrowLeftContainer,
          ]
        >

           <Svg style=styles.arrowLeft width=moderateScale(15.5, 0.6) height=moderateScale(17.5, 0.6) viewBox="32.484 17.5 15.515 17.5"  enable-background="new 32.485 17.5 15.515 17.5">
                <Path
                    d="M38.484,17.5c0,8.75,1,13.5-6,17.5C51.484,35,52.484,17.5,38.484,17.5z"
                    fill="grey"
                    x="0"
                    y="0"
                />
            </Svg>
        </View>
        </View>
      </View>


      <View style=[styles.item, styles.itemOut]>
        <View style=[styles.balloon, backgroundColor: '#1084ff']>
          <Text style=paddingTop: 5, color: 'white'>Hey! I am good. How are you?</Text>
          <View
          style=[
            styles.arrowContainer,
            styles.arrowRightContainer,
          ]
        >
           <Svg style=styles.arrowRight width=moderateScale(15.5, 0.6) height=moderateScale(17.5, 0.6) viewBox="32.485 17.5 15.515 17.5"  enable-background="new 32.485 17.5 15.515 17.5">
                <Path
                    d="M48,35c-7-4-6-8.75-6-17.5C28,17.5,29,35,48,35z"
                    fill="#1084ff"
                    x="0"
                    y="0"
                />
            </Svg>
        </View>
        </View>
      </View>





       <View style=[styles.item, styles.itemOut]>
        <View style=[styles.balloon, backgroundColor: '#1084ff']>
          <Text style=paddingTop: 5, color: 'white'>Check this Image out !!!</Text>
          <View
          style=[
            styles.arrowContainer,
            styles.arrowRightContainer,
          ]
        >
           <Svg style=styles.arrowRight width=moderateScale(15.5, 0.6) height=moderateScale(17.5, 0.6) viewBox="32.485 17.5 15.515 17.5"  enable-background="new 32.485 17.5 15.515 17.5">
                <Path
                    d="M48,35c-7-4-6-8.75-6-17.5C28,17.5,29,35,48,35z"
                    fill="#1084ff"
                    x="0"
                    y="0"
                />
            </Svg>
        </View>
        </View>
      </View>


       <View style=[styles.item, styles.itemOut]>
        <View style=[styles.balloon, backgroundColor: '#1084ff']>

        <Image
            styleName="small"
            borderRadius=5
            source= uri: 'https://shoutem.github.io/img/ui-toolkit/examples/image-3.png'
            />
          <View
          style=[
            styles.arrowContainer,
            styles.arrowRightContainer,
          ]
        >
           <Svg style=styles.arrowRight width=moderateScale(15.5, 0.6) height=moderateScale(17.5, 0.6) viewBox="32.485 17.5 15.515 17.5"  enable-background="new 32.485 17.5 15.515 17.5">
                <Path
                    d="M48,35c-7-4-6-8.75-6-17.5C28,17.5,29,35,48,35z"
                    fill="#1084ff"
                    x="0"
                    y="0"
                />
            </Svg>
        </View>
        </View>
      </View>


     <View style=[styles.item, styles.itemIn]>
        <View style=[styles.balloon, backgroundColor: 'grey']>
          <Text style=paddingTop: 5, color: 'white'>Nice Picture</Text>
          <View
          style=[
            styles.arrowContainer,
            styles.arrowLeftContainer,
          ]
        >

           <Svg style=styles.arrowLeft width=moderateScale(15.5, 0.6) height=moderateScale(17.5, 0.6) viewBox="32.484 17.5 15.515 17.5"  enable-background="new 32.485 17.5 15.515 17.5">
                <Path
                    d="M38.484,17.5c0,8.75,1,13.5-6,17.5C51.484,35,52.484,17.5,38.484,17.5z"
                    fill="grey"
                    x="0"
                    y="0"
                />
            </Svg>
        </View>
        </View>
      </View>

CSS 部分

 item: 
       marginVertical: moderateScale(7, 2),
       flexDirection: 'row'
    ,
    itemIn: 
        marginLeft: 20
    ,
    itemOut: 
       alignSelf: 'flex-end',
       marginRight: 20
    ,
    balloon: 
       maxWidth: moderateScale(250, 2),
       paddingHorizontal: moderateScale(10, 2),
       paddingTop: moderateScale(5, 2),
       paddingBottom: moderateScale(7, 2),
       borderRadius: 20,
    ,
    arrowContainer: 
        position: 'absolute',
        top: 0,
        left: 0,
        right: 0,
        bottom: 0,
        zIndex: -1,
        flex: 1
    ,
    arrowLeftContainer: 
        justifyContent: 'flex-end',
        alignItems: 'flex-start'
    ,

    arrowRightContainer: 
        justifyContent: 'flex-end',
        alignItems: 'flex-end',
    ,

    arrowLeft: 
        left: moderateScale(-6, 0.5),
    ,

    arrowRight: 
        right:moderateScale(-6, 0.5),
    

现在在不同的设备屏幕上缩放它对我来说只是反复试验。现在的输出对我来说已经足够了。也许当我有时间时,我会尝试改进当前的设计。

这是它在 iOS 上的样子:

iPhone 7:

iPhone X:

不幸的是,现在在 android 上我无法使箭头的曲线出现。也许我做错了什么。这就是它最终的样子。

像素 2:

Nexus 6:

也许我们可以使用flex 让箭头曲线在android 上看起来不错。

如果有人对此做了更好的版本。分享。 :)

【讨论】:

【参考方案2】:

您可以在不使用 SVG 的情况下合并它。这基本上是通过将&lt;View&gt; 组件锚定在文本容器的角落来完成的。

<View style=
                    backgroundColor: "#0078fe",
                    padding:10,
                    marginLeft: '45%',
                    borderRadius: 5,
                    marginTop: 5,
                    marginRight: "5%",
                    maxWidth: '50%',
                    alignSelf: 'flex-end',
                    
                    
                    borderRadius: 20,
                  >
  
                    
                    <Text style= fontSize: 16, color: "#fff",  key=index>item.text</Text>
  
                      <View style=styles.rightArrow></View>
                      
                      <View style=styles.rightArrowOverlap></View>
                    
                    
                    
</View> 


const styles = StyleSheet.create(
rightArrow: 
  position: "absolute",
  backgroundColor: "#0078fe",
  //backgroundColor:"red",
  width: 20,
  height: 25,
  bottom: 0,
  borderBottomLeftRadius: 25,
  right: -10
,

rightArrowOverlap: 
  position: "absolute",
  backgroundColor: "#eeeeee",
  //backgroundColor:"green",
  width: 20,
  height: 35,
  bottom: -6,
  borderBottomLeftRadius: 18,
  right: -20

,

borderRadiusmaxWidthmargin 等属性值是任意的,可以根据您的需要进行更改。 您可以参考this 文章,我在其中对此进行了深入的解释。 警告:将此与 FlatList 一起使用,因为观察到与其他功能(例如:地图)的呈现不一致

【讨论】:

【参考方案3】:

您可以使用 react-native-gifted-chat 库来制作完美的气泡 或者如果你想让客户冒泡,那么在平面列表渲染项中使用 react-native 的平面列表制作气泡 根据 id 发送者 id 或接收者 id 对齐气泡

【讨论】:

以上是关于React Native 中的聊天气泡的主要内容,如果未能解决你的问题,请参考以下文章

如何通过反应原生天才聊天设置气泡中显示的图像尺寸?

react-native聊天室|RN版聊天App仿微信实例|RN仿微信界面

我如何在 react-native 聊天应用程序中使用 GraphQl 订阅从 GraphQl 查询中获取实时更新

react-native FlatList 滚动到底部的聊天应用程序

Expo 中用于 React Native 的 Dialogflow API 聊天机器人

如何在 expo 的 React Native 天才聊天中设置用户头像?