安卓:textview的最后一行被截断

122

我有一个水平的 LinearLayout,其中包含一个 TextView 接着是旁边的一个 Spinner。该 LinearLayout 动态地被多次充气到固定垂直的 LinearLayout 中,后者包含在一个 RelativeLayout 中。

问题是,自从我从 Theme.light 切换到 Theme.holo.lightTextView 的最后一行被切成了两半。这种情况发生在动态文本很长且跨越多行时。

enter image description here

我已经通过为水平的 LinearLayout 增加底部填充来解决了这个问题。

但这似乎不像是一种真正的解决方法,更像是一种 hack。请问是否有人可以给我一些关于如何正确解决这个问题的建议?

我已经阅读了其他一些相关问题,但没有一个能帮助我。

水平线性布局:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:orientation="horizontal">

    <TextView
        android:id="@+id/textView1"
        android:layout_width="150dp"
        android:layout_height="wrap_content"
        android:layout_marginRight="20dp"
        android:text="TextView"/>

    <Spinner
        android:id="@+id/spinner1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>

</LinearLayout>

在线性布局中动态填充上面的布局,该布局为相对布局,其id为ll2_7:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <ScrollView
        android:id="@+id/scrollView"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_above="@+id/relLayoutButtonNext"
        android:layout_below="@id/textView1" >

        <RelativeLayout
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:paddingBottom="20dp"
            android:paddingLeft="10dp"
            android:paddingRight="10dp"
            android:paddingTop="10dp" >

            <TextView
                android:id="@+id/textView10"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:paddingRight="30dp"
                android:text="2.7" />

            <TextView
                android:id="@+id/textView11"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginBottom="10dp"
                android:layout_toRightOf="@id/textView10"
                android:text="@string/question2_7" />


            <LinearLayout
                android:id="@+id/ll2_7"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_alignLeft="@+id/textView11"
                android:layout_below="@+id/textView11"
                android:orientation="vertical" android:layout_marginBottom="20dp">
            </LinearLayout>

        </RelativeLayout>

    </ScrollView>

</RelativeLayout>

编辑: 以下是上述布局xml的完整代码:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <TextView
        android:id="@+id/textView1"
        style="@style/question_section_title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_alignParentTop="true"
        android:text="@string/question2_header" />

    <RelativeLayout
        android:id="@+id/relLayoutButtonNext"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:background="@color/bottomBar"
        android:paddingBottom="3dp"
        android:paddingLeft="50dp"
        android:paddingRight="50dp"
        android:paddingTop="3dp" >

        <Button
            android:id="@+id/buttonNext"
            android:layout_width="180dp"
            android:layout_height="wrap_content"
            android:layout_alignParentRight="true"
            android:onClick="nextStep"
            android:text="Next Section"
            android:textSize="20sp" />

        <Button
            android:id="@+id/buttonPrevious"
            android:layout_width="180dp"
            android:layout_height="wrap_content"
            android:layout_alignParentLeft="true"
            android:layout_alignParentTop="true"
            android:onClick="previousStep"
            android:text="Previous Section"
            android:textSize="20sp" />
    </RelativeLayout>


    <ScrollView
        android:id="@+id/scrollView"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_above="@+id/relLayoutButtonNext"
        android:layout_below="@id/textView1" >



        <RelativeLayout
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:paddingBottom="20dp"
            android:paddingLeft="10dp"
            android:paddingRight="10dp"
            android:paddingTop="10dp" >

            <TextView
                android:id="@+id/textView10"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:paddingRight="30dp"
                android:text="2.7" />

            <TextView
                android:id="@+id/textView11"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginBottom="10dp"
                android:layout_toRightOf="@id/textView10"
                android:text="@string/question2_7" />


            <LinearLayout
                android:id="@+id/ll2_7"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_alignLeft="@+id/textView11"
                android:layout_below="@+id/textView11"
                android:orientation="vertical" android:layout_marginBottom="20dp">

            </LinearLayout>

            <TextView
                android:id="@+id/textView2"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_alignLeft="@+id/textView10"
                android:layout_below="@+id/ll2_7"
                android:text="2.8" />

            <TextView
                android:id="@+id/textView3"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_below="@+id/ll2_7"
                android:layout_toRightOf="@+id/textView10"
                android:text="@string/question2_8" android:layout_marginBottom="10dp"/>


            <LinearLayout
                android:id="@+id/ll2_8"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_alignLeft="@+id/textView3"
                android:layout_below="@+id/textView3"
                android:layout_marginBottom="20dp"
                android:orientation="vertical" >

            </LinearLayout>

            <TextView
                android:id="@+id/textView4"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_alignLeft="@+id/textView2"
                android:layout_below="@+id/ll2_8"
                android:text="2.9" />

            <TextView
                android:id="@+id/textView5"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_below="@+id/ll2_8"
                android:layout_toRightOf="@+id/textView10"
                android:text="@string/question2_9" android:layout_marginBottom="10dp"/>


            <LinearLayout
                android:id="@+id/ll2_9"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_below="@+id/textView5"
                android:layout_toRightOf="@+id/textView10"
                android:orientation="vertical" android:layout_marginBottom="20dp">

            </LinearLayout>

            <TextView
                android:id="@+id/textView6"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_alignLeft="@+id/textView4"
                android:layout_below="@+id/ll2_9"
                android:text="2.10" />

            <TextView
                android:id="@+id/textView7"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_below="@+id/ll2_9"
                android:layout_toRightOf="@+id/textView10"
                android:text="@string/question2_10" android:layout_marginBottom="10dp"/>


            <LinearLayout
                android:id="@+id/ll2_10"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_below="@+id/textView7"
                android:layout_marginBottom="20dp"
                android:layout_toRightOf="@+id/textView10"
                android:orientation="vertical" >

            </LinearLayout>

            <TextView
                android:id="@+id/textView8"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_alignLeft="@+id/textView6"
                android:layout_below="@+id/ll2_10"
                android:text="2.11" />

            <TextView
                android:id="@+id/textView9"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_below="@+id/ll2_10"
                android:layout_toRightOf="@+id/textView10"
                android:text="@string/quesiton2_11" android:layout_marginBottom="10dp"/>


            <LinearLayout
                android:id="@+id/ll2_11"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_alignLeft="@+id/textView9"
                android:layout_below="@+id/textView9"
                android:orientation="vertical" android:layout_marginBottom="20dp">

            </LinearLayout>

            <TextView
                android:id="@+id/textView12"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_alignLeft="@+id/textView8"
                android:layout_below="@+id/ll2_11"
                android:text="2.11.1" />

            <TextView
                android:id="@+id/textView13"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_below="@+id/ll2_11"
                android:layout_toRightOf="@+id/textView10"
                android:text="@string/question2_11_1" android:layout_marginBottom="10dp"/>


            <LinearLayout
                android:id="@+id/ll2_11_1"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_below="@+id/textView13"
                android:layout_toRightOf="@+id/textView10"
                android:orientation="vertical" android:layout_marginBottom="20dp">

            </LinearLayout>

        </RelativeLayout>

    </ScrollView>

</RelativeLayout>

尝试删除 android:paddingBottom="20dp"。 - Dheeresh Singh
2
尝试在TextView和LinearLayout上添加填充,这样可以使界面看起来更美观。 - Aashish Bhatnagar
LinearLayout在水平方向上使用时确实存在问题。相反,应该使用ConstraintLayout。请参见https://dev59.com/ulYM5IYBdhLWcg3wjAuw#48677954。 - Dharmendra
21个回答

271

我为TextView项目应用了一个LayoutGravity:

android:layout_gravity="fill"

12
好的,我会尽力进行翻译。请注意,许多layout_gravity值都很有用,例如center_vertical。原文已经很简洁了,我将尽量保持原意,使翻译更加通俗易懂。另外,感谢您的反馈和点赞(+1)。 - Grzegorz Dev
2
如果这不起作用,添加一个填充值为“1sp”应该可以解决问题。我创建了一个扩展@android:style/Widget.TextView的样式,并添加了以下行:<item name="android:gravity">fill</item> <item name="android:padding">1sp</item> - Graeme
14
这只是一个权宜之计。正确的解决方法是在你的LinearLayout中添加android:baselineAligned="false"。 - tomrozb
1
尽管这似乎可行,但正确的解决方案是来自tomrozb上面的评论或Jusid的答案。 - Eduard B.
现在是2017年,使用wrap_content时,多行TextView仍然可能被裁剪,而您的答案仍然有效。谢谢! - Violet Giraffe
显示剩余2条评论

68
我遇到了与截图中相同的截断问题。这是由水平LinearLayout中的基线对齐引起的。TextViewSpinner由于字体大小差异具有不同的基线。为了解决此问题,需要通过设置来禁用布局的基线对齐:
android:baselineAligned="false"

或者在代码中:

layout.setBaselineAligned(false);

2
我希望我能给这个点赞100次!在过去的几天里,我浪费了太多时间在这个问题上,而你的答案是我的解决方案!由于在Android上调试视图层次结构非常困难,我很长时间没有意识到发生了什么。非常感谢!!! - mbm29414
这是我的问题的解决方案,除了Rynardt的答案之外。谢谢! - James Dobson
1
这是正确的答案,它指出了错误发生的原因。谢谢。 - Hoang Nguyen Huu
这对于像这样的情况来说是一个巨大的提示。一点也不错。谢谢! - sunlover3
非常感谢。那么,这实际上是一个 bug,对吗? - user9900987
Angga Arya S,不,这不是一个错误。只是布局的默认对齐设置会在元素文本大小不同且存在多行文本的情况下导致混淆。 - Jusid

34
我遇到了同样的问题,并发现只需添加

即可。
android:includeFontPadding="false"

这段文本的最后一行不再被剪去下降部分了。

2
使用自定义字体可能是完美的解决方案。当我使用Droid Sans日语时,这是唯一有效的解决方案。 - computingfreak

11

我通过添加一些虚拟空间来在文本后面添加了内容。

textView.setText(firstString+"\n");

我尝试了所有其他解决方案。但这是唯一对我起作用的解决方案。


这是你所说的“chepi”。 - Zulqurnain Jutt

7
我通过扩展TextView并添加自定义类来找到了不同的解决方案,如下所示:
 public class AdaptingTextView extends TextView {

    public AdaptingTextView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    public AdaptingTextView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public AdaptingTextView(Context context) {
        super(context);
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);

        // set fitting lines to prevent cut text
        int fittingLines = h / this.getLineHeight();
        if (fittingLines > 0) {
            this.setLines(fittingLines);
        }
    }

}

工作得很好,但是如果你在TextView上指定了layout_margin,要小心,因为它可能会导致适应行数变短!我改用padding而不是margin,问题解决了。 - MobileMon
1
这个绝对完美。到目前为止,我找到的最佳解决方案。 - Moonbloom
1
这是正确的答案,谢谢!为了使它更好看并在截断文本之前添加“...”,请在上面的if语句中添加this.setEllipsize(TextUtils.TruncateAt.END);,并从XML中删除android:ellipsize="end",因为某种原因它会破坏它。 - NeilS

6

将有问题的TextView放入FrameLayout中。我认为由于Spinner这个兄弟视图,文本视图没有被正确计算。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:orientation="horizontal">

    <FrameLayout
        android:layout_width="150dp"
        android:layout_height="wrap_content">
        <TextView
            android:id="@+id/textView1"
            android:layout_width="150dp"
            android:layout_height="wrap_content"
            android:layout_marginRight="20dp"
            android:text="TextView"/>
    </FrameLayout>
    <Spinner
        android:id="@+id/spinner1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>
</LinearLayout>

1
我在同一个LinearLayout中放置了CheckBox,这解决了问题。 - Chintan Shah
在 CheckBox 的情况下,像 @ChintanShah 一样工作得很好。 - ignacardel

5

我的解决方案接近被接受的方案,但我不得不对其进行修改

   android:layout_gravity="fill_vertical"

否则,其他行也会随机添加换行符而被拉伸。例如,最大的行有4行,因此另一行从

this is a testphrase

变成了

thi
s is
a testph
rase

5
当出现这种情况时,您应确保 TextView 的大小不会超过其容器-
如果将 TextView 设置为 wrap_content ,并且它的容器(或祖先容器)没有留出空间供 TextView 增长,那么它可能会被遮挡。
如果不是这种情况,则 TextView onMeasure()有时可能无法正确测量字母、非拉丁字符的尾巴或文本斜体效果的影响。您可以通过为 TextView 设置全局样式来进行纠正,因此它将被拾取而无需更改整个代码库:
确保您的应用程序/活动使用自定义主题,如下所示:
<style name="Custom" parent="@android:style/Theme.Light">   
    <item name="android:textViewStyle">@style/Custom.Widget.TextView</item>
</style>

<style name="Custom.Widget.TextView" parent="@android:style/Widget.TextView"> 
    <item name="android:gravity">fill</item>
    <item name="android:padding">1sp</item>
</style>

@Rynadt的回答对于达到上述阶段非常有帮助。在视图内部设置文本的重力可以确保在某些设备上不会发生遮挡(文本正确适合视图内),而在其他设备上,使用特定TextSize值的sp填充可以确保考虑到尾巴等问题。


4

尝试移除 android:paddingBottom="20dp"

 <RelativeLayout
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:paddingBottom="20dp"
            android:paddingLeft="10dp"
            android:paddingRight="10dp"
            android:paddingTop="10dp" >

1
那里的填充实际上与相对布局中包含的其他项无关,我已将它们删除以便更轻松地阅读此帖子。请参见问题中的编辑。 - Rynardt

4

getViewTreeObserver().addOnGlobalLayoutListener 在 Recycler View 中不起作用。如果您正在使用 Recycler View,请使用 View.addOnLayoutChangeListener

我发现我在 xml 中为 textView 定义的省略号并不总是生效,因此在重新分配文本属性之前,我通过编程方式设置了它。这对我起到了作用。

textView.addOnLayoutChangeListener(new OnLayoutChangeListener() {
    @Override
        public void onLayoutChange(View v, int left, int top, int right, int bottom,
                                   int oldLeft, int oldTop, int oldRight, int oldBottom) {
            textView.removeOnLayoutChangeListener(this);
            float lineHeight = textView.getLineHeight();
            int maxLines = (int) (textView.getHeight() / lineHeight);
            if (textView.getLineCount() != maxLines) {
                textView.setLines(maxLines);
                textView.setEllipsize(TextUtils.TruncateAt.END);
                // Re-assign text to ensure ellipsize is performed correctly.
                textView.setText(model.getText());
            }
        }
    });

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