Android: última línea de vista de texto cortada

113

Tengo una horizontal que LinearLayoutcontiene una TextViewseguida de una Spinnerjunto a ella. Esto LinearLayoutse infla dinámicamente varias veces en una vertical fija LinearLayoutcontenida dentro de a RelativeLayout.

El problema es que desde que cambié de Theme.lighta Theme.holo.light, la última línea TextViewse corta a la mitad. Esto sucede cuando el texto dinámico es largo y ocupa más de una fila.

ingrese la descripción de la imagen aquí

He podido solucionar esto agregando relleno inferior al horizontal que LinearLayoutcontiene TextViewy Spinner.

Esto no se siente como una solución, sino más como un truco. ¿Alguien puede darme algún consejo sobre cómo solucionar esto correctamente?

También he leído algunas otras preguntas, pero ninguna parece ayudar.

Diseño lineal horizontal:

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

Diseño relativo donde el diseño anterior se infla dinámicamente en el diseño lineal con 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>

EDITAR: Aquí está el xml de diseño completo para arriba:

<?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
fuente
intente eliminar android: paddingBottom = "20dp"
Dheeresh Singh
2
Intente rellenar la vista de texto y los márgenes de diseño lineal también pueden ser una buena mano
Aashish Bhatnagar
LinearLayout es realmente problemático cuando se usa horizontalmente. En su lugar, utilice ConstraintLayout. Ver. stackoverflow.com/a/48677954/630668
Dharmendra

Respuestas:

55

Encontré el mismo problema de corte que se muestra en la captura de pantalla. Es causado por la alineación de la línea de base en la horizontal LinearLayout. TextViewy Spinnertienen diferentes líneas de base debido a la diferencia de tamaño de fuente. Para solucionar el problema, es necesario deshabilitar la alineación de la línea de base para el diseño configurando:

android:baselineAligned="false"

o en el código:

layout.setBaselineAligned(false);
Jusid
fuente
2
¡Ojalá pudiera votar esto 100 veces! He perdido muchísimo tiempo en los últimos días en este problema, ¡y tu respuesta fue mi solución! No me di cuenta de lo que estaba sucediendo durante tanto tiempo porque es muy difícil depurar la jerarquía de vistas en Android. ¡¡¡Muchas gracias!!!
mbm29414
Esta fue la solución a mi problema, además de la respuesta de Rynardt. ¡Gracias!
James Dobson
1
Esta es la respuesta correcta y señala la razón por la que ocurrió el error. Gracias.
Hoang Nguyen Huu
Este es un gran consejo para situaciones como esta. No está mal. ¡Gracias!
sunlover3
260

Después de probar un millón de cosas diferentes, creo que tengo la respuesta.

LayoutGravityApliqué un al elemento TextView:

android:layout_gravity="fill"

Parece resolver todos los problemas de recorte que tuve. Espero que esto ayude a alguien con el mismo problema.

Rynardt
fuente
12
perfecto, tnx, +1; tenga en cuenta que muchos valores de layout_gravity ayudan, por ejemplo. center_vertical
Grzegorz Dev
2
Cuando esto no funcione, agregar un valor de relleno de "1sp" debería funcionar. Creo un estilo que se extiende @android:style/Widget.TextViewy agrego las siguientes líneas:<item name="android:gravity">fill</item> <item name="android:padding">1sp</item>
Graeme
¿Por qué ocurre este problema solo con el texto árabe?
Menna-Allah Sami
12
Eso es solo una solución. La solución adecuada es agregar android:baselineAligned="false"a suLinearLayout
tomrozb
1
Aunque esto parece funcionar, la solución correcta es la del comentario de tomrozb anterior, o la respuesta de Jusid
Eduard B.
28

Tuve el mismo problema y descubrí que simplemente agregando

android:includeFontPadding="false"

la última línea de texto ya no tenía sus descendientes recortados.

Neal Sanche
fuente
1
Con fuentes personalizadas, esta podría ser la solución perfecta. Esta es la única solución que me funcionó al usar Droid Sans Japanese.
computingfreak
11

Agregué un espacio ficticio después del texto agregando

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

Probé todas las demás soluciones, pero esta fue la única solución que funcionó para mí.

Ameer
fuente
esto es lo que llamas "chepi"
Zulqurnain Jutt
6

Coloque la vista de texto problemática dentro de un diseño de marco. Creo que la vista de texto no se calcula correctamente debido a la vista de hermanos, 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>
Rubin Yoo
fuente
1
Yo tenía CheckBoxen el mismo LinearLayout. Esto resolvió el problema.
Chintan Shah
Funcionó como un encanto con una situación de CheckBox como @ChintanShah
ignacardel
5

Cuando esto ocurra, debe asegurarse de que TextView no esté creciendo más grande que su contenedor -

Si a TextViewse establece en wrap_contenty su contenedor (o un contenedor ancestro) no deja espacio para TextViewque crezca, se puede ocluir.

Si ese no es el caso, también es posible la onMeasure()de la TextViewveces no mide correctamente las colas de letras, caracteres no latinos o los efectos de texto que se está en cursiva. Puede corregir esto configurando un estilo global para usted, TextViewpor lo que se seleccionará sin necesidad de cambiar toda su base de código:

Asegúrese de que su aplicación / actividades use un tema personalizado como este:

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

La respuesta de @Rynadt fue realmente útil para llegar a la etapa anterior. Establecer la gravedad del texto dentro de la vista asegura en algunos dispositivos que la oclusión nunca se produce (el texto se ajusta correctamente dentro de la vista), en otros, una mano amiga con el relleno de un valor sp, asegura que las colas y otros se tengan en cuenta con un valor específico de TextSize.

Graeme
fuente
5

Mi solución estaba cerca de la aceptada, pero tuve que cambiarla a

   android:layout_gravity="fill_vertical"

en lugar. De lo contrario, las otras filas también se habrían estirado con saltos de línea agregados en lugares aleatorios. Por ejemplo, la fila más grande tenía 4 líneas, por lo que se cambió otra fila de

this is a testphrase

a

thi
s is
a testph
rase
Hermana fantasma
fuente
1
Funciona para mi. ¡Gracias! +1
Ahmed
5

Encontré una solución diferente extendiendo TextView y agregando una clase personalizada como esta:

 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);
        }
    }

}
Nombre para mostrar
fuente
Funciona muy bien, pero tenga cuidado si tiene layout_margin especificado en la vista de texto, ya que puede alterar el número de líneas de ajuste para que sea más corto de lo que debería ser. Cambié a usar relleno en lugar de márgenes y el problema se solucionó
MobileMon
1
Esto funciona absolutamente perfecto. De lejos, la mejor solución que he encontrado.
Moonbloom
1
Esta es la respuesta correcta, ¡gracias! Para hacerlo un poco más agradable y agregar '...' al final del texto antes de que se trunque, agregue this.setEllipsize(TextUtils.TruncateAt.END);la declaración if anterior y elimine android:ellipsize="end"del XML que por alguna razón lo rompe.
NeilS
4

intente eliminar android: paddingBottom = "20dp"

de

 <RelativeLayout
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:paddingBottom="20dp"
            android:paddingLeft="10dp"
            android:paddingRight="10dp"
            android:paddingTop="10dp" >
Dheeresh Singh
fuente
1
El relleno no está realmente relacionado ya que hay elementos adicionales contenidos dentro de este diseño relativo con el relleno. Los eliminé para facilitar la lectura de esta publicación. Ver edición en cuestión.
Rynardt
4

getViewTreeObserver().addOnGlobalLayoutListenerno funciona en una vista de reciclador. Si está usando un reciclador, use View.addOnLayoutChangeListener:

Descubrí que la elipsización que definí textViewen xml no siempre se reflejaba, así que la configuré programáticamente antes de reasignar la propiedad de texto. Esto funcionó para mí.

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

Si tiene este problema y se TextViewencuentra dentro de a RelativeLayout, intente cambiar el RelativeLayoutpor a LinearLayout.

Eso me solucionó el problema

JesperB
fuente
¡Esta es la única solución que funciona para mí (comportamiento extraño)! Thx
mrroboa el
1
¿Cómo puede simplemente "cambiar" de RelativeLayout a LinearLayout? Si tiene que realizar un diseño relativamente, es casi imposible implementarlo con LinearLayout.
El increíble
3

Puede utilizar un detector de diseño global para TextView en cualquier tipo de 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);
        }

    }
});

Puedes leer más sobre esto aquí.

Jim Baca
fuente
1

Creo que es muy poco lo que puede hacer para que esto funcione modificando los diseños. Como he descubierto, algunos métodos funcionan solo en algunos casos. Creo que depende de toda la jerarquía de diseño y no es una solución única para todos. También he notado que sucede especialmente cuando tiene una fuente diferente que desea establecer en TextView.

Un método de disparo seguro que he experimentado y probado es que puede establecer los atributos de fuente en el código después de inflar la vista. Supongo que tiene una fuente en la carpeta de activos / fuentes que desea para usted.

Por ejemplo, en un fragmento:

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

Y en una actividad:

@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
}
Mahesh Iyer
fuente
1

Tengo el mismo problema y es muy molesto.

Solo ocurre con el texto árabe.

Si hace la etiqueta de varias líneas y agrega un \nal final de su cadena, lo solucionaría, pero el problema es que habría un gran espacio entre esta etiqueta y el objeto debajo de ella, debido al hecho de que este campo ahora tiene una nueva línea vacía debajo.

Se puede hacer un control personalizado para evitar eso. Pero en general, este es un error molesto.

Adel Ammari
fuente
Si tiene una pregunta NUEVA, hágala haciendo clic en el botón Preguntar . Si tiene suficiente reputación, puede votar a favor de la pregunta. Alternativamente, "destaque" como favorito y se le notificará de las nuevas respuestas.
Martijn Pieters
0

La mejor solución para esto es agregar una vista ficticia de la altura deseada (es decir, esto agregará relleno) en la parte inferior de la vista.

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

Como en mi caso, agregué una fila de tabla más en la parte inferior de la vista. Espero que esto pueda ayudar a alguien.

Anuj Sharma
fuente
0

Sé que es muy tarde, pero esto es un trabajo maravilloso para mí. agregue este código a sutextview

android:ellipsize="marquee"
android:layout_weight="1"
rociado
fuente
0

Agregue relleno en la parte inferior de la vista de texto:

android:paddingBottom="24dp"
Phil
fuente
-1

¡Finalmente lo arreglé!

Intento agregar String a TextView en Service y luego llamo scrollTo (), ¡la última línea se cortará!

El scrollTo () debe llamarse en "Ejecutable", como:

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);
        }
    });
}

Lo creo porque en el dinero de la llamada scrollTo () en servicio, la actualización de TextView no está lista.

kazon
fuente