Android TextView Justify Text

396

Как вы получаете текст a, TextViewкоторый будет оправдан (с текстом сбоку на левой и правой сторонах)?

Я нашел возможное решение здесь , но оно не работает (даже если вы измените вертикальный-центр на center_vertical и т. Д.).

Билл Ящерица
источник
@Jimbo - правильный ответ для моего случая на inputtext и textview для арабского языка справа налево для ввода и отображения, но для входного текста мне пришлось добавить также gravity = "right"
shareef 21.12.12
Вы можете использовать github.com/pouriaHemmati/JustifiedTextView
Pouria Hemati

Ответы:

240

Я не верю, что Android поддерживает полное оправдание.

ОБНОВЛЕНИЕ 2018-01-01 : Android 8.0+ поддерживает режимы выравнивания сTextView .

CommonsWare
источник
5
После дальнейшего анализа вы можете сделать снимок для Android: gravity = "fill_hor Horizontal". Это называется «Увеличить горизонтальный размер объекта, если это необходимо, чтобы он полностью заполнил свой контейнер», но я не знаю, как они «увеличивают» текст.
CommonsWare
8
android: gravity = "fill_horizontal" тоже не работает. Похоже, Android не поддерживает оправдание в конце концов, да ладно :)
6
Нет, вы не можете установить свойство как гравитацию. Но, тем не менее, вы можете установить обоснование для своего текста, используя веб-просмотр вместо просмотра текста. Вы можете обратиться к seal.io/2010/12/only-way-how-to-align-text-in-block-in.html . (Украдено из stackoverflow.com/questions/5976627/… )
jcaruso
2
@CommonsWare Теперь какой-нибудь правильный способ оправдать текст?
Джон Р
1
Чувак, я живу с тяжелым веб-обзором, чтобы достичь этого, и поверьте мне, мой пользовательский интерфейс требует новых вещей, которые еще не добавлены в API, потому что это чертовски медленно для таких компонентов, как чат в виде списка.
nobalG
156

Ответ @CommonsWare правильный. Android 8.0+ поддерживает «Полное обоснование» (или просто «Обоснование», как это иногда называют неоднозначно).

Android также поддерживает «выравнивание текста по левому / правому краю». См. Статью об оправдании в Википедии . Многие люди считают, что концепция «выравнивания» включает в себя полное выравнивание, а также выравнивание текста влево / вправо, что они и ищут, когда хотят выполнить выравнивание текста влево / вправо. Этот ответ объясняет, как добиться выравнивания текста влево / вправо.

Можно добиться выравнивания текста по левому / правому краю (в отличие от полного выравнивания, о чем вопрос). Для демонстрации я буду использовать базовую форму с двумя столбцами (метки в левом столбце и текстовые поля в правом столбце) в качестве примера. В этом примере текст в метках в левом столбце будет выровнен по правому краю, поэтому они будут отображаться вровень с текстовыми полями в правом столбце.

В макете XML вы можете заставить сами элементы TextView (левый столбец) выравниваться вправо, добавив следующий атрибут во все TextViews:

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

Однако если текст переносится на несколько строк, текст все равно будет выровнен по левому краю внутри TextView. При добавлении следующего атрибута фактический текст выравнивается по правому краю (неровно по левому краю) внутри TextView:

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

Таким образом, атрибут gravity определяет, как выровнять текст внутри TextView layout_gravity указывает, как выровнять / расположить сам элемент TextView.

plainjimbo
источник
12
Если я правильно понимаю, и учитывая результаты тестирования, все это делает выравнивание текста влево или вправо. Это не оправдывает текст, не так ли?
Пол Ламмерцма
14
Отлично. Просто чтобы добавить, если вы хотите, чтобы центр оправдания, вы можете сделать android:layout_gravity="center_horizontal|center" android:gravity="center".
Луис А. Флорит
определенно работает для моего случая на inputtext и textview для арабского языка справа налево ввода и отображения
shareef
1
Это просто выравнивание, а не оправдание. Прочитайте эту ссылку в Википедии внимательно. Разница между различными типами обоснования влияет только на последнюю строку абзаца. Не существует левого / правого / центрального оправдания для абзацев, которые имеют только одну строку.
Кару
тогда зачем даже отвечать здесь, если речь не justify
идет
136

Для выравнивания текста в Android я использовал 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");

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

Я пока не могу загрузить изображения, чтобы доказать это, но "это работает для меня".

Конрад Новицки
источник
3
Хорошее решение здесь. FWIW вам не нужно большинство дополнительных HTML. Достаточно тега body с выравниванием текста.
gnac
5
Это хорошо работает. Обратите внимание, что вы можете сделать фон прозрачным, следуя view.loadData()с view.setBackgroundColor("#00000000").
Пол Ламмерцма
Однако мне не удалось заставить его загрузить собственный шрифт / шрифт. Я попробовал это и это предложение, без какой-либо удачи.
Пол Ламмерцма
2
Как я уже упоминал в этих темах, я нашел решение: если вы создаете файл HTML и помещаете его в ресурсы, загрузка его с помощью view.loadUrl()работает, тогда как view.loadData()нет. Я понятия не имею, почему последний не делает.
Пол Ламмерцма
1
@PaulLammertsma, setBackgroundColor (0x00000000) скорее будет правильным форматом для установки прозрачного фона.
Ричи
100

ОБНОВЛЕНО

Для этого мы создали простой класс. В настоящее время есть два метода для достижения того, что вы ищете. Оба не требуют веб-просмотра и поддерживает поддержку .

БИБЛИОТЕКА : https://github.com/bluejamesbond/TextJustify-Android

ПОДДЕРЖКА : Android 2.0 до 5.X

НАСТРОИТЬ

// Please visit Github for latest setup instructions.

СКРИНШОТ

Comparison.png

Мэтью Курьян
источник
Это действительно помогает, но, используя его, мои TextViews не сохраняют оригинальный формат, я ссылаюсь: поля, стиль текста, и я думаю, что размер текста тоже, Plese, продолжайте работать в нем, должен быть действительно большим подспорьем
Леонардо Сапуй
Ну, я не могу установить эти классы. у одного из них не было названия пакета, у другого - желтая ошибка. На самом деле я не могу доверять.
Мехмет
Хорошая библиотека, но я до сих пор не знаю, как добавить форматирование в Text с помощью этой библиотеки.
Семантик
4
Спасибо за эту замечательную общую библиотеку, но она не может поддерживать персидский или арабский текст. Когда я устанавливаю направление, мое слово рисует от последнего до начала, а не от начала до последнего. Я имею в виду это: мое Слово это: "سلام" и его ничья, как это: "مالس". (если вы не понимаете персидский, посмотрите этот пример: позвольте мне «1234» -> «4321»)
Наруто Узумаки
1
Основанный на scrollView ... Хорошее решение, однако, не может найти еще какой-либо ответ, который делает его возможным с textview. :(
superUser
89

TextViewв Android Oпредлагает полное оправдание (новое типографское выравнивание) себя.

Вам просто нужно сделать это:

Котлин

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

Ява

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

по умолчанию JUSTIFICATION_MODE_NONE.

Джайдипсин Зала
источник
3
Будем надеяться, что он будет перенесен обратно в библиотеку поддержки, затем O :)
Stefan Haustein
2
Пожалуйста, добавьте библиотеку здесь!
Кунал Дхарайя
4
как оправдать использование XML?
Викаш Параджули
14
Вы можете использовать Android: justificationMode = "inter_word" в XML.
Кристиан Д.
5
API 26 требуется для Android: justificationMode.
Бинк
42

Вы можете использовать проект JustifiedTextView for Android в github. это пользовательский вид, имитирующий оправданный текст для вас. Он поддерживает Android 2.0+ и справа налево языки. введите описание изображения здесь

Саид Заринфам
источник
это не поддерживает spannable строку
MSepehr
Как мы можем добавить наш собственный текст?
Каран
Пожалуйста, смотрите образец на GitHub.
Саид Заринфам
Привет Saeed, tnx за вашу помощь, есть ли способ поддержать расширяемые текстовые представления ?!
Хамид Реза
@SaeedZarinfam Я пытался использовать «JustifiedTextView для Android», но у меня возникла ошибка в теге xml ir.noghteh.JustifiedTextView. Помогите мне, пожалуйста, по этому вопросу stackoverflow.com/questions/37911376/…
Jumong
30

Я пишу базу виджетов на родном textview, чтобы сделать это.

GitHub

Фрэнк Ченг
источник
Я бы порекомендовал этот, главным образом потому, что он основан на оригинальном текстовом представлении официального Android SDK, который, по моему личному мнению, намного легче, чем метод веб-просмотра, который многие публикуют по этой общей теме. Если вы создаете приложение, которое требует разумного использования памяти, например, с использованием объектов списка, вы можете рассмотреть возможность использования чего-то подобного. Ï уже опробовать, и работает как положено. Если вы, люди, знаете другого лучше, как этот 1, пожалуйста, поделитесь своим опытом со мной.
superUser
Хорошая работа, кстати. Что я искал
superUser
5
не поддерживает языки RTL, такие как персидский
стрельба в дыре
1
@Frank Cheng Очень Полезная Библиотека. Я получаю много пробелов в конце абзаца. Как я могу это исправить?
iSrinivasan27
1
работал для меня, но последняя строка textview была обрезана. Я должен был продолжать добавлять 5 для просмотра текста.
TharakaNirmana
23

Я нашел способ решить эту проблему, но это может быть не очень благодати, но эффект не плохой.

Его принцип заключается в замене пробелов каждой строки на ImageSpan фиксированной ширины (цвет прозрачный).

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

Я положил код на GitHub: https://github.com/twiceyuan/TextJustification

Обзор:

обзор

twiceYuan
источник
1
Не работает в предварительном просмотре XML, но отлично работает с реальным устройством :)
pgreze
15

XML-макет: объявите WebView вместо TextView

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

Java-код: установить текстовые данные в 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");

Это может решить вашу проблему. Это полностью сработало для меня.


источник
9

Вот как я это сделал, я думаю, самый элегантный способ, которым я мог. С этим решением единственные вещи, которые вам нужно сделать в ваших макетах:

  • добавить дополнительную xmlnsдекларацию
  • изменить TextViewисходное текстовое пространство имен с Android на новое пространство имен
  • заменить ваши TextViewсx.y.z.JustifiedTextView

Вот код Отлично работает на моих телефонах (Galaxy Nexus Android 4.0.2, Galaxy Teos Android 2.1). Не стесняйтесь, конечно, заменить имя моего пакета на ваше.

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

Нам нужно настроить рендеринг на программное обеспечение, чтобы получить прозрачный фон на Android 3+. Отсюда и попытка поймать старые версии Android.

Надеюсь это поможет!

PS: пожалуйста, помните, что было бы полезно добавить это к вашей активности на Android 3+, чтобы получить ожидаемое поведение:
android:hardwareAccelerated="false"

Бенуа Даффез
источник
Это решение на основе webView. Любой из них нашел еще текстовое представление, учитывая, что textview легче, чем webview и scrollview.
superUser
9

Очень просто Мы можем сделать это в файле XML

<TextView 
android:justificationMode="inter_word"
/>
Махиндра Неупане
источник
6

Я пишу свой собственный класс, чтобы решить эту проблему, Вот только вы должны вызвать статическую функцию justify, которая принимает два аргумента

  1. Текст Просмотр объекта
  2. Ширина контента (общая ширина вашего текстового представления)

//Основная деятельность

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>
Фавад Бадар
источник
пожалуйста, завершите этот пример хотя бы для того, чтобы \ n или System.getProperty ("line.separator") уважали :)
ceph3us
5

FILL_HORIZONTALэквивалентно CENTER_HORIZONTAL. Вы можете увидеть этот фрагмент кода в исходном коде textview:

case Gravity.CENTER_HORIZONTAL:
case Gravity.FILL_HORIZONTAL:
    return (mLayout.getLineWidth(0) - ((mRight - mLeft) -
            getCompoundPaddingLeft() - getCompoundPaddingRight())) /
            getHorizontalFadingEdgeLength();
jiashie
источник
4

Существует CustomView для этой проблемы, это настраиваемое текстовое представление поддерживает Justered Text View.

Взгляните на это: 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;
                }
        }
}

Добавьте вышеупомянутый класс в вашу папку src и используйте этот пример кода, чтобы добавить в свой макет:

JustifiedTextView jtv= new JustifiedTextView(getApplicationContext(), "Lorem ipsum dolor sit amet... ");
LinearLayout place = (LinearLayout) findViewById(R.id.book_profile_content);
place.addView(jtv);
Merter
источник
4

смотрите здесь в GitHub

Просто импортируйте два файла "TextJustifyUtils.java" и "TextViewEx.java" в ваш проект.

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

а также

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

Теперь, если вы используете обычный textView, как:

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

Просто использовать

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

Определите переменную и установите justify на true,

TextViewEx changed = (TextViewEx) findViewById(R.id.changed);
changed.setText(getResources().getString(R.string.lorum_ipsum),true);
Mr_Moradi
источник
жирный текст не работает, пожалуйста, помогите, если у вас есть какие-либо исправления для этого?
Правиенб
4

Android Text Justify For TextView XML

Просто Android-текст оправдать использование в XML. Вы можете просто реализовать в виджете textview.

 <TextView
    android:justificationMode="inter_word"
/>

По умолчанию android:justificationMode="none"

Самед Талукдер
источник
2

Я думаю, что есть два варианта:

  • Используйте что-то вроде Pango, который специализируется на этом через NDK, и визуализируйте текст на OpenGL или другой поверхности.

  • Используйте Paint.measureText () и друзей, чтобы получить длины слов и выложить их вручную на холсте в пользовательском представлении.

Мэтью Уиллис
источник
2

На Android, чтобы выровнять текст по левому краю и не иметь усечения цвета фона, попробуйте это, это сработало для меня, производя согласованные результаты на Android, FF, т.е. и Chrome, но вы должны измерить пространство, оставшееся между текстом при расчете заполнения.

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

Хак это то, padding-right:1000px;что толкает текст в крайнее левое положение.

Любая попытка влево или выровнять код в CSS или HTML приводит к фону, который имеет только половинную ширину.

Робин Глас
источник
1

Android пока не поддерживает полное обоснование. Мы можем использовать Webview и обосновать HTML вместо использования textview. Это работает так хорошо. Если вы, ребята, не ясно, не стесняйтесь спрашивать меня :)

kypiseth
источник
Это можно сделать. Но мы можем установить фон WebView transparent. У меня есть фоновое изображение.
Мистер Индия
Я не думаю, что это может быть памятью.
superUser
1

Попробуйте это решение по ссылке ниже, просто создайте этот класс в папке проекта и используйте его. Он отлично работает для меня :)

Обоснуйте текст в приложении для Android, используя WebView, но представьте интерфейс, подобный TextView?

Yoganand.N
источник
Пожалуйста, дайте некоторые детали.
Седа Зунаира
1

Обоснование содержимого TextView. Его простые парни просто используют android: justificationMode = "inter_word" в вашем теге 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

Попробуйте использовать < RelativeLayout >(убедитесь, что fill_parent), затем просто добавьте android:layout_alignParentLeft="true"и

android:layout_alignParentRight="true" к элементам, которые вы хотели бы снаружи слева и справа.

БЛАМ, оправдано!

esharp
источник
отличный пример здесь: stackoverflow.com/questions/2099249/…
esharp
3
Все еще не то, что он ищет. См. Обоснование в Википедии: en.wikipedia.org/wiki/Justification_(typesetting)
Кевин Коппок
Это не оправдание
Араш Хатами
-5

Вы должны установить

android:layout_height="wrap_content"

а также

android:layout_centerInParent="true"
Lukas
источник
11
Это центрирует текст, который не является полным оправданием
Janusz
-12

Это не совсем оправдывает ваш текст, но

android:gravity="center_horizontal"

это лучший выбор, который у вас есть.

Вольфене
источник
9
Нет, это центрирует текст. Это не оправдывает это. Цитируя Википедию : «В выровненном тексте пробелы между словами и, в меньшей степени, между глифами или буквами (кернинг) растягиваются или иногда сжимаются, чтобы выровнять текст по левому и правому краям».
CommonsWare
текст не соответствует вашему коду, а центрирует текст по горизонтали
Маттео