¿Cómo obtener N texto que pueda caber en Screen/TextView con un tamaño específico?

Tengo una gran historia en formato String. Quiero mostrar el texto en la galería. Lo que quiero hacer es dividir todo el texto de tal manera que toda mi vista en la galería muestre el texto que cabe en la pantalla.

Para que pueda hacer mi cadena en parte, donde cada parte se mostrará en la pantalla y cada parte cubrirá toda la pantalla.

Una cosa a tener en cuenta es que el usuario puede cambiar el tamaño del texto Grande, Pequeño, por lo que el texto en pantalla también cambiará a medida que cambie el tamaño.

Me pregunto si hay una manera de hacer esto.

Solución

Muchas gracias a usuarioSeven7s por ayudarme. Basado en su ejemplo, puedo hacer un ejemplo. Aquí está:

package com.gsoft.measure.text;

import java.util.Timer;
import java.util.TimerTask;

import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.widget.LinearLayout;
import android.widget.TextView;

public class MainScreen extends Activity {

    private final String TAG = "MainScreen";
    private String textToBeShown = "These are the text";
    private String sampleText = "Here are more text";
    private TextView mTextView = null;

    Handler handler = new Handler() {

        public void handleMessage(Message msg) {
            if (msg.what == 1) {
                updateUI();
            }
        };
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        mTextView = (TextView) findViewById(R.id.ui_main_textView);
        mTextView.setTextSize(20f);
        for (int i = 0; i < 100; i++) {
            textToBeShown = textToBeShown + " =" + i + "= " + sampleText;
        }

        // I am using timer as the in UI is not created and
        // we can't get the width.
        TimerTask task = new TimerTask() {

            @Override
            public void run() {
                // So that UI thread can handle UI work
                handler.sendEmptyMessage(1);
            }
        };
        Timer timer = new Timer();
        timer.schedule(task, 1000 * 1);
    }

    @Override
    protected void onResume() {
        super.onResume();

    }

    private void updateUI() {

        // Set text
        mTextView.setText(textToBeShown);
        // Check the width
        Log.e(TAG, "Width = " + mTextView.getWidth());

        // Check height of one line
        Log.e(TAG, "Line height= " + mTextView.getLineHeight());

        // Check total height for TextView
        Log.e(TAG, "Text height= " + mTextView.getHeight());

        // No of line we can show in textview
        int totalLine = mTextView.getHeight() / mTextView.getLineHeight();
        Log.e(TAG, "Total Lines are height= " + totalLine);


        for (int i = 0; i < totalLine; i++) {
            // Get No of characters fit in that textView
            int number = mTextView.getPaint().breakText(textToBeShown, 0, textToBeShown.length(), true,
                    mTextView.getWidth(), null);
            Log.e(TAG, "Number of chracters = " + number);

            // Show the text that fit into line
            Log.e(TAG, textToBeShown.substring(0, number));
            // Update the text to show next
            textToBeShown = textToBeShown.substring(number, textToBeShown.length());
        }
    }
}

Aquí está mi XML

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

    <TextView
        android:id="@+id/ui_main_textView"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:background="@color/twitter"
        android:textColor="@color/white" />

</LinearLayout>

preguntado el 03 de mayo de 12 a las 14:05

Me pregunto si hay alguna manera de hacer esto. - Sí. -

¿Cómo puedo obtener el texto recordatorio de su algoritmo? -

3 Respuestas

Usted revisa el TextView código fuente y vea cómo deciden dónde elipsear la cadena.

El código para TextView is aquí.

Alternativamente, puede utilizar TextUtils la clase public static CharSequence ellipsize(CharSequence text, TextPaint p, float avail, TruncateAt where) método.

TextPaint p debería ser el objeto de pintura de TextView.

Actualizar:

Otra alternativa es usar Paint.getTextWidths(char[] text, int index, int count, float[] widths).

textpaint.getTextWidths(char[] text, int index, int count, float[] widths);

int i = 0;
int prev_i = 0;
while (i < count) {
    textWidth = 0;
    for (int i = prev_i; (i < count) || (textWidth < availableWidth); i++) {
        textWidth += widths[i];
    }
    String textThatFits = mOriginalText.subString(prev_i, i);
    mTextview.setText(textThatFits);
    prev_i = i;
}

i es el número de caracteres que caben en TextView.
availableWidth es el ancho de la TextView en píxeles.

Este código es aproximado y contiene errores de sintaxis. Tendrá que hacer algunos cambios menores para que funcione.

Update 2:

Otra alternativa sería utilizar

int breakText (CharSequence text,      
                int start, int end,   
                boolean measureForwards,   
                float maxWidth, float[] measuredWidth). 

Creo que esta es la mejor solución para ti. Compruebe su documentación aquí.

Actualizar:

Ejemplo de código usando pintura.breakText método.

paint.setSubpixelText(true);
int prevPos = 0;
while (nextPos  < chars.length) {
    int nextPos = paint.breakText(chars, prevPos, chars.length, maxWidth, null);
    tvStr = str.substring(prevPos, nextPos);
    prevPos = nextPos+1;
}

contestado el 07 de mayo de 12 a las 18:05

gracias me ayudo mucho tu solucion Pero, ¿qué pasa con el tamaño de fuente cambiado? - Arslan Anwar

Genial, funciona. Estaba actualizando fuentes en onResume(). pero ponerlo en onCreate() o XML lo hace perfecto. Estoy actualizando mi pregunta con la respuesta, qué ejemplo se basa en su respuesta. - Arslan Anwar

Gracias señor, una cosita. Si ejecuta el código, encontrará que hay texto adicional en cada línea. no sé por qué ¿Puedes ayudarme? Arslan Anwar

¿Qué quieres decir con "texto adicional" - Ronnie

Quiero decir, cuando los datos se muestran en la pantalla, hay un texto "Aquí está el texto" y, pero en el texto estimado por el algoritmo. Mostrará "Aquí está el texto mor". Entonces "mor" es el texto adicional para cada línea. Que en realidad no se muestra en la pantalla. - Arslan Anwar

si cada parte tiene un número diferente de caracteres, también necesitarán tener diferentes tamaños de fuentes. no solo eso, sino que los dispositivos demasiado pequeños también tendrán un tamaño de fuente demasiado pequeño, ya que el texto debe caber en un espacio más pequeño. Sugeriría tener el mismo tamaño de fuente para todas las partes, mientras permite desplazarse hacia abajo si no hay suficiente espacio.

para esto, puede usar un visor con vistas de desplazamiento en cada página, cada una contiene una vista de texto.

contestado el 05 de mayo de 12 a las 18:05

Gráficos.getFontMetrics y FontMetrics.stringWidth le ayudará a determinar el tamaño real del texto en la pantalla. En función de este cálculo, puede determinar la longitud que debe mostrar la subcadena.

contestado el 05 de mayo de 12 a las 18:05

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.