React Native聊天bubble flexbox类似于whatsapp

时间:2018-01-08 16:18:06

标签: react-native

我尝试在类似于Whatsapp UI的React Native中创建聊天视图。 我无法绕过的是 - 如何做时间。以下是Whatsapp的外观: enter image description here

请注意,时间本身不是一条全新的线,而是半条线。

在上一个评论的同时,您可以看到,如果文本足够长,则时间将被推送到新行。

我尝试了几件事:

  1. 使气泡相对,然后在时间元素上使用绝对定位。不幸的是,如果文本足够长,我的时间会与文本重叠。

  2. 制作bubble flexDirection:" row",然后在1个视图中显示文本,在另一个视图中显示时间。但是,当文本足够长时,我无法弄清楚如何强制换行"。

  3. 任何想法如何实现这一目标?

1 个答案:

答案 0 :(得分:0)

我设法得到了我想要的东西。它与whatsapp不是100%相同,但足够好。

我有以下代码:

  <View style={{
      margin: 10, marginTop: 10, marginBottom: 0,
      padding: 10, borderRadius: 5, paddingBottom: 10,
      backgroundColor: cropType ? '#93D14C' : '#F1F0F5'
    }}>
        {this.renderContent(comment)}

      <Text
        style={[styles.muted,
          {
            color: constants.FJMUTEDLIGHT,
            backgroundColor: 'transparent',
            alignSelf: 'flex-end',
            fontSize: 12,
            marginBottom: -5,
            marginTop: 2
          }]}>{moment.utc(comment.created).local().format('HH:mm')}</Text>
    </View>

renderContentHere()函数可以渲染Text,但它也可以渲染包含文本的复杂View。最初我想弄清楚文本有多少行并计算行的宽度。这似乎不可能使用React Native,因为Text节点上的onLayout属性只能告诉您元素的宽度和高度,但如果Text是2行或3行则不能。

所以我决定只测量包含注释的View,并确定它是否有一行或多行。如果它有一条线,我假设我可以把时间放在比正常情况稍高的位置。

这就是我最终做的事情:

<View style={{
          margin: 10, marginTop: 10, marginBottom: 0,
          padding: 10, borderRadius: 5, paddingBottom: 10,
          backgroundColor: cropType ? '#93D14C' : '#F1F0F5'
        }}>

          <View style={this.state.oneLine ? {
            // Since we don't know how long the one line is, just in case add 25px padding on the right
            // this way even if we are dealing with a long line of text it won't end up over the time
            paddingRight: 25
          } : {}}
                onLayout={(e) => {
                  let {height} = e.nativeEvent.layout

                  // if height is less than 30px, then we are dealing with a single line of content
                  if (height < 30) {
                    this.setState({'oneLine': true})
                  }
                }}>

            {this.renderContent(comment)}

          </View>

          <Text
            style={[styles.muted,
              {
                color: constants.FJMUTEDLIGHT,
                backgroundColor: 'transparent',
                alignSelf: 'flex-end',
                fontSize: 12,
                marginBottom: -5,
                // If one line, move the time up - there is enough space
                marginTop: this.state.oneLine ? -10 : 2
              }]}>{moment.utc(comment.created).local().format('HH:mm')}</Text>
        </View> 

如果我们只有一行,那么文本最终可能会落后于时间,这就是为什么我在25 px的文本上应用正确的填充。这会打破长线,我们最终得到这样的视图: enter image description here