Android TextView Testo giustificato


396

Come si ottiene che il testo di TextViewa sia giustificato (con il testo a filo sui lati sinistro e destro)?

Ho trovato una possibile soluzione qui , ma non funziona (anche se cambi vertical-center in center_vertical, ecc.).


La risposta di @Jimbo funziona correttamente per il mio caso su inputtext e textview per la lingua araba da input e display da destra a sinistra, ma per il testo di input ho dovuto aggiungere anche la gravità = "right"
shareef

Risposte:


240

Non credo che Android supporti la piena giustificazione.

AGGIORNAMENTO 2018-01-01 : Android 8.0+ supporta le modalità di giustificazione conTextView .


5
Dopo ulteriori analisi, potresti dare un colpo a android: gravity = "fill_horizontal". Questo è descritto come "Aumenta la dimensione orizzontale dell'oggetto se necessario in modo da riempire completamente il suo contenitore", ma non so come "crescano" il testo.
CommonsWare,

8
android: gravity = "fill_horizontal" non ha funzionato neanche. Sembra che Android non supporti la giustificazione dopo tutto, oh bene :)

6
No, non puoi impostare la proprietà come la gravità. Tuttavia, puoi impostare la giustificazione per il tuo testo eseguendo la visualizzazione Web anziché la visualizzazione testo. Puoi fare riferimento a seal.io/2010/12/only-way-how-to-align-text-in-block-in.html . (Stola da stackoverflow.com/questions/5976627/... )
jcaruso

2
@CommonsWare Ora un modo corretto di giustificare il testo?
John R,

1
Amico, sto vivendo una pesante webview per raggiungere questo obiettivo, e credimi, la mia UI piange per alcune nuove cose che devono ancora essere aggiunte all'API, perché è dannatamente lento per componenti come la chat in una lista.
nobalG,

156

La risposta @CommonsWare è corretta. Android 8.0+ supporta la "Giustificazione completa" (o semplicemente la "Giustificazione", come talvolta viene definita ambiguamente).

Android supporta anche "Allineamento del testo a sinistra / a destra". Vedi l'articolo di Wikipedia sulla giustificazione per la distinzione. Molte persone considerano il concetto di "giustificazione" che comprende la piena giustificazione e l'allineamento del testo a sinistra / a destra, che è ciò che cercano quando vogliono fare l'allineamento a sinistra / a destra. Questa risposta spiega come ottenere l'allineamento del testo a sinistra / a destra.

È possibile ottenere l'allineamento del testo a sinistra / a destra (al contrario della giustificazione completa, poiché la domanda si pone). Per dimostrare userò un modulo base a 2 colonne (etichette nella colonna sinistra e campi di testo nella colonna destra) come esempio. In questo esempio il testo nelle etichette nella colonna di sinistra sarà allineato a destra in modo che appaiano allineati con i loro campi di testo nella colonna di destra.

Nel layout XML è possibile ottenere gli elementi TextView stessi (la colonna di sinistra) per allinearli a destra aggiungendo il seguente attributo all'interno di tutte le visualizzazioni di testo:

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

Tuttavia, se il testo si sposta su più righe, il testo verrebbe comunque allineato a sinistra allineato all'interno di TextView. L'aggiunta del seguente attributo allinea il testo effettivo allineato a destra (sfilacciato a sinistra) all'interno di TextView:

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

Quindi l' attributo gravity specifica come allineare il testo all'interno di TextView layout_gravity specifica come allineare / layout l'elemento TextView stesso.


12
Se capisco correttamente, e dati i risultati del test, tutto ciò che fa è allineare il testo a sinistra o a destra. Questo non giustifica il testo, vero?
Paul Lammertsma,

14
Eccellente. Solo per aggiungere, se vuoi una giustificazione centrale, puoi farlo android:layout_gravity="center_horizontal|center" android:gravity="center".
Luis A. Florit,

sicuramente lavorando per il mio caso su inputtext e textview per la lingua araba da destra a sinistra input e display
shareef

1
Questo è solo allineamento, non giustificazione. Leggi attentamente quel link di Wikipedia. La differenza tra i diversi tipi di giustificazione riguarda solo l'ultima riga di un paragrafo. Non esiste una giustificazione sinistra / destra / centro per i paragrafi che hanno solo una riga.
Karu,

allora perché anche rispondere qui se non si trattajustify
user924

136

Per giustificare il testo in Android ho usato 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");

e 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>

Non riesco ancora a caricare immagini per dimostrarlo ma "funziona per me".


3
Bella soluzione qui. FWIW non hai bisogno della maggior parte dell'html extra. Il tag body con text align è sufficiente.
Gnac,

5
Funziona bene Si noti che è possibile rendere trasparente lo sfondo seguendo view.loadData()con view.setBackgroundColor("#00000000").
Paul Lammertsma,

Tuttavia, non sono riuscito a farlo caricare un carattere / carattere personalizzato. Ho provato questo e questo suggerimento, senza fortuna.
Paul Lammertsma,

2
Come ho già detto in quei thread, ho trovato una risoluzione: se si crea un file HTML e lo si inserisce negli asset, caricandolo tramite view.loadUrl()Works, mentre view.loadData()non lo è. Non ho idea del perché quest'ultimo non lo faccia.
Paul Lammertsma,

1
@PaulLammertsma, setBackgroundColor (0x00000000) sarebbe piuttosto il formato corretto per l'impostazione dello sfondo trasparente.
Richey,

100

AGGIORNATO

Abbiamo creato una classe semplice per questo. Esistono attualmente due metodi per ottenere ciò che stai cercando. Entrambi non richiedono WEBVIEW e SPANNABLES DI SUPPORTO .

BIBLIOTECA : https://github.com/bluejamesbond/TextJustify-Android

SUPPORTI : da Android 2.0 a 5.X

IMPOSTARE

// Please visit Github for latest setup instructions.

IMMAGINE DELLO SCHERMO

Comparison.png


È davvero un aiuto, ma usandolo, le mie TextViews non mantengono il formato originale, mi rifaccio: margini, stile del testo e penso che nessuna dimensione del testo, Plese continui a lavorarci, dovrebbe essere davvero di grande aiuto
Leonardo Sapuy

Beh, non posso stabilire quelle classi. uno di loro non aveva alcun nome per il pacchetto, l'altro ha qualche errore giallo. In realtà non posso fidarmi.
Mehmet,

Bella libreria, ma non so ancora come aggiungere alcuna formattazione al testo usando questa libreria.
Semanticer,

4
Grazie per questa fantastica libreria condivisa, ma non può supportare il testo persiano o arabo. Quando imposto la direzione, la mia parola disegna dall'inizio alla fine, anziché dall'inizio alla fine. Intendo questo: la mia parola è: "سلام" e il suo disegno in questo modo: "مالس". (se non capisci il persiano, vedi questo esempio: fammi "1234" -> "4321")
Naruto Uzumaki,

1
Basato su scrollView ... Bella soluzione ma non riesco ancora a trovare alcuna risposta che la renda possibile con textview. :(
superUser

88

TextView in Android O offre la giustificazione completa (nuovo allineamento tipografico) stesso.

Hai solo bisogno di fare questo:

Kotlin

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
    textView.justificationMode = JUSTIFICATION_MODE_INTER_WORD
}

Giava

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
    textView.setJustificationMode(JUSTIFICATION_MODE_INTER_WORD);
}

il valore predefinito è JUSTIFICATION_MODE_NONE.


3
Speriamo che venga riportato nella libreria di supporto, quindi O :)
Stefan Haustein,

2
per favore aggiungi la libreria qui !!
Kunal Dharaiya,

4
come giustificare l'utilizzo di XML?
Vikash Parajuli

14
Puoi usare android: justificMode = "inter_word" in xml.
Christian D,

5
API 26 richiesta per android: justificMode.
Bink,

42

Puoi usare JustifiedTextView per il progetto Android in github. questa è una vista personalizzata che simula il testo giustificato per te. Supporta Android 2.0+ e le lingue da destra a sinistra. inserisci qui la descrizione dell'immagine


non supporta le stringhe modificabili
MSepehr

come possiamo aggiungere il nostro testo?
Karan,

Si prega di consultare l'esempio su github.
Saeed Zarinfam,

ciao Saeed, grazie per il tuo aiuto, esiste un modo per supportare visualizzazioni di testo spannabili ?!
Hamid Reza,

@SaeedZarinfam Ho provato a usare "JustifiedTextView per Android" ma ho ricevuto un errore sul tag xml ir.noghteh.JustifiedTextView mi aiuteresti ad aiutarmi su questa domanda stackoverflow.com/questions/37911376/…
Jumong

30

Scrivo una base di widget su textview nativo per farlo.

github


lo avrei raccomandato, soprattutto perché è basato nella visualizzazione di testo originale dell'SDK ufficiale di Android, che secondo la mia opinione personale è un modo molto più leggero della tecnica della webview che molte persone pubblicano su questo argomento comune. Se si crea un'app che deve essere basata sulla memoria, ad esempio utilizzando gli oggetti listview, è possibile considerare l'utilizzo di qualcosa del genere. Ï già provalo e funziona come previsto. Se conoscete qualcun altro meglio di questo 1, per favore, potreste condividere la vostra esperienza con me.
superUser

Bel lavoro tra l'altro. Quello che stavo cercando.
superUser

5
non supporta le lingue RTL come il persiano
fuoco nella buca,

1
@Frank Cheng Biblioteca molto utile. Ottengo molti spazi alla fine del paragrafo. Come posso ripararlo?
iSrinivasan27,

1
ha funzionato per me, ma l'ultima riga della visualizzazione del testo è stata tagliata. Ho dovuto continuare a riempire 5 per la visualizzazione del testo.
Tharaka Nirmana,

23

Ho trovato un modo per risolvere questo problema, ma potrebbe non essere molto grazia, ma l'effetto non è male.

Il suo principio è quello di sostituire gli spazi di ogni linea con ImageSpan a larghezza fissa (il colore è trasparente).

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

Ho inserito il codice su GitHub: https://github.com/twiceyuan/TextJustification

Panoramica:

Panoramica


1
Non funziona nell'anteprima XML ma funziona alla grande con un dispositivo reale :)
pgreze

15

Layout XML: dichiarare WebView anziché TextView

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

Codice Java: imposta i dati di testo su 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");

Questo potrebbe risolvere il tuo problema. Ha funzionato completamente per me.


9

Ecco come l'ho fatto, penso nel modo più elegante che potevo. Con questa soluzione, le uniche cose che devi fare nei tuoi layout sono:

  • aggiungere una xmlnsdichiarazione aggiuntiva
  • cambia il tuo TextView spazio dei nomi di testo sorgente da Android al tuo nuovo spazio dei nomi
  • sostituisci i tuoi TextViewconx.y.z.JustifiedTextView

Ecco il codice. Funziona perfettamente sui miei telefoni (Galaxy Nexus Android 4.0.2, Galaxy Teos Android 2.1). Sentiti libero di sostituire il nome del mio pacchetto con il tuo.

/assets/justified_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/myapp/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);
    }
}

Dobbiamo impostare il rendering sul software per ottenere uno sfondo trasparente su Android 3+. Da qui il try-catch per le versioni precedenti di Android.

Spero che sia di aiuto!

PS: per favore, non che potrebbe essere utile aggiungere questo a tutta la tua attività su Android 3+ per ottenere il comportamento previsto:
android:hardwareAccelerated="false"


Questa è una soluzione basata su webView. Qualcuno ha ancora trovato la visualizzazione testuale, considerando che la visualizzazione testuale è più leggera di webview e scrollview.
superUser

9

Molto semplice Possiamo farlo nel file xml

<TextView 
android:justificationMode="inter_word"
/>


6

Scrivo la mia classe per risolvere questo problema, qui è solo che devi chiamare la funzione di giustificazione statica che accetta due argomenti

  1. Testo Visualizza oggetto
  2. Larghezza contenuto (larghezza totale della visualizzazione del testo)

//Attività 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>

i motivi completano questo esempio almeno affinché "\ n" o System.getProperty ("line.separator") rispettino :)
ceph3us

5

FILL_HORIZONTALè equivalente a CENTER_HORIZONTAL. Puoi vedere questo snippet di codice nel codice sorgente di textview:

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

4

Esiste un CustomView per questo problema, questa visualizzazione di testo personalizzata supporta la visualizzazione di testo giustificato.

Fai bottino a questo: 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;
                }
        }
}

Aggiungi la classe sopra alla cartella src e usa questo codice di esempio per aggiungere al tuo layout:

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

4

Vedere qui nel github

Basta importare i due file "TextJustifyUtils.java" e "TextViewEx.java" nel progetto.

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

e

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

Ora, se usi textView normale come:

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

Basta usare

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

Definire una variabile e impostare giustificare come vero,

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

il testo in grassetto non funziona, per favore aiutatemi se hai qualche correzione?
praveenb,

4

Testo Android giustificato per TextView XML

Semplicemente Android giustifica il testo usando in XML. Puoi semplicemente implementare nel widget di visualizzazione di testo.

 <TextView
    android:justificationMode="inter_word"
/>

L'impostazione predefinita è android:justificationMode="none"


2

Penso che ci siano due opzioni:

  • Usa qualcosa come Pango specializzato in questo tramite NDK e esegui il rendering del testo su OpenGL o altra superficie.

  • Usa Paint.measureText () e gli amici per ottenere la lunghezza delle parole e disporle manualmente su una tela in una vista personalizzata.


2

Su Android, a sinistra per giustificare il testo e non avere il troncamento del colore di sfondo, prova questo, ha funzionato per me, producendo risultati coerenti su Android, FF, ie & Chrome, ma devi misurare lo spazio che rimane nel mezzo per il testo quando si calcola l'imbottitura.

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

L'hacking è quello padding-right:1000px;che spinge il testo all'estrema sinistra.

Qualsiasi tentativo di spostare a sinistra o giustificare il codice in CSS o HTML produce uno sfondo di solo metà larghezza.



1

Android non supporta ancora la piena giustificazione. Possiamo usare Webview e giustificare HTML invece di usare textview. Funziona così bene. Se non siete chiari, non esitate a chiedermelo :)


Questo può essere fatto. Ma possiamo impostare lo sfondo di WebView transparent. Ho un'immagine di sfondo.
Mr.India,

Non penso che questo potrebbe essere un aspetto saggio della memoria.
superUser


1

Giustificazione dei contenuti di TextView: i suoi semplici ragazzi usano semplicemente android: justificMode = "inter_word" all'interno del tag TextView.

 <TextView
    android:id="@+id/textView2"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginTop="92dp"
    android:text="@string/contents"
    android:layout_margin="20dp"
    android:justificationMode="inter_word"
     />

-4

Prova a usare < RelativeLayout >(assicurandoti di fill_parent), quindi aggiungi android:layout_alignParentLeft="true"e

android:layout_alignParentRight="true" agli elementi che desideri all'esterno SINISTRA e DESTRA.

BLAM, giustificato!



3
Non è ancora quello che sta cercando. Vedi giustificazione su Wikipedia: en.wikipedia.org/wiki/Justification_(typesetting)
Kevin Coppock

Non è una giustificazione
Arash Hatami,

-5

Devi impostare

android:layout_height="wrap_content"

e

android:layout_centerInParent="true"

11
Questo centra il testo che non è piena giustificazione
Janusz,

-12

Questo non giustifica davvero il tuo testo ma

android:gravity="center_horizontal"

è la scelta migliore che hai.


9
No, questo centra il testo. Non lo giustifica. Citando Wikipedia : "Nel testo giustificato, gli spazi tra le parole e, in misura minore, tra glifi o le lettere (crenatura), sono allungati o talvolta compressi per allineare il testo con i margini sinistro e destro".
Commons War

il testo non è giustificato dal tuo codice ma centra il testo in orizzontale
Matteo,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.