Android TextView Justify Text

396

Bagaimana Anda membuat teks a TextViewdibenarkan (dengan teks rata di sisi kiri dan kanan)?

Saya menemukan solusi yang mungkin di sini , tetapi tidak berhasil (bahkan jika Anda mengubah vertikal-center ke center_vertical, dll).

Bill the Lizard
sumber
@Jimbo jawaban benar benar bekerja untuk kasus saya pada inputtext dan textview untuk bahasa arab dari kanan ke kiri input dan tampilan tetapi untuk input teks saya harus menambahkan juga gravitasi = "kanan"
shareef
Anda dapat menggunakan github.com/pouriaHemmati/JustifiedTextView
Pouria Hemati

Jawaban:

240

Saya tidak percaya Android mendukung pembenaran penuh.

UPDATE 2018-01-01 : Android 8.0+ mendukung mode justifikasi denganTextView .

CommonsWare
sumber
5
Setelah analisis lebih lanjut, Anda dapat memberikan suntikan android: gravity = "fill_horizontal". Itu digambarkan sebagai "Tumbuhkan ukuran horizontal objek jika diperlukan sehingga benar-benar mengisi wadahnya", tetapi saya tidak tahu bagaimana mereka "menumbuhkan" teks.
CommonsWare
8
android: gravity = "fill_horizontal" juga tidak berfungsi. Sepertinya android tidak mendukung pembenaran setelah semua, oh baik :)
6
Tidak, Anda tidak dapat mengatur properti seperti gravitasi. Namun Anda masih dapat mengatur pembenaran untuk teks Anda dengan mengambil tampilan web alih-alih tampilan teks. Anda dapat merujuk ke seal.io/2010/12/only-way-how-to-align-text-in-block-in.html . (Dicuri dari stackoverflow.com/questions/5976627/… )
jcaruso
2
@CommonsWare Sekarang ada cara yang tepat untuk membenarkan teks?
John R
1
Sobat, saya hidup dengan tampilan web yang berat untuk mencapai hal ini, dan percayalah, UI saya meminta beberapa hal baru yang belum ditambahkan ke API, karena sangat lambat untuk komponen seperti obrolan dalam listview.
nobalG
156

Jawaban @CommonsWare benar. Android 8.0+ mendukung "Pembenaran Penuh" (atau hanya "Pembenaran", karena kadang-kadang disebut secara ambigu).

Android juga mendukung "Flush Left / Right Text Alignment". Lihat artikel wikipedia tentang Justifikasi untuk perbedaannya. Banyak orang mempertimbangkan konsep 'justifikasi' untuk mencakup justifikasi penuh serta perataan teks kiri / kanan, yang akhirnya mereka cari ketika ingin melakukan perataan teks kiri / kanan. Jawaban ini menjelaskan cara mencapai perataan teks kiri / kanan.

Dimungkinkan untuk mencapai Alignment Teks Kiri / Kanan rata (berlawanan dengan Pembenaran Penuh, karena pertanyaannya adalah tentang). Untuk menunjukkan saya akan menggunakan formulir 2-kolom dasar (label di kolom kiri dan bidang teks di kolom kanan) sebagai contoh. Dalam contoh ini teks dalam label di kolom kiri akan rata kanan sehingga mereka muncul rata terhadap bidang teks mereka di kolom kanan.

Di tata letak XML Anda bisa mendapatkan elemen TextView sendiri (kolom kiri) untuk menyelaraskan ke kanan dengan menambahkan atribut berikut di dalam semua TextViews:

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

Namun, jika teks membungkus ke beberapa baris, teks akan tetap rata kiri di dalam TextView. Menambahkan atribut berikut membuat teks aktual rata rata (kiri kasar) di dalam TextView:

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

Jadi atribut gravitasi menentukan cara menyelaraskan teks di dalam TextView layout_gravity menentukan cara menyelaraskan / tata letak elemen TextView itu sendiri.

plainjimbo
sumber
12
Jika saya mengerti benar, dan diberi hasil pengujian ini, semua ini dilakukan adalah menyelaraskan teks ke kiri atau kanan. Ini tidak membenarkan teksnya, bukan?
Paul Lammertsma
14
Luar biasa. Untuk menambahkan, jika Anda ingin pembenaran pusat, Anda dapat melakukannya android:layout_gravity="center_horizontal|center" android:gravity="center".
Luis A. Florit
jelas bekerja untuk kasus saya pada inputtext dan textview untuk bahasa arab dari input dan display kanan ke kiri
shareef
1
Ini hanya keberpihakan, bukan pembenaran. Baca tautan Wikipedia itu dengan cermat. Perbedaan antara berbagai jenis pembenaran hanya memengaruhi baris terakhir paragraf. Tidak ada justifikasi kiri / kanan / tengah untuk paragraf yang hanya memiliki satu baris.
Karu
lalu mengapa bahkan menjawabnya di sini jika ini bukan tentangjustify
user924
136

Untuk membenarkan teks di android saya menggunakan 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");

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

Saya belum dapat mengunggah gambar untuk membuktikannya, tetapi "berhasil untuk saya".

Konrad Nowicki
sumber
3
Solusi yang bagus di sini. FWIW Anda tidak membutuhkan sebagian besar html tambahan. Tag tubuh dengan perataan teks sudah cukup.
gnac
5
Ini bekerja dengan baik. Perhatikan bahwa Anda dapat membuat latar belakang transparan dengan mengikuti view.loadData()dengan view.setBackgroundColor("#00000000").
Paul Lammertsma
Namun, saya belum berhasil membuatnya memuat font / jenis huruf khusus. Saya sudah mencoba ini dan ini saran, tanpa keberuntungan.
Paul Lammertsma
2
Seperti yang saya sebutkan di utas tersebut, saya menemukan resolusi: jika Anda membuat file HTML dan meletakkannya di aset, memuatnya melalui view.loadUrl()karya, sedangkan view.loadData()tidak. Saya tidak tahu mengapa yang terakhir tidak.
Paul Lammertsma
1
@ PaulLammertsma, setBackgroundColor (0x00000000) lebih suka format yang benar untuk pengaturan latar belakang transparan.
richey
100

DIPERBARUI

Kami telah membuat kelas sederhana untuk ini. Saat ini ada dua metode untuk mencapai apa yang Anda cari. Keduanya TIDAK memerlukan WEBVIEW dan DUKUNGAN SPANNABLES .

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

DUKUNGAN : Android 2.0 hingga 5.X

MENDIRIKAN

// Please visit Github for latest setup instructions.

SCREENSHOT

Comparison.png

Mathew Kurian
sumber
Benar-benar membantu, tetapi menggunakannya, TextViews saya tidak menyimpan format asli, saya menolak: margin, gaya teks, dan saya pikir ukuran teks juga, Plese terus bekerja di dalamnya, harus menjadi bantuan yang sangat hebat
Leonardo Sapuy
Ya saya tidak bisa membuat kelas-kelas itu. salah satu dari mereka tidak memiliki nama paket, yang lain memberikan beberapa kesalahan kuning. Sebenarnya saya tidak bisa percaya.
mehmet
Lib bagus, tapi saya masih tidak tahu cara menambahkan format apa pun ke Teks menggunakan perpustakaan ini.
Semanticer
4
Terima kasih atas pustaka bersama yang hebat ini, tetapi tidak dapat mendukung teks Persia atau Arab. Ketika saya menetapkan arah, kata saya menarik dari yang terakhir ke yang awal, alih-alih mulai dari yang terakhir. Maksud saya ini: Firman saya adalah: "سلام" dan gambarnya seperti ini: "مالس". (jika Anda tidak mengerti bahasa Persia, lihat contoh ini: izinkan saya "1234" -> "4321")
Naruto Uzumaki
1
Berdasarkan scrollView ... Solusi yang bagus namun tidak dapat menemukan jawaban yang membuatnya mungkin dengan textview. :(
superUser
88

TextView di Android O menawarkan pembenaran penuh (alignment tipografi baru) itu sendiri.

Anda hanya perlu melakukan ini:

Kotlin

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

Jawa

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

standarnya adalah JUSTIFICATION_MODE_NONE.

Jaydipsinh Zala
sumber
3
Mari kita berharap itu akan dipindahkan kembali ke perpustakaan dukungan kemudian O :)
Stefan Haustein
2
tolong tambahkan perpustakaan di sini !!
Kunal Dharaiya
4
bagaimana cara membenarkan menggunakan XML?
Vikash Parajuli
14
Anda dapat menggunakan android: justificationMode = "inter_word" dalam xml.
Christian D
5
API 26 diperlukan untuk android: justificationMode.
Bink
42

Anda dapat menggunakan proyek JustifiedTextView untuk Android di github. ini adalah tampilan khusus yang mensimulasikan teks yang dibenarkan untuk Anda. Ini mendukung Android 2.0+ dan bahasa kanan ke kiri. masukkan deskripsi gambar di sini

Saeed Zarinfam
sumber
itu tidak mendukung string yang dapat di
spannable
bagaimana kita bisa menambahkan teks kita sendiri?
Karan
Silakan lihat sampel di github.
Saeed Zarinfam
hai Saeed, tnx atas bantuan Anda, apakah ada cara untuk mendukung tampilan teks yang dapat dip spannable ?!
Hamid Reza
@SaeedZarinfam Saya mencoba menggunakan "JustifiedTextView untuk Android" tetapi saya mendapat kesalahan pada tag xml ir.noghteh.JustifiedTextView akan tolong bantu saya dalam pertanyaan ini stackoverflow.com/questions/37911376/…
Jumong
30

Saya menulis basis widget pada tampilan teks asli untuk melakukannya.

github

Frank Cheng
sumber
Saya telah merekomendasikan yang ini, sebagian besar karena berbasis di tampilan teks asli dari android resmi SDK, yang menurut pendapat pribadi saya itu adalah cara yang lebih ringan daripada teknik tampilan web yang banyak orang posting mengenai topik umum ini. Jika Anda membuat aplikasi yang membutuhkan ingatan bijaksana, misalnya menggunakan objek tampilan daftar, Anda dapat mempertimbangkan untuk menggunakan sesuatu seperti ini. Ï sudah mencobanya, dan berfungsi seperti yang diharapkan. Jika Anda orang lain yang lebih tahu seperti ini, silakan bagikan pengalaman Anda kepada saya.
superUser
Kerja bagus btw. Apa yang saya cari.
superUser
5
tidak mendukung bahasa RTL seperti persia
tembak dalam lubang
1
@ Frank Cheng Perpustakaan Sangat Berguna. Saya mendapatkan banyak ruang di akhir paragraf. Bagaimana saya bisa memperbaikinya?
iSrinivasan27
1
bekerja untuk saya, tetapi baris terakhir dari tampilan teks terputus. Saya harus tetap padding 5 untuk tampilan teks.
TharakaNirmana
23

Saya menemukan cara untuk menyelesaikan masalah ini, tetapi ini mungkin bukan rahmat, tetapi efeknya tidak buruk.

Prinsipnya adalah mengganti spasi setiap baris ke ImageSpan dengan lebar tetap (warnanya transparan).

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

Saya menaruh kode di GitHub: https://github.com/twiceyuan/TextJustification

Gambaran:

Gambaran

dua kali Yuan
sumber
1
Tidak bekerja dalam pratinjau XML tetapi bekerja dengan perangkat nyata :)
pgreze
15

Layout XML: nyatakan WebView bukan TextView

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

Kode Java: atur data teks ke 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");

Ini dapat memecahkan masalah Anda. Sepenuhnya bekerja untuk saya.


sumber
9

Inilah cara saya melakukannya, saya pikir cara paling elegan yang saya bisa. Dengan solusi ini, satu-satunya hal yang perlu Anda lakukan di tata letak adalah:

  • tambahkan xmlnsdeklarasi tambahan
  • ubah-Mu TextView sumber teks namespace Anda dari android ke namespace baru Anda
  • ganti TextViewdengan Andax.y.z.JustifiedTextView

Ini kodenya. Bekerja dengan sangat baik pada ponsel saya (Galaxy Nexus Android 4.0.2, Galaxy Teos Android 2.1). Tentu saja merasa bebas untuk mengganti nama paket saya dengan milik Anda.

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

Kita perlu mengatur rendering ke perangkat lunak untuk mendapatkan latar belakang transparan pada Android 3+. Oleh karena itu coba-coba untuk Android versi lama.

Semoga ini membantu!

PS: mohon jangan berguna untuk menambahkan ini ke seluruh aktivitas Anda di Android 3+ untuk mendapatkan perilaku yang diharapkan:
android:hardwareAccelerated="false"

Benoit Duffez
sumber
Ini adalah solusi berbasis webView. Setiap orang telah menemukan berdasarkan textview, mengingat textview lebih ringan daripada tampilan web dan scrollview.
superUser
9

Sangat Sederhana. Kita dapat melakukannya di file xml

<TextView 
android:justificationMode="inter_word"
/>
Machhindra Neupane
sumber
6

Saya menulis kelas saya sendiri untuk menyelesaikan masalah ini, Ini dia Just Anda harus memanggil fungsi justify statis yang membutuhkan dua argumen

  1. Objek Tampilan Teks
  2. Lebar Konten (Total lebar tampilan teks Anda)

//Aktifitas utama

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>
Fawad Badar
sumber
mohon lengkapi contoh ini setidaknya untuk "\ n" atau System.getProperty ("line.separator") untuk menghormati :)
ceph3us
5

FILL_HORIZONTALsetara dengan CENTER_HORIZONTAL. Anda dapat melihat potongan kode ini dalam kode sumber textview:

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

Ada CustomView untuk masalah ini, tampilan teks khusus ini mendukung Tampilan Teks yang Dibenarkan.

Loot at this: 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;
                }
        }
}

Tambahkan kelas di atas ke folder src Anda dan gunakan kode sampel ini untuk menambah tata letak Anda:

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

lihat di sini di github

Impor saja dua file "TextJustifyUtils.java" dan "TextViewEx.java" di proyek Anda.

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

dan

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

Sekarang, jika Anda menggunakan textView biasa seperti:

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

Cukup gunakan

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

Tentukan variabel dan set justify true,

TextViewEx changed = (TextViewEx) findViewById(R.id.changed);
changed.setText(getResources().getString(R.string.lorum_ipsum),true);
Tuan_Moradi
sumber
teks tebal tidak berfungsi, tolong bantu jika Anda memiliki perbaikan untuk itu?
praveenb
4

Teks Android Membenarkan Untuk TextView XML

Cukup android teks-justify menggunakan dalam XML. Anda cukup menerapkan di widget textview.

 <TextView
    android:justificationMode="inter_word"
/>

Defaultnya adalah android:justificationMode="none"

Samad Talukder
sumber
2

Saya pikir ada dua opsi:

  • Gunakan sesuatu seperti Pango yang berspesialisasi dalam hal ini melalui NDK dan render teks ke OpenGL atau permukaan lainnya.

  • Gunakan Paint.measureText () dan teman-teman untuk mendapatkan panjang kata dan meletakkannya secara manual di atas Kanvas dalam tampilan kustom.

Matthew Willis
sumber
2

Di android, untuk meninggalkan justifikasi teks dan tidak memiliki pemotongan warna latar belakang, coba ini, itu bekerja untuk saya, menghasilkan hasil yang konsisten pada android, ff, yaitu & chrome tetapi Anda harus mengukur ruang yang tersisa di antara untuk teks saat menghitung padding.

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

Retas adalah padding-right:1000px;yang mendorong teks ke kiri ekstrim.

Setiap upaya ke kiri atau membenarkan kode dalam css atau html menghasilkan latar belakang yang hanya setengah lebar.

Robin Glas
sumber
1

Android belum mendukung pembenaran penuh. Kita dapat menggunakan Webview dan membenarkan HTML alih-alih menggunakan textview. Ini bekerja dengan sangat baik. Jika kalian tidak jelas, jangan ragu untuk bertanya kepada saya :)

Kypiseth
sumber
Itu bisa dilakukan. Tapi bisakah kita mengatur latar belakang WebView transparent. Saya memiliki gambar latar belakang.
Mr.India
Saya tidak berpikir ini mungkin ingatan bijak.
superUser
1

TextView Content Justification: Mudahnya, gunakan saja android: justificationMode = "inter_word" di dalam tag TextView Anda.

 <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"
     />
Ashraf Gardizy
sumber
-4

Coba gunakan < RelativeLayout >(pastikan untuk fill_parent), lalu tambahkan android:layout_alignParentLeft="true"dan

android:layout_alignParentRight="true" ke elemen yang Anda inginkan di luar KIRI & KANAN.

BLAM, dibenarkan!

esharp
sumber
contoh yang bagus di sini: stackoverflow.com/questions/2099249/…
esharp
3
Tetap bukan yang dia cari. Lihat Pembenaran di Wikipedia: en.wikipedia.org/wiki/Justification_(typesetting)
Kevin Coppock
Itu bukan pembenaran
Arash Hatami
-5

Anda harus mengatur

android:layout_height="wrap_content"

dan

android:layout_centerInParent="true"
Lukas
sumber
11
Ini memusatkan teks yang tidak justifikasi penuh
Janusz
-12

Ini tidak benar-benar membenarkan teks Anda tetapi

android:gravity="center_horizontal"

adalah pilihan terbaik yang Anda miliki.

Wolfen
sumber
9
Tidak, itu pusat teks. Itu tidak membenarkannya. Mengutip Wikipedia : "Dalam teks yang dibenarkan, spasi di antara kata-kata, dan, pada tingkat yang lebih rendah, antara mesin terbang atau huruf (kerning), diregangkan atau kadang-kadang dikompresi untuk membuat teks sejajar dengan margin kiri dan kanan."
CommonsWare
teks tidak dibenarkan oleh kode Anda tetapi tengah horizontal teks
Matteo