React Native文本溢出屏幕,拒绝自动换行。该怎么办?

312
以下代码可以在这个实例中找到。
我有以下的React Native元素:
'use strict';

var React = require('react-native');
var {
  AppRegistry,
  StyleSheet,
  Text,
  View,
} = React;

var SampleApp = React.createClass({
  render: function() {
    return      (
  <View style={styles.container}>

        <View style={styles.descriptionContainerVer}>
          <View style={styles.descriptionContainerHor}>
            <Text style={styles.descriptionText} numberOfLines={5} >
              Here is a really long text that you can do nothing about, its gonna be long wether you like it or not, so be prepared for it to go off screen. Right? Right..!
            </Text>
          </View>
        </View>

        <View style={styles.descriptionContainerVer2}>
          <View style={styles.descriptionContainerHor}>
            <Text style={styles.descriptionText} numberOfLines={5} >Some other long text which you can still do nothing about.. Off the screen we go then.</Text>
          </View>
        </View>



  </View>);
  }
});
AppRegistry.registerComponent('SampleApp', () => SampleApp);

带有以下样式:
var styles = StyleSheet.create({
  container:{
        flex:1,
    flexDirection:'column',
        justifyContent: 'flex-start',
        backgroundColor: 'grey'
    },
    descriptionContainerVer:{
    flex:0.5, //height (according to its parent)
    flexDirection: 'column', //its children will be in a row
    alignItems: 'center',
    backgroundColor: 'blue',
    // alignSelf: 'center',
  },
  descriptionContainerVer2:{
    flex:0.5, //height (according to its parent)
    flexDirection: 'column', //its children will be in a row
    alignItems: 'center',
    backgroundColor: 'orange',
    // alignSelf: 'center',
  },
  descriptionContainerHor:{
    //width: 200, //I DON\'T want this line here, because I need to support many screen sizes
    flex: 0.3,  //width (according to its parent)
    flexDirection: 'column',    //its children will be in a column
    alignItems: 'center', //align items according to this parent (like setting self align on each item)
    justifyContent: 'center',
    flexWrap: 'wrap'
  },
  descriptionText: {
    backgroundColor: 'green',//Colors.transparentColor,
    fontSize: 16,
    color: 'white',
    textAlign: 'center',
    flexWrap: 'wrap'
  }
});

这将导致以下屏幕显示:

Text off screen app

如何避免文本超出屏幕并将其限制在屏幕中央,宽度为父元素的80%。

我认为不应该使用width,因为我将在许多不同的移动屏幕上运行它,并且希望它是动态的,因此我认为应完全依赖于flexbox

(这就是为什么我在descriptionContainerHor中使用了flex:0.8的初始原因。

我想要实现的效果类似于这样:

What I want to achieve

谢谢!

25个回答

503

我从下面的链接中找到了解决方案。

[Text] 文本不换行 #1438

<View style={{flexDirection:'row'}}> 
   <Text style={{flex: 1, flexWrap: 'wrap'}}> You miss fdddddd dddddddd 
     You miss fdd
   </Text>
</View>

输出

以下是Github个人资料链接,如果您想要感谢他。

Ally Rippley


编辑:2019年4月9日星期二

如@sudopLz在评论中提到的,使用flexShrink:1更新这个答案。

输入图像描述


1
谢谢,这是一个很好的答案,但我已经尝试过了,出于某些原因它并不总是有效(我也不知道原因:S)。在React Native中,flexWrap有点不太可靠。非常感谢您提出这个观点。 - SudoPlz
1
接受这个操作!这是实际的答案。 - Greg Blass
1
请注意此答案的信息部分 https://github.com/facebook/react-native/issues/1438#issuecomment-278745825 - SudoPlz
55
我发现,在某些情况下,将flexShrink:1应用于父视图也有帮助。 - SudoPlz
flexShrink: 1,然后对文本添加一些填充即可完成任务。 - Diego Ponciano
显示剩余3条评论

237

那个问题的解决方案是 flexShrink: 1

<View
    style={{ flexDirection: 'row' }}
> 
   <Text style={{ flexShrink: 1 }}>
       Really really long text...
   </Text>
</View>

根据您的设置,您可能还需要将flexShrink: 1添加到 <View> 的父级中,以使其起作用,因此请尝试一下,您就能做到。

该解决方案是由Adam Pietrasiak此线程中发现的。


5
父视图对我也是一个解决方案!如果父视图具有flexDirection: 'column',则文本将拒绝换行。 - crestinglight

114

这是已知的错误。我的情况下,flexWrap: 'wrap'无效,但这个解决方案似乎适用于大多数人。

代码

<View style={styles.container}>
    <Text>Some text</Text>
</View>

样式

export default StyleSheet.create({
    container: {
        width: 0,
        flexGrow: 1,
        flex: 1,
    }
});

4
我花了一整天的时间才找到了你的答复...谢谢! - Kevin Amiranoff
我的安卓模拟器会在单行文本超出边界时彻底冻结。这是一个很难找到和解决的可怕 bug(这个并不相关的 SO 问题是我找到的唯一线索)。现在看来,加入了容器 {flexGrow:1,flex:1} 和文本 {flex:1} 后问题已经得到解决。 - Henrique Bruno
这对我在 "react-native": "0.68.2" 上有效。 - Syed Amir Ali

58

你只需要像下面这样为你的 <Text> 设置一个 flex 包装器即可:

<View style={{ flex: 1 }}>
  <Text>Your Text</Text>
</View>

2
这是唯一正确的解决方案,而且实际上也有效。 - AlwaysConfused
3
确实,flex: 1 就足够了。 - instanceof
如果您不想让文本占用所有可用空间怎么办? - huseyin39
只有<Text style={{ flex: 1 }}>没有额外的<View>对我也起作用。 - sihaya
这对于我来说在处理大段文字时有效。但是对于小段文字,它会添加空格。flexShrink: 1 在这两种情况下都解决了我的问题。 - Lucas Basquerotto

45

这对我起作用了

<View style={{flexShrink:1}}>
  <Text>some long random text...</Text>
</View>

我有一个复杂的结构,出于某种原因,这个可以工作,其他答案不行哈哈。 - Vortechron
在所有的解决方案中,只有这个对我有效。 - John

42

大多数情况下,我们在使用flexDirection:'row'时会遇到这个问题,因为在其他情况下,它会被正确处理。

无论如何,这里有两种正确换行文本的方法:

第一种方法:

要将文本换行并不让其离开显示区域,我们可以通过限制<Text>的宽度来实现;

<Text style={{width: "60%"}}>some long text goes here ...</Text>

上述代码将限制文本的宽度为可用宽度的60%,如果整个文本无法适应,则会自动换行,即其余文本将移至下一行,以此类推。

第二种方法

在文本元素及其包装它的父元素上设置flexShrink: 1

例如,

<View style={{ flexShrink: 1, justifyContent: 'space-between', alignItems: 'center', flex: 1, flexDirection: 'row'}}>
    <Text>First long string which goes long....</Text>
    <Text style={{flexShrink: 1}}>This is a long long text which must go out of the screen if we dont style it properly and not do some logic here</Text>
</View>

其他样式只是为了展示结果是否正常工作。 flexShrink: 1 是你唯一需要的东西。


14

我发现的另一种解决此问题的方法是将Text放在View中,同时将View的样式设置为flex: 1。


14

我也遇到了类似的问题,解决方法是确保所有的视图父组件都有样式style={{flex: 1}}。


1
这就是你要找的答案。 - undefined

13

如果从 descriptionContainerVerdescriptionContainerVer2 中分别移除 flexDirection: row,它就会起作用。

更新(请参见评论)

我进行了一些更改,以实现我认为您想要的效果。首先,我删除了 descriptionContainerHor 组件。然后,我将垂直视图的 flexDirection 设置为 row 并添加了 alignItems: 'center'justifyContent: 'center'。由于垂直视图现在实际上沿水平轴堆叠,因此我从名称中删除了 Ver 部分。

因此,现在您有一个包装器视图,应该可以垂直和水平对齐其内容并沿 x 轴堆叠它们。然后,我只是在 Text 组件的左侧和右侧放置了两个不可见的 View 组件来进行填充。

像这样:

<View style={styles.descriptionContainer}>
  <View style={styles.padding}/>
    <Text style={styles.descriptionText} numberOfLines={5} >
      Here is a really long text that you can do nothing about, its gonna be long wether you like it or not, so be prepared for it to go off screen. Right? Right..!
    </Text>
  <View style={styles.padding}/>
</View>

还有这个:

descriptionContainer:{
  flex:0.5, //height (according to its parent),
  flexDirection: 'row',
  backgroundColor: 'blue',
  alignItems: 'center',
  justifyContent: 'center',
  // alignSelf: 'center',
},
padding: {
  flex: 0.1
},
descriptionText: {
  backgroundColor: 'green',//Colors.transparentColor,
  fontSize: 16,
  flex: 0.8,
  color: 'white',
  textAlign: 'center',
  flexWrap: 'wrap'
},

那么您现在得到了我认为你想要的东西。

更进一步的改进

如果您想在蓝色和橙色视图中堆叠多个文本区域,可以尝试以下操作:

<View style={styles.descriptionContainer2}>
  <View style={styles.padding}/>
  <View style={styles.textWrap}>
    <Text style={styles.descriptionText} numberOfLines={5} >
      Some other long text which you can still do nothing about.. Off the screen we go then.
    </Text>
    <Text style={styles.descriptionText} numberOfLines={5} >
      Another column of text.
    </Text>
  </View>
  <View style={styles.padding}/>
</View>

其中textWrap的样式如下:

textWrap: {
  flexDirection: 'column',
  flex: 0.8
},

希望这能帮到你!


好的,我稍微修改了问题以反映我真正想要实现的内容。 现在关于答案:我使用flexDirection: row的原因是(如果我记得没错的话)flexDirection决定了父元素的“子元素”将被堆叠的方向。 现在我希望文本成为一个父元素中的中间子元素,该父元素按行堆叠子元素,并占用父元素宽度的80%(类似第二张照片)。您能否稍微更新一下答案以反映这一点?我愿意接受这个答案。 - SudoPlz
抱歉回复晚了,最近很忙。但是我已经更新了我的答案,希望这是你所需要的。 - Eysi
这个答案绝对棒极了!正是我一直在寻找的,谢谢Elliot!!! - SudoPlz
"flexDirection: 'row'" 是我的问题核心,尝试了其他所有方法都没有成功。将您的 "flexDirection" 更改为 "column",它内部的文本将正常换行。 - eightyfive

12
<View style={{flexDirection:'row'}}> 
  <Text style={{flex: 1, flexWrap: 'wrap'}}> 

这会起作用


Flexwrap是不必要的。 - Steve Moretz

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接