web-dev-qa-db-fra.com

Android TextView Justify Text

Comment obtenez-vous le texte d'un TextView à justifier (avec un texte affleurant à gauche et à droite)?

J'ai trouvé une solution possible ici , mais cela ne fonctionne pas (même si vous changez vertical-center en center_vertical, etc.).

369
user130076

Je ne crois pas que Android prenne en charge la justification complète.

UPDATE 2018-01-01 : Android 8.0+ prend en charge modes de justification avec TextView .

219
CommonsWare

La réponse @CommonsWare est correcte. Android ne prend pas en charge la "justification complète" (ou simplement la "justification", comme il est parfois désigné de manière ambiguë).

Cependant, Android prend en charge l '"alignement du texte à gauche/à droite". Voir l'article de Wikipédia sur Justification pour la distinction. Beaucoup de gens considèrent que le concept de "justification" englobe la justification complète ainsi que l'alignement gauche/droite du texte, ce qu'ils recherchent quand ils veulent faire l'alignement du texte gauche/droite. Cette réponse explique comment réaliser l'alignement du texte gauche/droite.

Il est possible d’obtenir l’alignement du texte à l’échelle gauche/droite (par opposition à la justification complète, selon la question posée). Pour illustrer mon propos, j'utiliserai comme exemple un formulaire de base à 2 colonnes (étiquettes dans la colonne de gauche et champs de texte dans la colonne de droite). Dans cet exemple, le texte dans les étiquettes de la colonne de gauche sera aligné à droite de manière à ce qu'il apparaisse au même niveau que leurs champs de texte dans la colonne de droite.

Dans la présentation XML, vous pouvez aligner les éléments TextView eux-mêmes (la colonne de gauche) sur la droite en ajoutant l'attribut suivant dans toutes les vues TextViews:

<TextView
   ...
   Android:layout_gravity="center_vertical|end">
   ...
</TextView>

Toutefois, si le texte est enroulé sur plusieurs lignes, il restera aligné à gauche dans le TextView. L'ajout de l'attribut suivant rend le texte réel aligné à droite dans le TextView:

<TextView
   ...
   Android:gravity="end">
   ...
</TextView>

Ainsi, l'attribut gravity indique comment aligner le texte à l'intérieur du TextView layout_gravity spécifie comment aligner/mettre en forme l'élément TextView lui-même.

158
plainjimbo

Pour justifier le texte dans Android j'ai utilisé WebView

    setContentView(R.layout.main);

    WebView view = new WebView(this);
    view.setVerticalScrollBarEnabled(false);

    ((LinearLayout)findViewById(R.id.inset_web_view)).addView(view);

    view.loadData(getString(R.string.hello), "text/html; charset=utf-8", "utf-8");

et html.

<string name="hello">
<![CDATA[
<html>
 <head></head>
 <body style="text-align:justify;color:gray;background-color:black;">
  Lorem ipsum dolor sit amet, consectetur 
  adipiscing elit. Nunc pellentesque, urna
  nec hendrerit pellentesque, risus massa
 </body>
</html>
]]>
</string>

Je ne peux pas encore télécharger des images pour le prouver, mais "ça marche pour moi".

132
Konrad Nowicki

MIS À JOUR

Nous avons créé une classe simple pour cela. Il existe actuellement deux méthodes pour réaliser ce que vous recherchez. Les deux nécessitent NO WEBVIEW et SUPPORTS SPANNABLES .

BIBLIOTHÈQUE: https://github.com/bluejamesbond/TextJustify-Android

PREND EN CHARGE: Android 2.0 à 5.X

SETUP

// Please visit Github for latest setup instructions.

CAPTURE D'ÉCRAN

Comparison.png

98
Mathew Kurian

TextView dans Android O offre une justification complète (nouvel alignement typographique).

Tu as juste besoin de faire ça,

textView.setJustificationMode(JUSTIFICATION_MODE_INTER_Word);

la valeur par défaut est JUSTIFICATION_MODE_NONE.

60
Jaydipsinh Zala

Vous pouvez utiliser le projet JustifiedTextView for Android dans github. Il s'agit d'une vue personnalisée qui simule un texte justifié pour vous. Il supporte Android 2.0+ et les langues de droite à gauche. enter image description here

39
Saeed Zarinfam

J'écris un widget basé sur textview natif pour le faire.

github

28
Frank Cheng

J'ai trouvé un moyen de résoudre ce problème, mais cela n'a peut-être pas beaucoup de grâce, mais l'effet n'est pas mauvais.

Son principe est de remplacer les espaces de chaque ligne par ImageSpan à largeur fixe (la couleur est transparente).

public static void justify(final TextView textView) {

    final AtomicBoolean isJustify = new AtomicBoolean(false);

    final String textString = textView.getText().toString();

    final TextPaint textPaint = textView.getPaint();

    final SpannableStringBuilder builder = new SpannableStringBuilder();

    textView.post(new Runnable() {
        @Override
        public void run() {

            if (!isJustify.get()) {

                final int lineCount = textView.getLineCount();
                final int textViewWidth = textView.getWidth();

                for (int i = 0; i < lineCount; i++) {

                    int lineStart = textView.getLayout().getLineStart(i);
                    int lineEnd = textView.getLayout().getLineEnd(i);

                    String lineString = textString.substring(lineStart, lineEnd);

                    if (i == lineCount - 1) {
                        builder.append(new SpannableString(lineString));
                        break;
                    }

                    String trimSpaceText = lineString.trim();
                    String removeSpaceText = lineString.replaceAll(" ", "");

                    float removeSpaceWidth = textPaint.measureText(removeSpaceText);
                    float spaceCount = trimSpaceText.length() - removeSpaceText.length();

                    float eachSpaceWidth = (textViewWidth - removeSpaceWidth) / spaceCount;

                    SpannableString spannableString = new SpannableString(lineString);
                    for (int j = 0; j < trimSpaceText.length(); j++) {
                        char c = trimSpaceText.charAt(j);
                        if (c == ' ') {
                            Drawable drawable = new ColorDrawable(0x00ffffff);
                            drawable.setBounds(0, 0, (int) eachSpaceWidth, 0);
                            ImageSpan span = new ImageSpan(drawable);
                            spannableString.setSpan(span, j, j + 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
                        }
                    }

                    builder.append(spannableString);
                }

                textView.setText(builder);
                isJustify.set(true);
            }
        }
    });
}

J'ai mis le code sur GitHub: https://github.com/twiceyuan/TextJustification

Vue d'ensemble:

Overview

21
twiceYuan

XML Layout: déclarer WebView au lieu de TextView

<WebView
 Android:id="@+id/textContent"
 Android:layout_width="fill_parent"
 Android:layout_height="wrap_content" />

Code Java: définir les données texte sur WebView

WebView view = (WebView) findViewById(R.id.textContent);
String text;
text = "<html><body><p align=\"justify\">";
text+= "This is the text will be justified when displayed!!!";
text+= "</p></body></html>";
view.loadData(text, "text/html", "utf-8");

Cela peut résoudre votre problème. Son entièrement travaillé pour moi.

16
user2599233

Voici comment je l'ai fait, je pense de la manière la plus élégante possible. Avec cette solution, les seules choses à faire dans vos mises en page sont les suivantes:

  • ajouter une déclaration xmlns supplémentaire
  • changez votre espace de noms TextViews du texte source de Android en votre nouvel espace de noms
  • remplacez votre TextViews par x.y.z.JustifiedTextView

Voici le code. Fonctionne parfaitement bien sur mes téléphones (Galaxy Nexus Android 4.0.2, Galaxy Teos Android 2.1). N'hésitez pas, bien sûr, à remplacer le nom de votre paquet par le vôtre.

/ assets/excluded_textview.css:

body {
    font-size: 1.0em;
    color: rgb(180,180,180);
    text-align: justify;
}

@media screen and (-webkit-device-pixel-ratio: 1.5) {
    /* CSS for high-density screens */
    body {
        font-size: 1.05em;
    }
}

@media screen and (-webkit-device-pixel-ratio: 2.0) {
    /* CSS for extra high-density screens */
    body {
        font-size: 1.1em;
    }
}

/ res/values ​​/ attrs.xml:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="JustifiedTextView">
        <attr name="text" format="reference" />
    </declare-styleable>
</resources>

/ res/layout/test.xml:

<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:Android="http://schemas.Android.com/apk/res/Android"
    xmlns:myapp="http://schemas.Android.com/apk/res/net.bicou.myapp"
    Android:layout_width="match_parent"
    Android:layout_height="match_parent">

    <LinearLayout
        Android:layout_width="match_parent"
        Android:layout_height="wrap_content"
        Android:orientation="vertical" >

        <net.bicou.myapp.widget.JustifiedTextView
            Android:layout_width="match_parent"
            Android:layout_height="wrap_content"
            myapp:text="@string/surv1_1" />

    </LinearLayout>
</ScrollView>

/ src/net/bicou/monapp/widget/JustifiedTextView.Java:

package net.bicou.myapp.widget;

import net.bicou.myapp.R;

import Android.content.Context;
import Android.content.res.TypedArray;
import Android.graphics.Color;
import Android.util.AttributeSet;
import Android.util.TypedValue;
import Android.view.View;
import Android.webkit.WebView;

public class JustifiedTextView extends WebView {
    public JustifiedTextView(final Context context) {
        this(context, null, 0);
    }

    public JustifiedTextView(final Context context, final AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public JustifiedTextView(final Context context, final AttributeSet attrs, final int defStyle) {
        super(context, attrs, defStyle);

        if (attrs != null) {
            final TypedValue tv = new TypedValue();
            final TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.JustifiedTextView, defStyle, 0);
            if (ta != null) {
                ta.getValue(R.styleable.JustifiedTextView_text, tv);

                if (tv.resourceId > 0) {
                    final String text = context.getString(tv.resourceId).replace("\n", "<br />");
                    loadDataWithBaseURL("file:///Android_asset/",
                            "<html><head>" +
                                    "<link rel=\"stylesheet\" type=\"text/css\" href=\"justified_textview.css\" />" +
                                    "</head><body>" + text + "</body></html>",

                                    "text/html", "UTF8", null);
                    setTransparentBackground();
                }
            }
        }
    }

    public void setTransparentBackground() {
        try {
            setLayerType(View.LAYER_TYPE_SOFTWARE, null);
        } catch (final NoSuchMethodError e) {
        }

        setBackgroundColor(Color.TRANSPARENT);
        setBackgroundDrawable(null);
        setBackgroundResource(0);
    }
}

Nous devons définir le rendu sur logiciel afin d'obtenir un arrière-plan transparent sur Android 3+. D'où l'essayage des anciennes versions d'Android.

J'espère que cela t'aides!

PS: s'il vous plait, pas qu'il soit utile d'ajouter ceci à toute votre activité sur Android 3+ afin d'obtenir le comportement attendu:
Android:hardwareAccelerated="false"

9
Benoit Duffez

Bien que le texte justifié ne soit toujours pas complet, vous pouvez maintenant équilibrer les longueurs de ligne à l'aide de Android:breakStrategy="balanced" à partir de l'API 23

http://developer.Android.com/reference/Android/widget/TextView.html#attr_Android:breakStrategy

9
kassim

J'écris ma propre classe pour résoudre ce problème, la voici. Il suffit d'appeler la fonction de justification statique qui prend deux arguments.

  1. Objet de vue texte
  2. Contenu Largeur (Largeur totale de votre vue texte)

//Activité principale

package com.fawad.textjustification;
import Android.app.Activity;
import Android.database.Cursor;
import Android.graphics.Point;
import Android.graphics.Typeface;
import Android.os.Bundle;
import Android.util.DisplayMetrics;
import Android.view.Display;
import Android.view.Gravity;
import Android.view.Menu;
import Android.widget.TextView;

public class MainActivity extends Activity {
    static Point size;
    static float density;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Display display = getWindowManager().getDefaultDisplay();
        size=new Point();
        DisplayMetrics dm=new DisplayMetrics();
        display.getMetrics(dm);
        density=dm.density;
        display.getSize(size);


        TextView tv=(TextView)findViewById(R.id.textView1);
        Typeface typeface=Typeface.createFromAsset(this.getAssets(), "Roboto-Medium.ttf");
        tv.setTypeface(typeface);
        tv.setLineSpacing(0f, 1.2f);
        tv.setTextSize(10*MainActivity.density);

        //some random long text
         String myText=getResources().getString(R.string.my_text);

         tv.setText(myText);
        TextJustification.justify(tv,size.x);


    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

}

// TextJustificationClass

package com.fawad.textjustification;

import Java.util.ArrayList;

import Android.graphics.Paint;
import Android.text.TextUtils;
import Android.widget.TextView;

public class TextJustification {

    public static void justify(TextView textView,float contentWidth) {
        String text=textView.getText().toString();
        Paint paint=textView.getPaint();

        ArrayList<String> lineList=lineBreak(text,Paint,contentWidth);

        textView.setText(TextUtils.join(" ", lineList).replaceFirst("\\s", ""));
    }


    private static ArrayList<String> lineBreak(String text,Paint paint,float contentWidth){
        String [] wordArray=text.split("\\s"); 
        ArrayList<String> lineList = new ArrayList<String>();
        String myText="";

        for(String Word:wordArray){
            if(Paint.measureText(myText+" "+Word)<=contentWidth)
                myText=myText+" "+Word;
            else{
                int totalSpacesToInsert=(int)((contentWidth-Paint.measureText(myText))/Paint.measureText(" "));
                lineList.add(justifyLine(myText,totalSpacesToInsert));
                myText=Word;
            }
        }
        lineList.add(myText);
        return lineList;
    }

    private static String justifyLine(String text,int totalSpacesToInsert){
        String[] wordArray=text.split("\\s");
        String toAppend=" ";

        while((totalSpacesToInsert)>=(wordArray.length-1)){
            toAppend=toAppend+" ";
            totalSpacesToInsert=totalSpacesToInsert-(wordArray.length-1);
        }
        int i=0;
        String justifiedText="";
        for(String Word:wordArray){
            if(i<totalSpacesToInsert)
                justifiedText=justifiedText+Word+" "+toAppend;

            else                
                justifiedText=justifiedText+Word+toAppend;

            i++;
        }

        return justifiedText;
    }

}

// XML

 <RelativeLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
    xmlns:tools="http://schemas.Android.com/tools"
    Android:layout_width="match_parent"
    Android:layout_height="match_parent"

    tools:context=".MainActivity" 
    >



    <ScrollView
        Android:id="@+id/scrollView1"
        Android:layout_width="wrap_content"
        Android:layout_height="wrap_content"
         >

        <LinearLayout
            Android:layout_width="match_parent"
            Android:layout_height="match_parent"
            Android:orientation="vertical"

             >
            <TextView
        Android:id="@+id/textView1"
        Android:layout_width="wrap_content"
        Android:layout_height="wrap_content"
        Android:text="@string/hello_world" />
        </LinearLayout>
    </ScrollView>

</RelativeLayout>
6
Fawad Badar

FILL_HORIZONTAL est équivalent à CENTER_HORIZONTAL. Vous pouvez voir cet extrait de code dans le code source de textview:

case Gravity.CENTER_HORIZONTAL:
case Gravity.FILL_HORIZONTAL:
    return (mLayout.getLineWidth(0) - ((mRight - mLeft) -
            getCompoundPaddingLeft() - getCompoundPaddingRight())) /
            getHorizontalFadingEdgeLength();
5
jiashie

Il existe un CustomView pour ce problème, cette vue de texte personnalisée prend en charge la vue de texte justifiée.

Butin à ceci: JustifiedTextView

import Java.util.ArrayList;
import Android.content.Context;
import Android.graphics.Canvas;
import Android.graphics.Color;
import Android.graphics.Paint;
import Android.graphics.Typeface;
import Android.text.TextPaint;
import Android.view.View;

public class JustifiedTextView extends View {
        String text;
        ArrayList<Line> linesCollection = new ArrayList<Line>();
        TextPaint textPaint;
        Typeface font;
        int textColor;
        float textSize = 42f, lineHeight = 57f, wordSpacing = 15f, lineSpacing = 15f;
        float onBirim, w, h;
        float leftPadding, rightPadding;

        public JustifiedTextView(Context context, String text) {
                super(context);
                this.text = text;
                init();
        }

        private void init() {
                textPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
                textColor = Color.BLACK;
        }

        @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
                super.onMeasure(widthMeasureSpec, heightMeasureSpec);

                if (font != null) {
                        font = Typeface.createFromAsset(getContext().getAssets(), "font/Trykker-Regular.ttf");
                        textPaint.setTypeface(font);
                }
                textPaint.setColor(textColor);

                int minw = getPaddingLeft() + getPaddingRight() + getSuggestedMinimumWidth();
                w = resolveSizeAndState(minw, widthMeasureSpec, 1);
                h = MeasureSpec.getSize(widthMeasureSpec);

                onBirim = 0.009259259f * w;
                lineHeight = textSize + lineSpacing;
                leftPadding = 3 * onBirim + getPaddingLeft();
                rightPadding = 3 * onBirim + getPaddingRight();

                textPaint.setTextSize(textSize);

                wordSpacing = 15f;
                Line lineBuffer = new Line();
                this.linesCollection.clear();
                String[] lines = text.split("\n");
                for (String line : lines) {
                        String[] words = line.split(" ");
                        lineBuffer = new Line();
                        float lineWidth = leftPadding + rightPadding;
                        float totalWordWidth = 0;
                        for (String Word : words) {
                                float ww = textPaint.measureText(Word) + wordSpacing;
                                if (lineWidth + ww + (lineBuffer.getWords().size() * wordSpacing) > w) {// is
                                        lineBuffer.addWord(Word);
                                        totalWordWidth += textPaint.measureText(Word);
                                        lineBuffer.setSpacing((w - totalWordWidth - leftPadding - rightPadding) / (lineBuffer.getWords().size() - 1));
                                        this.linesCollection.add(lineBuffer);
                                        lineBuffer = new Line();
                                        totalWordWidth = 0;
                                        lineWidth = leftPadding + rightPadding;
                                } else {
                                        lineBuffer.setSpacing(wordSpacing);
                                        lineBuffer.addWord(Word);
                                        totalWordWidth += textPaint.measureText(Word);
                                        lineWidth += ww;
                                }
                        }
                        this.linesCollection.add(lineBuffer);
                }
                setMeasuredDimension((int) w, (int) ((this.linesCollection.size() + 1) * lineHeight + (10 * onBirim)));
        }

        @Override
        protected void onDraw(Canvas canvas) {
                super.onDraw(canvas);
                canvas.drawLine(0f, 10f, getMeasuredWidth(), 10f, textPaint);
                float x, y = lineHeight + onBirim;
                for (Line line : linesCollection) {
                        x = leftPadding;
                        for (String s : line.getWords()) {
                                canvas.drawText(s, x, y, textPaint);
                                x += textPaint.measureText(s) + line.spacing;
                        }
                        y += lineHeight;
                }
        }

        public String getText() {
                return text;
        }

        public void setText(String text) {
                this.text = text;
        }

        public Typeface getFont() {
                return font;
        }

        public void setFont(Typeface font) {
                this.font = font;
        }

        public float getLineHeight() {
                return lineHeight;
        }

        public void setLineHeight(float lineHeight) {
                this.lineHeight = lineHeight;
        }

        public float getLeftPadding() {
                return leftPadding;
        }

        public void setLeftPadding(float leftPadding) {
                this.leftPadding = leftPadding;
        }

        public float getRightPadding() {
                return rightPadding;
        }

        public void setRightPadding(float rightPadding) {
                this.rightPadding = rightPadding;
        }

        public void setWordSpacing(float wordSpacing) {
                this.wordSpacing = wordSpacing;
        }

        public float getWordSpacing() {
                return wordSpacing;
        }

        public float getLineSpacing() {
                return lineSpacing;
        }

        public void setLineSpacing(float lineSpacing) {
                this.lineSpacing = lineSpacing;
        }

        class Line {
                ArrayList<String> words = new ArrayList<String>();
                float spacing = 15f;

                public Line() {
                }

                public Line(ArrayList<String> words, float spacing) {
                        this.words = words;
                        this.spacing = spacing;
                }

                public void setSpacing(float spacing) {
                        this.spacing = spacing;
                }

                public float getSpacing() {
                        return spacing;
                }

                public void addWord(String s) {
                        words.add(s);
                }

                public ArrayList<String> getWords() {
                        return words;
                }
        }
}

Ajoutez la classe ci-dessus à votre dossier src et utilisez cet exemple de code pour ajouter à votre mise en page:

JustifiedTextView jtv= new JustifiedTextView(getApplicationContext(), "Lorem ipsum dolor sit amet... ");
LinearLayout place = (LinearLayout) findViewById(R.id.book_profile_content);
place.addView(jtv);
4
Merter

Très simple, nous pouvons le faire dans le fichier XML

<TextView 
Android:justificationMode="inter_Word"
/>
3
Machhindra Neupane

voir ici dans le github

Importez simplement les deux fichiers "TextJustifyUtils.Java" et "TextViewEx.Java" dans votre projet.

public class TextJustifyUtils {
    // Please use run(...) instead
    public static void justify(TextView textView) {
        Paint paint = new Paint();

        String[] blocks;
        float spaceOffset = 0;
        float textWrapWidth = 0;

        int spacesToSpread;
        float wrappedEdgeSpace;
        String block;
        String[] lineAsWords;
        String wrappedLine;
        String smb = "";
        Object[] wrappedObj;

        // Pull widget properties
        Paint.setColor(textView.getCurrentTextColor());
        Paint.setTypeface(textView.getTypeface());
        Paint.setTextSize(textView.getTextSize());

        textWrapWidth = textView.getWidth();
        spaceOffset = Paint.measureText(" ");
        blocks = textView.getText().toString().split("((?<=\n)|(?=\n))");

        if (textWrapWidth < 20) {
            return;
        }

        for (int i = 0; i < blocks.length; i++) {
            block = blocks[i];

            if (block.length() == 0) {
                continue;
            } else if (block.equals("\n")) {
                smb += block;
                continue;
            }

            block = block.trim();

            if (block.length() == 0)
                continue;

            wrappedObj = TextJustifyUtils.createWrappedLine(block, Paint,
                    spaceOffset, textWrapWidth);
            wrappedLine = ((String) wrappedObj[0]);
            wrappedEdgeSpace = (Float) wrappedObj[1];
            lineAsWords = wrappedLine.split(" ");
            spacesToSpread = (int) (wrappedEdgeSpace != Float.MIN_VALUE ? wrappedEdgeSpace
                    / spaceOffset
                    : 0);

            for (String Word : lineAsWords) {
                smb += Word + " ";

                if (--spacesToSpread > 0) {
                    smb += " ";
                }
            }

            smb = smb.trim();

            if (blocks[i].length() > 0) {
                blocks[i] = blocks[i].substring(wrappedLine.length());

                if (blocks[i].length() > 0) {
                    smb += "\n";
                }

                i--;
            }
        }

        textView.setGravity(Gravity.LEFT);
        textView.setText(smb);
    }

    protected static Object[] createWrappedLine(String block, Paint paint,
            float spaceOffset, float maxWidth) {
        float cacheWidth = maxWidth;
        float origMaxWidth = maxWidth;

        String line = "";

        for (String Word : block.split("\\s")) {
            cacheWidth = Paint.measureText(Word);
            maxWidth -= cacheWidth;

            if (maxWidth <= 0) {
                return new Object[] { line, maxWidth + cacheWidth + spaceOffset };
            }

            line += Word + " ";
            maxWidth -= spaceOffset;

        }

        if (Paint.measureText(block) <= origMaxWidth) {
            return new Object[] { block, Float.MIN_VALUE };
        }

        return new Object[] { line, maxWidth };
    }

    final static String SYSTEM_NEWLINE = "\n";
    final static float COMPLEXITY = 5.12f; // Reducing this will increase
                                            // efficiency but will decrease
                                            // effectiveness
    final static Paint p = new Paint();

    public static void run(final TextView tv, float origWidth) {
        String s = tv.getText().toString();
        p.setTypeface(tv.getTypeface());
        String[] splits = s.split(SYSTEM_NEWLINE);
        float width = origWidth - 5;
        for (int x = 0; x < splits.length; x++)
            if (p.measureText(splits[x]) > width) {
                splits[x] = wrap(splits[x], width, p);
                String[] microSplits = splits[x].split(SYSTEM_NEWLINE);
                for (int y = 0; y < microSplits.length - 1; y++)
                    microSplits[y] = justify(removeLast(microSplits[y], " "),
                            width, p);
                StringBuilder smb_internal = new StringBuilder();
                for (int z = 0; z < microSplits.length; z++)
                    smb_internal.append(microSplits[z]
                            + ((z + 1 < microSplits.length) ? SYSTEM_NEWLINE
                                    : ""));
                splits[x] = smb_internal.toString();
            }
        final StringBuilder smb = new StringBuilder();
        for (String cleaned : splits)
            smb.append(cleaned + SYSTEM_NEWLINE);
        tv.setGravity(Gravity.LEFT);
        tv.setText(smb);
    }

    private static String wrap(String s, float width, Paint p) {
        String[] str = s.split("\\s"); // regex
        StringBuilder smb = new StringBuilder(); // save memory
        smb.append(SYSTEM_NEWLINE);
        for (int x = 0; x < str.length; x++) {
            float length = p.measureText(str[x]);
            String[] pieces = smb.toString().split(SYSTEM_NEWLINE);
            try {
                if (p.measureText(pieces[pieces.length - 1]) + length > width)
                    smb.append(SYSTEM_NEWLINE);
            } catch (Exception e) {
            }
            smb.append(str[x] + " ");
        }
        return smb.toString().replaceFirst(SYSTEM_NEWLINE, "");
    }

    private static String removeLast(String s, String g) {
        if (s.contains(g)) {
            int index = s.lastIndexOf(g);
            int indexEnd = index + g.length();
            if (index == 0)
                return s.substring(1);
            else if (index == s.length() - 1)
                return s.substring(0, index);
            else
                return s.substring(0, index) + s.substring(indexEnd);
        }
        return s;
    }

    private static String justifyOperation(String s, float width, Paint p) {
        float holder = (float) (COMPLEXITY * Math.random());
        while (s.contains(Float.toString(holder)))
            holder = (float) (COMPLEXITY * Math.random());
        String holder_string = Float.toString(holder);
        float lessThan = width;
        int timeOut = 100;
        int current = 0;
        while (p.measureText(s) < lessThan && current < timeOut) {
            s = s.replaceFirst(" ([^" + holder_string + "])", " "
                    + holder_string + "$1");
            lessThan = p.measureText(holder_string) + lessThan
                    - p.measureText(" ");
            current++;
        }
        String cleaned = s.replaceAll(holder_string, " ");
        return cleaned;
    }

    private static String justify(String s, float width, Paint p) {
        while (p.measureText(s) < width) {
            s = justifyOperation(s, width, p);
        }
        return s;
    }
}

et

public class TextViewEx extends TextView {
    private Paint paint = new Paint();

    private String[] blocks;
    private float spaceOffset = 0;
    private float horizontalOffset = 0;
    private float verticalOffset = 0;
    private float horizontalFontOffset = 0;
    private float dirtyRegionWidth = 0;
    private boolean wrapEnabled = false;
    int left, top, right, bottom = 0;
    private Align _align = Align.LEFT;
    private float strecthOffset;
    private float wrappedEdgeSpace;
    private String block;
    private String wrappedLine;
    private String[] lineAsWords;
    private Object[] wrappedObj;

    private Bitmap cache = null;
    private boolean cacheEnabled = false;

    public TextViewEx(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        // set a minimum of left and right padding so that the texts are not too
        // close to the side screen
        // this.setPadding(10, 0, 10, 0);
    }

    public TextViewEx(Context context, AttributeSet attrs) {
        super(context, attrs);
        // this.setPadding(10, 0, 10, 0);
    }

    public TextViewEx(Context context) {
        super(context);
        // this.setPadding(10, 0, 10, 0);
    }

    @Override
    public void setPadding(int left, int top, int right, int bottom) {
        // TODO Auto-generated method stub
        super.setPadding(left + 10, top, right + 10, bottom);
    }

    @Override
    public void setDrawingCacheEnabled(boolean cacheEnabled) {
        this.cacheEnabled = cacheEnabled;
    }

    public void setText(String st, boolean wrap) {
        wrapEnabled = wrap;
        super.setText(st);
    }

    public void setTextAlign(Align align) {
        _align = align;
    }

    @SuppressLint("NewApi")
    @Override
    protected void onDraw(Canvas canvas) {
        // If wrap is disabled then,
        // request original onDraw
        if (!wrapEnabled) {
            super.onDraw(canvas);
            return;
        }

        // Active canas needs to be set
        // based on cacheEnabled
        Canvas activeCanvas = null;

        // Set the active canvas based on
        // whether cache is enabled
        if (cacheEnabled) {

            if (cache != null) {
                // Draw to the OS provided canvas
                // if the cache is not empty
                canvas.drawBitmap(cache, 0, 0, Paint);
                return;
            } else {
                // Create a bitmap and set the activeCanvas
                // to the one derived from the bitmap
                cache = Bitmap.createBitmap(getWidth(), getHeight(),
                        Config.ARGB_4444);
                activeCanvas = new Canvas(cache);
            }
        } else {
            // Active canvas is the OS
            // provided canvas
            activeCanvas = canvas;
        }

        // Pull widget properties
        Paint.setColor(getCurrentTextColor());
        Paint.setTypeface(getTypeface());
        Paint.setTextSize(getTextSize());
        Paint.setTextAlign(_align);
        Paint.setFlags(Paint.ANTI_ALIAS_FLAG);

        // minus out the paddings pixel
        dirtyRegionWidth = getWidth() - getPaddingLeft() - getPaddingRight();
        int maxLines = Integer.MAX_VALUE;
        int currentapiVersion = Android.os.Build.VERSION.SDK_INT;
        if (currentapiVersion >= Android.os.Build.VERSION_CODES.JELLY_BEAN) {
            maxLines = getMaxLines();
        }
        int lines = 1;
        blocks = getText().toString().split("((?<=\n)|(?=\n))");
        verticalOffset = horizontalFontOffset = getLineHeight() - 0.5f; // Temp
                                                                        // fix
        spaceOffset = Paint.measureText(" ");

        for (int i = 0; i < blocks.length && lines <= maxLines; i++) {
            block = blocks[i];
            horizontalOffset = 0;

            if (block.length() == 0) {
                continue;
            } else if (block.equals("\n")) {
                verticalOffset += horizontalFontOffset;
                continue;
            }

            block = block.trim();

            if (block.length() == 0) {
                continue;
            }

            wrappedObj = TextJustifyUtils.createWrappedLine(block, Paint,
                    spaceOffset, dirtyRegionWidth);

            wrappedLine = ((String) wrappedObj[0]);
            wrappedEdgeSpace = (Float) wrappedObj[1];
            lineAsWords = wrappedLine.split(" ");
            strecthOffset = wrappedEdgeSpace != Float.MIN_VALUE ? wrappedEdgeSpace
                    / (lineAsWords.length - 1)
                    : 0;

            for (int j = 0; j < lineAsWords.length; j++) {
                String Word = lineAsWords[j];
                if (lines == maxLines && j == lineAsWords.length - 1) {
                    activeCanvas.drawText("...", horizontalOffset,
                            verticalOffset, Paint);

                } else if (j == 0) {
                    // if it is the first Word of the line, text will be drawn
                    // starting from right Edge of textview
                    if (_align == Align.RIGHT) {
                        activeCanvas.drawText(Word, getWidth()
                                - (getPaddingRight()), verticalOffset, Paint);
                        // add in the paddings to the horizontalOffset
                        horizontalOffset += getWidth() - (getPaddingRight());
                    } else {
                        activeCanvas.drawText(Word, getPaddingLeft(),
                                verticalOffset, Paint);
                        horizontalOffset += getPaddingLeft();
                    }

                } else {
                    activeCanvas.drawText(Word, horizontalOffset,
                            verticalOffset, Paint);
                }
                if (_align == Align.RIGHT)
                    horizontalOffset -= Paint.measureText(Word) + spaceOffset
                            + strecthOffset;
                else
                    horizontalOffset += Paint.measureText(Word) + spaceOffset
                            + strecthOffset;
            }

            lines++;

            if (blocks[i].length() > 0) {
                blocks[i] = blocks[i].substring(wrappedLine.length());
                verticalOffset += blocks[i].length() > 0 ? horizontalFontOffset
                        : 0;
                i--;
            }
        }

        if (cacheEnabled) {
            // Draw the cache onto the OS provided
            // canvas.
            canvas.drawBitmap(cache, 0, 0, Paint);
        }
    }
}

Maintenant, si vous utilisez textView normal comme:

<TextView
                Android:id="@+id/original"
                Android:layout_width="wrap_content"
                Android:layout_height="wrap_content"
                Android:text="@string/lorum_ipsum" />

Simplement utiliser

<yourpackagename.TextViewEx
                Android:id="@+id/changed"
                Android:layout_width="wrap_content"
                Android:layout_height="wrap_content"
                Android:text="@string/lorum_ipsum" />

Définir une variable et définir justifier d'être vrai,

TextViewEx changed = (TextViewEx) findViewById(R.id.changed);
changed.setText(getResources().getString(R.string.lorum_ipsum),true);
2
Mr_Moradi

Essayez cette solution dans le lien ci-dessous, créez simplement cette classe dans le dossier du projet et utilisez-la. Ça fonctionne bien pour moi :)

Justifiez le texte dans une application Android à l'aide d'une vue Web mais présentant une interface de type TextView?

2
Yoganand.N

Sur Android, pour justifier le texte à gauche et ne pas tronquer la couleur de fond, essayez-le, cela a fonctionné pour moi et produire des résultats cohérents sur Android, ff, c.-à-d. & chrome mais vous devez mesurer l'espace qui est disponible. laissé entre les deux pour le texte lors du calcul du remplissage.

<td style="font-family:Calibri,Arial;
    font-size:15px;
    font-weight:800;
    background-color:#f5d5fd;
    color:black;
    border-style:solid;
    border-width:1px;
    border-color:#bd07eb;
    padding-left:10px;
    padding-right:1000px;
    padding-top:3px;
    padding-bottom:3px;
>

Le hack est le padding-right:1000px; qui pousse le texte à l'extrême gauche.

Toute tentative de gauche ou de justification de code en css ou html entraîne un arrière-plan de seulement une demi-largeur.

2
Robin Glas

Android ne supporte pas encore la justification complète. Nous pouvons utiliser Webview et justifier HTML au lieu d'utiliser textview. Cela fonctionne si bien. Si vous n'êtes pas clairs, n'hésitez pas à me demander :)

2
kypiseth

Je pense qu'il y a deux options:

  • Utilisez quelque chose comme Pango spécialisé dans ce domaine via le NDK et restituez le texte sur une surface OpenGL ou autre.

  • Utilisez Paint.measureText () et amis pour obtenir la longueur des mots et les disposer manuellement sur un canevas dans une vue personnalisée.

2
Matthew Willis

Pour le formatage HTML, vous n'avez pas besoin d'appeler le Webkit, vous pouvez utiliser Html.fromHtml(text) pour effectuer le travail.

Source: http://developer.Android.com/guide/topics/resources/string-resource.html

1
SaturnTheIcy