77 votes

Comment mettre en page le texte pour qu'il entoure une image

Pouvez-vous me dire si il existe un moyen de mise en page de texte autour d'une image? Comme ceci:

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

J'ai eu une réponse d'un développeur android à propos de cette question. Mais je ne suis pas sûr de ce qu'il entend par faire ma propre version de TextView? Merci pour les conseils.

Le Lundi, Février 8, 2010 à 11:05 PM, Romain Guy a écrit:

Salut,

Ce n'est pas possible en utilisant uniquement des widgets fournis et mises en page. Vous pouvez écrire votre propre version de TextView pour ce faire, il ne devrait pas être dur.

69voto

vorrtex Points 9356

Maintenant, c'est possible, mais seulement pour les téléphones avec la version supérieure ou égale à 2.2 en utilisant l' android.text.style.LeadingMarginSpan.LeadingMarginSpan2 interface qui est disponible dans l'API 8.

Voici l' article, pas en anglais, mais vous pouvez télécharger le code source de l'exemple directement à partir d' ici.

Si vous voulez faire de votre application compatible avec les anciens appareils, vous pouvez afficher une autre mise en page sans texte flottant. Voici un exemple:

Mise en page (par défaut pour les versions plus anciennes, sera modifiée par programme pour les versions plus récentes)

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

class FlowTextHelper {

    private static boolean mNewClassAvailable;

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

        // Also you can use this trick if you don't know the exact version:
        /*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){
        // 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)Math.round(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;
    }
}

Le MyLeadingMarginSpan2 classe

public class MyLeadingMarginSpan2 implements LeadingMarginSpan2 {
    private int margin;
    private int lines;

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

    @Override
    public int getLeadingMargin(boolean first) {
        return first ? margin : 0;
    }

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

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

Exemple de l'utilisation

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

C'est la façon dont l'application a l'air sur de l'Android 2.2 appareil: Android 2.2 the text flows around the image

Et c'est pour l'Androïde 2.1 de l'appareil:

Android 2.1 the text is situated near the image

7voto

Ronen Yacobi Points 259

Voici une amélioration pour FlowTextHelper (de la réponse de vorrtex). J'ai ajouté la possibilité d'ajouter un rembourrage supplémentaire entre le texte et l'image et d'améliorer le calcul des lignes afin de prendre également en compte le remplissage. Prendre plaisir!

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


}
 

4voto

johosher Points 102

Les réponses de Vorrtex et Ronen fonctionnent pour moi, à l'exception d'un détail: après avoir entouré le texte autour de l'image, il y avait une étrange marge "négative" sous l'image et du côté opposé. J'ai compris qu'en changeant la durée du SpannableString,

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

à

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

qui a arrêté la durée après l'image. Peut-être pas nécessaire dans tous les cas mais je pensais partager.

3voto

Victor Points 454

Cette question semble être la même que la mienne Comment remplir les espaces vides avec du contenu situé sous l'image dans Android

J'ai trouvé la solution en utilisant la bibliothèque flowtext, veuillez trouver la première réponse qui pourrait vous aider jusqu'à présent.

1voto

Peter vdL Points 1420

"Mais je ne suis pas sûr de ce qu'il veut dire en faisant ma propre version de TextView?"

Cela signifie que vous pouvez étendre la classe android.widget.TextView (ou Canvas ou une autre surface à restituer) et mettre en œuvre votre propre version de remplacement qui permet aux images incorporées avec du texte circulant autour d'eux.

Cela pourrait prendre pas mal de travail en fonction de votre généralité.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X