Android: обрезана последняя строка текстового просмотра

113

У меня есть горизонталь, LinearLayoutсодержащая a, TextViewза которой следует a Spinner. Он LinearLayoutдинамически раздувается несколько раз в фиксированной вертикали, LinearLayoutсодержащейся в RelativeLayout.

Проблема в том, что с тех пор, как я переключился с Theme.lightна Theme.holo.light, последняя строка строки TextViewразрезается пополам. Это происходит, когда динамический текст длинный и занимает более одной строки.

введите описание изображения здесь

Я смог исправить это, добавив нижнюю прокладку к горизонтали, LinearLayoutсодержащей TextViewи 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">

    <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>

Относительный макет, где макет выше динамически раздувается в Linear Layout с идентификатором 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>
Rynardt
источник
попробуйте удалить android: paddingBottom = "20dp"
Диреш Сингх
2
Попробуйте заполнить текстовое поле отступом, и поля линейного макета тоже могут помочь
Аашиш Бхатнагар
LinearLayout действительно проблематичен при горизонтальном использовании. Вместо этого используйте ConstraintLayout. Видеть. stackoverflow.com/a/48677954/630668
Дхармендра

Ответы:

55

Я столкнулся с той же проблемой отключения, что и на скриншоте. Это вызвано выравниванием базовой линии по горизонтали LinearLayout. TextViewи Spinnerимеют разные базовые значения из-за разницы в размере шрифта. Чтобы решить эту проблему, необходимо отключить выравнивание базовой линии для макета, установив:

android:baselineAligned="false"

или в коде:

layout.setBaselineAligned(false);
Джусид
источник
2
Я хотел бы проголосовать за это 100 раз! Я потратил оооочень много времени на эту проблему за последние несколько дней, и ваш ответ был моим решением! Я так долго не понимал, что происходит, потому что очень сложно отладить иерархию представлений на Android. Спасибо!!!
mbm29414 05
Это было решение моей проблемы в дополнение к ответу Райнардта. Спасибо!
Джеймс Добсон,
1
Это правильный ответ, который указывает на причину возникновения ошибки. Спасибо.
Hoang Nguyen Huu
Это отличный совет для подобных ситуаций. Совсем неплохо. Спасибо!
sunlover3,
259

Попробовав миллион разных вещей, я думаю, что у меня есть ответ.

Я применил LayoutGravityк элементу TextView:

android:layout_gravity="fill"

Кажется, это решило все мои проблемы с отсечением. Надеюсь, это поможет кому-то с той же проблемой.

Rynardt
источник
12
perfect, tnx, +1; обратите внимание, что многие значения layout_gravity помогают, например. center_vertical
Grzegorz Dev
2
Если это не сработает, добавление значения заполнения «1sp» должно работать. Я создаю расширяющийся стиль @android:style/Widget.TextViewи добавляю следующие строки:<item name="android:gravity">fill</item> <item name="android:padding">1sp</item>
Graeme
почему такая проблема бывает как раз с арабским текстом ?!
Menna-Allah Sami
12
Это просто обходной путь. Правильное решение - добавить android:baselineAligned="false"в свойLinearLayout
tomrozb
1
Хотя это, кажется, работает, правильное решение - это решение из комментария tomrozb выше или ответ
Эдуард Б.
28

У меня была такая же проблема, и я обнаружил, что просто добавляя

android:includeFontPadding="false"

нижние элементы последней строки текста больше не были обрезаны.

Нил Санче
источник
1
С пользовательскими шрифтами это может быть идеальным решением. Это единственное решение, которое у меня сработало при использовании Droid Sans Japanese.
computingfreak
11

Я добавил пробел после текста, добавив

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

Я пробовал все другие решения, но это было единственное решение, которое сработало для меня

эмир
источник
это то, что вы называете "чепи"
Zulqurnain Jutt
6

Поместите проблемное текстовое представление внутрь макета фрейма. Я думаю, что текстовое представление вычисляется неправильно из-за родственного представления 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
У меня было CheckBoxтакое же LinearLayout. Это решило проблему.
Chintan Shah
Сработал как шарм с ситуацией CheckBox, такой как @ChintanShah
ignacardel
5

Когда это происходит, вы должны убедиться, что TextViewон не растет больше, чем контейнер -

Если для a TextViewустановлено значение wrap_contentи его контейнер (или контейнер-предок) не оставляет места для TextViewроста, он может быть закрыт.

Если это не так, то это также возможно onMeasure()из TextViewиногда не правильно измерить хвосты букв, не латинских символов или эффектов текста является наклонным. Вы можете исправить это, установив для себя глобальный стиль, 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 был действительно полезен для перехода к вышеуказанному этапу. Установка силы тяжести текста внутри представления гарантирует на некоторых устройствах, что окклюзия никогда не происходит (текст правильно размещен внутри представления), на других рука помощи с заполнением значения sp гарантирует, что хвосты и другие учитываются с конкретным значением TextSize.

Graeme
источник
5

Мое решение было близко к принятому, но мне пришлось изменить его на

   android:layout_gravity="fill_vertical"

вместо. В противном случае другие строки также были бы растянуты с добавлением разрывов строк в случайных местах. Например, в самой большой строке было 4 строки, поэтому другая строка была изменена с

this is a testphrase

к

thi
s is
a testph
rase
Spookysister
источник
1
Работает для меня. Спасибо! +1
Ахмед
5

Я нашел другое решение, расширив 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);
        }
    }

}
Отображаемое имя
источник
Отлично работает, но будьте осторожны, если в текстовом окне указано layout_margin, так как он может изменить количество подходящих строк, чтобы они были короче, чем должно быть! Я перешел на использование отступов вместо полей, и проблема исправлена
MobileMon
1
Это работает абсолютно идеально. Безусловно, лучшее решение, которое я нашел.
Moonbloom
1
Это правильный ответ, спасибо! Чтобы сделать его немного лучше и добавить '...' в конец текста перед его усечением, добавьте this.setEllipsize(TextUtils.TruncateAt.END);в оператор if выше и удалите android:ellipsize="end"из XML, который по какой-то причине его нарушает.
NeilS 01
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не работает в режиме ресайклера. Если вы используете ресайклер, используйте View.addOnLayoutChangeListener:

Я обнаружил, что многоточие, которое я определил textViewв xml, не всегда отражалось, поэтому я программно установил его перед переназначением свойства text. Это сработало для меня.

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());
            }
        }
    });
mp501
источник
3

Если у вас возникла эта проблема и вы находитесь TextViewвнутри a RelativeLayout, попробуйте переключить ее RelativeLayoutна LinearLayout.

Это устранило проблему для меня

JesperB
источник
Это единственное решение, которое у меня работает (странное поведение)! Thx
mrroboaat 09
1
Как можно просто «переключиться» с RelativeLayout на LinearLayout? Если вам нужно относительно планировать макет, это практически невозможно реализовать с помощью LinearLayout.
Невероятный
3

Вы можете использовать прослушиватель глобального макета для TextView в любом типе 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);
        }

    }
});

Вы можете прочитать об этом здесь

Джим Бака
источник
1

Я думаю, что вы мало что можете сделать, чтобы заставить это работать, изменяя макеты. Как я обнаружил, некоторые методы работают только в некоторых случаях. Я думаю, что это зависит от всей иерархии макетов и не является универсальным решением. Я также заметил, что это происходит, особенно когда у вас есть другой шрифт, который вы хотите установить для TextView.

Верный метод, который я экспериментировал и тестировал, заключается в том, что вы можете установить атрибуты шрифта в коде после того, как представление будет увеличено. Я предполагаю, что в папке assets / fonts у вас есть нужный вам шрифт.

Например, во фрагменте:

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState)
{
    View view = inflater.inflate(R.layout.fragment_view, container, false);
    TextView tv = (TextView)view.findViewById(R.id.text_view);
    tv.setText("Insert text that needs to be displayed");
    AssetManager assetManager = getContext().getAssets();
    Typeface typeFace = Typeface.createFromAsset(assetManager, "Fonts/OpenSans-Light.ttf");
    tv.setTypeface(typeFace , 0); // 0 is normal font
    tv.setPadding(10,  0, 10, 0); // This is not mandatory
}

И в действии:

@Override
protected void onCreate(Bundle savedInstanceState) 
{
    super.onCreate(savedInstanceState);
    setContentView(Resource.Layout.main_activity);
    TextView tv = (TextView)this.findViewById(R.id.text_view);
    tv.setText("Insert text that needs to be displayed");
    AssetManager assetManager = getContext().getAssets();
    Typeface typeFace = Typeface.createFromAsset(assetManager, "Fonts/OpenSans-Light.ttf");
    tv.setTypeface(typeFace , 0); // 0 is normal font
    tv.setPadding(10,  0, 10, 0); // This is not mandatory
}
Махеш Айер
источник
1

У меня такая же проблема, и это очень раздражает.

Это происходит только с арабским текстом.

Если вы сделаете метку многострочной и добавите \nв конец строки, это исправит ее, но проблема в том, что между этой меткой и объектом под ней будет большой промежуток из-за того, что это поле теперь под ним новая пустая строка.

Чтобы обойти это, можно использовать специальный элемент управления. Но в целом это досадный баг.

Адель Аммари
источник
Если у вас есть НОВЫЙ вопрос, задайте его, нажав кнопку « Задать вопрос» . Если у вас достаточно репутации, вы можете проголосовать за вопрос. Вы также можете поставить его в избранное, и вы будете получать уведомления о новых ответах.
Мартейн Питерс
0

Лучшее обходное решение для этого - добавить фиктивный View желаемой высоты (т.е. это добавит само отступы) внизу вашего представления.

<TableRow
 android:layout_width="fill_parent"
 android:layout_height="wrap_content"
 android:layout_marginLeft="5dp"
 android:layout_marginRight="5dp" >
     <View 
       android:layout_width="match_parent" 
       android:layout_height="30dp"/>
</TableRow>

Как и в моем случае, я добавил еще одну строку таблицы внизу представления. Надеюсь, это может кому-то помочь.

Анудж Шарма
источник
0

Я знаю, что уже так поздно, но для меня это работа как шарм. добавьте этот код в свойtextview

android:ellipsize="marquee"
android:layout_weight="1"
увлажненный
источник
0

Добавьте отступ в нижнюю часть текстового представления:

android:paddingBottom="24dp"
Фил
источник
-1

Я наконец исправил это!

Я пытаюсь добавить String в TextView в Service, а затем вызываю scrollTo (), последняя строка будет обрезана!

ScrollTo () следует вызывать в «Runnable», например:

private ScrollView mScrollView;
public void scrollToBottom()
{
    mScrollView = (ScrollView) findViewById(R.id.debug_textview_scrollview);
    mScrollView.post(new Runnable()
    {
        public void run()
        {
            mScrollView.fullScroll(View.FOCUS_DOWN);
        }
    });
}

Я думаю, это потому, что в момент вызова scrollTo () в сервисе обновление TextView не готово.

кезоны
источник