Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

TextView populated dynamically cutting off last line of text

I'm not sure its only the "last line", but we have an app that has a TextView with fill_parent width, wrap_content height. Text is being put in there dynamically from the Java code. The last line of the text simply isn't showing up, even though there's plenty of space in the layout. Its inside of a fairly deep view hierarchy, so my guess is the measure logic in there is getting messed up, but its pretty frustrating. We need to guess how many lines are going to be in the text and set 'android:lines' accordingly to get it to work.

Anybody seen this? In the code, see id 'contentTextView' towards the bottom. If I take out the 'android:lines', the last line of text disappears.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:orientation="vertical"
              android:layout_width="fill_parent"
              android:layout_height="fill_parent"
              android:background="@drawable/flag"
        >

    <include android:id="@+id/incHeader" layout="@layout/header"/>

    <FrameLayout
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_weight="1">

        <LinearLayout
                android:layout_width="fill_parent"
                android:layout_height="fill_parent"
                android:orientation="vertical">

            <ImageView
                    android:layout_width="fill_parent"
                    android:layout_height="101dp"
                    android:background="@drawable/headershadow"/>

            <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:visibility="invisible"
                    android:layout_weight="1"/>


            <ImageView
                    android:layout_width="fill_parent"
                    android:layout_height="101dp"
                    android:background="@drawable/footershadow"/>

        </LinearLayout>

        <LinearLayout
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:background="@drawable/gybcontentback"
                android:layout_gravity="center_horizontal"
                android:orientation="vertical">

            <include android:id="@+id/gybHeaderInclude" layout="@layout/gybcontentheader"/>


                <TextView
                        android:layout_width="fill_parent"
                        android:layout_height="wrap_content"
                        android:textColor="#4f4f4f"
                        android:paddingLeft="15dp"
                        android:paddingRight="15dp"
                        android:lines="9"
                        android:id="@+id/contentTextView"/>

            <ImageView
                    android:layout_marginTop="15dp"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:src="@drawable/button_blue_rascal_button"
                    android:id="@+id/buttonMoreInfo"/>

        </LinearLayout>

    </FrameLayout>


    <include android:id="@+id/incFooter" layout="@layout/menu"/>

</LinearLayout>

Java code. I'm populating the TextView with a standard Java string during onCreate.

@Override
protected String body()
{
    return "Rascal Flatts and The Jason Foundation, Inc. are working together to prevent suicide.\n\n" +
            "Your Battle Buddy (or family member) may need a friend.\n\n" +
            "Take the pledge to B1.";
}

The base class calls that to get the actual text

@Override
protected void onCreate(Bundle savedInstanceState)
{
    super.onCreate(savedInstanceState);
    setContentView(contentView());
    wireMenu();

    TextView headerText = (TextView) findViewById(R.id.gybHeaderText);
    if(headerText != null)
        headerText.setText(header());

    ((TextView) findViewById(R.id.contentTextView)).setText(body()); // This is where the text is set
}

Anyway, I'm boiling it down. I'm cutting out parts to see what's left and still getting the same issue. I think I may have found the trigger, and a solution, but not the "cause".

like image 405
Kevin Galligan Avatar asked Nov 15 '11 23:11

Kevin Galligan


4 Answers

I have the same problem. I have found a workaround. Append a new line "\n" to your text. This will always show all of your text.

like image 114
tobias Avatar answered Nov 30 '22 11:11

tobias


Have you tried surrounding your TextView directly with a LinearLayout, with width and height set to wrap_content ?

It worked for me...

like image 21
Nico Avatar answered Nov 30 '22 11:11

Nico


I boiled the layout down to its base parts. Here's the stripped down version, that's still cutting the text off:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:orientation="vertical"
              android:layout_width="fill_parent"
              android:layout_height="fill_parent"
              android:background="@drawable/flag"
        >


    <LinearLayout
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center_horizontal"
                android:orientation="vertical">

            <TextView
                    android:layout_width="fill_parent"
                    android:layout_height="wrap_content"
                    android:textColor="#4f4f4f"
                    android:id="@+id/contentTextView"/>

            <ImageView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:src="@drawable/button_blue_rascal_button"
                    android:id="@+id/buttonMoreInfo"/>

        </LinearLayout>



</LinearLayout>

The problem, I think, is that the parent LinearLayout is getting its width from the ImageView inside it. Somewhere in this mix, the TextView is getting an incorrect value for its requested height. I would imagine this has to do with how the UI is calculated. The parent must ask the children for their requested width, then go back and tell everybody what their width is, then ask for heights. Something like that. Anyway, the following works. The image width is 263 pixels (in mdpi), so if I set 263dp instead of wrap_content on the parent layout, everything is OK.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:orientation="vertical"
              android:layout_width="fill_parent"
              android:layout_height="fill_parent"
              android:background="@drawable/flag"
        >


    <LinearLayout
                android:layout_width="263dp"
                android:layout_height="wrap_content"
                android:layout_gravity="center_horizontal"
                android:orientation="vertical">

            <TextView
                    android:layout_width="fill_parent"
                    android:layout_height="wrap_content"
                    android:textColor="#4f4f4f"
                    android:id="@+id/contentTextView"/>

            <ImageView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:src="@drawable/button_blue_rascal_button"
                    android:id="@+id/buttonMoreInfo"/>

        </LinearLayout>



</LinearLayout>

Setting the TextView to wrap_content works too, although it then pushes the whole layout larger than I want it to be.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:orientation="vertical"
              android:layout_width="fill_parent"
              android:layout_height="fill_parent"
              android:background="@drawable/flag"
        >


    <LinearLayout
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center_horizontal"
                android:orientation="vertical">

            <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:textColor="#4f4f4f"
                    android:id="@+id/contentTextView"/>

            <ImageView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:src="@drawable/button_blue_rascal_button"
                    android:id="@+id/buttonMoreInfo"/>

        </LinearLayout>



</LinearLayout>

Not sure what the takeaway here is. Summary, if you start seeing calculated height issues, consider fixing a width in there for the parent, just so the UI calculations don't get confused.

like image 43
Kevin Galligan Avatar answered Nov 30 '22 13:11

Kevin Galligan


I had a different problem but similarly related. Here is the solution that I think works for what you need as well. You can use a global layout listener for a TextView in any type of ViewGroup.

    final TextView dSTextView = (TextView)findViewById(R.id.annoyingTextView);
dSTextView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {

    @Override
    public void onGlobalLayout() {
        dSTextView.getViewTreeObserver().removeOnGlobalLayoutListener(this);

        float lineHeight = dSTextView.getLineHeight();
        int maxLines = (int) (dSTextView.getHeight() / lineHeight);

        if (dSTextView.getLineCount() != maxLines) {
            dSTextView.setLines(maxLines);
        }

    }
});

You can read more about it here

like image 35
Jim Baca Avatar answered Nov 30 '22 11:11

Jim Baca