2012-05-08 16 views
8

Voy a mostrar un documento de texto completo en varias páginas en una aplicación de Android. Cada página contiene un control TextView que se encarga de mostrar el texto. También contiene un botón siguiente, que se encarga de actualizar la vista de texto y seguir el texto justo desde donde terminó en la última sección mostrada.
El problema es ¿cómo puedo encontrar la última palabra que se muestra en el área visualizable de TextView?
Nota: en esta aplicación, textView no es se supone que debe desplazarse o utilizar ellipsize. También se debe tener en cuenta que el tamaño del texto se puede aumentar o disminuir. Para comprender mejor la situación: Texto la muestra que se mostrará:última palabra mostrada en una vista de texto

Este es un texto conjunto. En la primera página Acabo de terminar aquí y debe ser seguido desde aquí.

Y esta es la ilustración de muestra de su pantalla. La pregunta es ¿cómo encontrar la palabra "aquí" como última palabra que se muestra en la página 1? And this is the sample illustration of the its display. The question is how to find word "here" as last word displayed in page 1?

+0

¿El texto siempre será el mismo o puede cambiar? – caiocpricci2

+0

el texto se cambiará dinámicamente. – VSB

Respuesta

1

Finalmente desarrollé una pieza de código que puede encontrar la última palabra que se muestra. Teniendo en cuenta que vamos a utilizar una vista de texto con propiedades ancho y altura como su tamaño y TEXTSIZE en dp como el tamaño del texto, la función formatStringToFitInTextView evalúa la última palabra que se muestra en el TextView y lo devuelve a como la función salida. En la muestra siguiente, consideramos la fuente SERIF como tipo de letra TextView.

String formatStringToFitInTextView(int width, int heigth, String inputText,float textSize) { 
    String[] words; 
    String lastWord = ""; 
    String finalString=""; 
    StaticLayout stLayout; 
    int i,numberOfWords; 
    int h; 
    Typeface tf = Typeface.SERIF; 
    TextPaint tp = new TextPaint(); 
    tp.setTypeface(tf); 
    tp.setTextSize(textSize); //COMPLEX_UNIT_DP 

    words = inputText.split(" "); //split input text to words 
    numberOfWords = words.length; 
    for (i=0;i<numberOfWords;i++){ 
     stLayout= measure(tp,finalString+words[i]+" ",width); 
     h=stLayout.getHeight(); 
     if (stLayout.getHeight() > heigth) break; 
     finalString += words[i]+" "; 
     lastWord = words[i]; 
    } 

    return lastWord; 
} 
StaticLayout measure(TextPaint textPaint, String text, Integer wrapWidth) { 
    int boundedWidth = Integer.MAX_VALUE; 
    if(wrapWidth != null && wrapWidth > 0) { 
     boundedWidth = wrapWidth; 
    } 
    StaticLayout layout = new StaticLayout(text, textPaint, boundedWidth, Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); 
    return layout; 
} 

La lógica total de hacer acciones se divide el texto de entrada en palabras y añadir palabras una por una para Textview hasta que se llena la altura y la anchura proporcionada y luego regresar la última palabra añadida en último aparece la palabra.

Nota: Gracias a Moritz, utilicé la medida de función de this answer.

1

No puedo probar esta idea ahora, pero demos una oportunidad! De acuerdo con this post, puede usar el siguiente método para averiguar si una cadena encaja en una vista de texto.

private boolean isTooLarge (TextView text, String newText) { 
    float textWidth = text.getPaint().measureText(newText); 
    return (textWidth >= text.getMeasuredWidth()); 
} 

Así que una idea, si el texto es siempre la misma, puede definir los valores iniciales para cada vista de texto de forma manual y luego, cuando se aumenta o disminuye la fuente que calcular de nuevo, eliminando o añadiendo palabras.

Si no es una opción para introducir los valores iniciales manualmente se puede hacer algo como:

String wordsInTextview = new String(); 
int lastUsedWord= 0; 
int totalNumberOfWords = text.size(); 
    for (int i=lastUsedWord;i<totalNumberOfWords;i++) {    
     if !(isTooLarge(TextView,wordsInTextview)) { 
      wordsInTextview = wordsInTextview + text(i); // add the words to be shown 
     } else { 
     TextView.setText(wordsInTextView); 
     lastUsedWord= i; 
     wordsInTextView = new String(); // no idea if this will erase the textView but shouldn't be hard to fix  
     }  
    } 

Usted también necesitaría para almacenar la posición de la primera palabra de la Textview, por lo que al cambiar el tamaño del texto ¡Sabes por dónde empezar!

int firstWordOnTextView = TextView.getText().toString().split(" ")[0] 

Y cuando cambia el tamaño, lo utiliza en el mismo método para calcular el texto en la pantalla.

lastUsedWord = firstWordOnTextView; 

Si quieres ser aún más rápido, se puede mantener un registro de cuántas palabras tiene en cada página, hacer un promedio y después de algunas carreras siempre stat su bucle de allí. O unas pocas palabras antes para evitar tener que iterar de nuevo.

Creo que esta es una solución razonable si no tiene que mostrar demasiadas páginas a la vez.

Disculpa las equivocaciones en el código ¡No tengo dónde probarlo ahora! ¿Algún comentario sobre esta solución? Pregunta muy interesante!

+0

Gracias por su respuesta. Tu respuesta también es interesante y útil. Sin embargo, no es adecuado para Multi-line TextView ya que debe tener en cuenta el espacio vertical. Y al buscar la estimación del espaciado vertical, finalmente encuentro las soluciones que se usaron en: [This Post] (http://stackoverflow.com/questions/7549182/android-paint-measuretext-vs-gettextbounds). Publicaré mi código cuando termine aquí. gracias por su nota :) – VSB

+0

¡Oh, mi mal, no lo noté! Bueno, sí, compártelo con nosotros :) – caiocpricci2

+0

puede tener respuesta ahora :) – VSB

Cuestiones relacionadas