2010-02-12 13 views
54

¿Puede decirme si hay una forma de distribuir el texto alrededor de una imagen? De esta manera:Cómo distribuir el texto para que fluya alrededor de una imagen

------ text text text 
| | text text text 
----- text text text 
text text text text 
text text text text 

que han conseguido una respuesta de un desarrollador de Android sobre esta cuestión. Pero no estoy seguro de a qué se refiere al hacer mi propia versión de TextView. Gracias por cualquier consejo.

En lun 8 Feb de 2010 a las 23:05, Romain individuo escribió:

Hola,

Esto no es posible utilizando sólo los widgets y diseños suministrados. Usted podría escribir su propia versión de TextView para hacer esto, no debería ser difícil.

+0

silverburgh: ¿encontró una solución para esto que podría compartir? – znq

+4

http://stackoverflow.com/questions/13526949/how-to-fill-the-empty-spaces-with-content-below-the-image-in-android/13527178#13527178 es la solución probablemente – Victor

+0

Esto es tan fácil de hacer en la web. Voy a omitir esta función por ahora. – danny117

Respuesta

1

"pero no estoy seguro de lo que quiere decir con hacer mi propia versión de Vista de Texto?"

Quiere decir que puede extender la clase android.widget.TextView (o Canvas o alguna otra superficie renderizable) e implementar su propia versión de anulación que permite imágenes incrustadas con texto que fluye a su alrededor.

Esto podría ser bastante trabajo dependiendo de qué tan general lo hagas.

58

Ahora es posible, pero sólo para los teléfonos con versión superior o igual 2.2 mediante el uso de la interfaz android.text.style.LeadingMarginSpan.LeadingMarginSpan2 que está disponible en la API 8.

Aquí es el article, no en Inglés sin embargo, pero se puede descargar el el código fuente del ejemplo directamente desde here.

Si desea que su aplicación sea compatible con dispositivos más antiguos, puede mostrar un diseño diferente sin texto flotante. Aquí se muestra un ejemplo:

diseño (por defecto para las versiones anteriores, se cambia mediante programación para las versiones más recientes)

<RelativeLayout 
    xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content"> 
    <ImageView 
      android:id="@+id/thumbnail_view" 
      android:src="@drawable/icon" 
      android:layout_width="wrap_content" 
      android:layout_height="wrap_content" /> 

    <TextView android:id="@+id/message_view" 
      android:layout_width="wrap_content" 
      android:layout_height="wrap_content" 
      android:layout_toRightOf="@id/thumbnail_view" 
      android:textSize="18sp" 
      android:text="@string/text" /> 
</RelativeLayout> 

La clase de ayuda

class FlowTextHelper { 

    private static boolean mNewClassAvailable; 

    static { 
     if (Integer.parseInt(Build.VERSION.SDK) >= 8) { // Froyo 2.2, API level 8 
      mNewClassAvailable = true; 
     } 
    } 

    public static void tryFlowText(String text, View thumbnailView, TextView messageView, Display display){ 
     // There is nothing I can do for older versions, so just return 
     if(!mNewClassAvailable) return; 

     // Get height and width of the image and height of the text line 
     thumbnailView.measure(display.getWidth(), display.getHeight()); 
     int height = thumbnailView.getMeasuredHeight(); 
     int width = thumbnailView.getMeasuredWidth(); 
     float textLineHeight = messageView.getPaint().getTextSize(); 

     // Set the span according to the number of lines and width of the image 
     int lines = (int)FloatMath.ceil(height/textLineHeight); 
     //For an html text you can use this line: SpannableStringBuilder ss = (SpannableStringBuilder)Html.fromHtml(text); 
     SpannableString ss = new SpannableString(text); 
     ss.setSpan(new MyLeadingMarginSpan2(lines, width), 0, ss.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); 
     messageView.setText(ss); 

     // Align the text with the image by removing the rule that the text is to the right of the image 
     RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams)messageView.getLayoutParams(); 
     int[]rules = params.getRules(); 
     rules[RelativeLayout.RIGHT_OF] = 0; 
    } 
} 

La clase MyLeadingMarginSpan2 (actualizado para admitir API 21)

public class MyLeadingMarginSpan2 implements LeadingMarginSpan2 { 
    private int margin; 
    private int lines; 
    private boolean wasDrawCalled = false; 
    private int drawLineCount = 0; 

    public MyLeadingMarginSpan2(int lines, int margin) { 
     this.margin = margin; 
     this.lines = lines; 
    } 

    @Override 
    public int getLeadingMargin(boolean first) { 
     boolean isFirstMargin = first; 
     // a different algorithm for api 21+ 
     if (Build.VERSION.SDK_INT >= 21) { 
      this.drawLineCount = this.wasDrawCalled ? this.drawLineCount + 1 : 0; 
      this.wasDrawCalled = false; 
      isFirstMargin = this.drawLineCount <= this.lines; 
     } 

     return isFirstMargin ? this.margin : 0; 
    } 

    @Override 
    public void drawLeadingMargin(Canvas c, Paint p, int x, int dir, int top, int baseline, int bottom, CharSequence text, int start, int end, boolean first, Layout layout) { 
     this.wasDrawCalled = true; 
    } 

    @Override 
    public int getLeadingMarginLineCount() { 
     return this.lines; 
    } 
} 

Ejemplo del uso

ImageView thumbnailView = (ImageView) findViewById(R.id.thumbnail_view); 
TextView messageView = (TextView) findViewById(R.id.message_view); 
String text = getString(R.string.text); 

Display display = getWindowManager().getDefaultDisplay(); 
FlowTextHelper.tryFlowText(text, thumbnailView, messageView, display); 

Así es como se ve la aplicación en el dispositivo Android 2.2: Android 2.2 the text flows around the image

y esto es para el Android 2.1 dispositivo:

Android 2.1 the text is situated near the image

+2

En lugar del truco Class.forName, puede usar una condición simple: if (Build.VERSION.SDK_INT

+0

También estoy usando esto. Pero cuando los datos con las etiquetas Html no son compatibles con Html.fromHtml (contenido html), por favor, ayúdenme, necesito mostrar la lista con el adaptador de wrapText, como el anterior – Harsha

+0

@Harsha El método 'Html.fromHtml' no funcionará con ningún html, solo admite html simple con pocas etiquetas. – vorrtex

5

Aquí es una mejora para la FlowTextHelper (según la respuesta del vorrtex). Agregué la posibilidad de agregar relleno extra entre el texto y la imagen y mejoré el cálculo de línea para tener también en cuenta el relleno. ¡Disfrútalo!

public class FlowTextHelper { 
    private static boolean mNewClassAvailable; 

    /* class initialization fails when this throws an exception */ 
    static { 
     try { 
      Class.forName("android.text.style.LeadingMarginSpan$LeadingMarginSpan2"); 
      mNewClassAvailable = true; 
     } catch (Exception ex) { 
      mNewClassAvailable = false; 
     } 
    } 

    public static void tryFlowText(String text, View thumbnailView, TextView messageView, Display display, int addPadding){ 
     // There is nothing I can do for older versions, so just return 
     if(!mNewClassAvailable) return; 



     // Get height and width of the image and height of the text line 
     thumbnailView.measure(display.getWidth(), display.getHeight()); 
     int height = thumbnailView.getMeasuredHeight(); 
     int width = thumbnailView.getMeasuredWidth() + addPadding; 
     messageView.measure(width, height); //to allow getTotalPaddingTop 
     int padding = messageView.getTotalPaddingTop(); 
     float textLineHeight = messageView.getPaint().getTextSize(); 

     // Set the span according to the number of lines and width of the image 
     int lines = (int)Math.round((height - padding)/textLineHeight); 
     SpannableString ss = new SpannableString(text); 
     //For an html text you can use this line: SpannableStringBuilder ss = (SpannableStringBuilder)Html.fromHtml(text); 
     ss.setSpan(new MyLeadingMarginSpan2(lines, width), 0, ss.length(), 0); 
     messageView.setText(ss); 

     // Align the text with the image by removing the rule that the text is to the right of the image 
     RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams)messageView.getLayoutParams(); 
     int[]rules = params.getRules(); 
     rules[RelativeLayout.RIGHT_OF] = 0; 
    } 


} 
+0

Hola Ronen. Tengo un gran problema para entender la idea de la cuestión del 'texto envolvente'. ¿Podría decirme dónde puedo obtener información sobre cómo escribir dicho código? Me gustaría aprender cómo escribir el código por mi cuenta en lugar de solo copiarlo. – Ramona

+0

Hola @Ramona Tal vez eche un vistazo a esta biblioteca: https://github.com/deano2390/FlowTextView –

+0

Hola, muchas gracias por la información. ¿Sabes cómo lograr esto con la imagen colocada en el lado derecho de la pantalla? – Ramona

2

Vorrtex y de Ronen respuestas están trabajando para mí excepto por un detalle: después de ajustar el texto alrededor de la imagen, había un extraño margen "negativo" debajo de la imagen y en el lado opuesto. Me di cuenta de que al establecer el lapso en el SpannableString he cambiado

ss.setSpan(new MyLeadingMarginSpan2(lines, width), 0, ss.length(), 0); 

a

ss.setSpan(new MyLeadingMarginSpan2(lines, width), 0, lines, 0); 

que paró el lapso después de la imagen. Puede que no sea necesario en todos los casos, pero pensé que lo compartiría.

0

que puede ofrecer el constructor más cómodo para La clase MyLeadingMarginSpan2

MyLeadingMarginSpan2(Context cc,int textSize,int height,int width) {     
    int pixelsInLine=(int) (textSize*cc.getResources().getDisplayMetrics().scaledDensity);    
    if (pixelsInLine>0 && height>0) { 
     this.lines=height/pixelsInLine;   
    } else { 
     this.lines=0; 
    } 
    this.margin=width; 
} 
+0

Hola Evgeny, ¿cómo establecer 'el flujo de texto alrededor de la imagen' para la imagen colocada en el lado derecho de la pantalla? Respuesta muy apreciada. – Ramona

2

Hoy en día se puede usar la biblioteca: https://github.com/deano2390/FlowTextView. De esta manera:

<uk.co.deanwild.flowtextview.FlowTextView 
    android:id="@+id/ftv" 
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content" > 

     <ImageView 
      android:layout_width="wrap_content" 
      android:layout_height="wrap_content" 
      android:layout_alignParentLeft="true" 
      android:layout_alignParentTop="true" 
      android:padding="10dip" 
      android:src="@drawable/android"/> 
</uk.co.deanwild.flowtextview.FlowTextView> 
Cuestiones relacionadas