Android TextView Вирівнювання тексту


395

Як ви вважаєте TextViewвиправданим текст а (з флеш-тексту в лівій і правій частині)?

Я знайшов можливе рішення тут , але він не працює (навіть при зміні вертикального-центру в center_vertical і т.д.).


@Jimbo відповідь правильно, я точно працюю в моєму випадку на введеннятексту та перегляду тексту для арабської мови з правого на лівого вводу та відображення, але для введення тексту мені довелося додати також gravity = "right"
shareef

ви можете використовувати github.com/pouriaHemmati/JustifiedTextView
Pouria Hemati

Відповіді:


239

Я не вірю, що Android підтримує повне виправдання.

ОНОВЛЕННЯ 2018-01-01 : Android 8.0+ підтримує режими виправдання за допомогоюTextView .


5
Після подальшого аналізу ви зможете дати андроїд: gravity = "fill_horizontal" знімок. Це описується як "Збільште горизонтальний розмір об'єкта, якщо це потрібно, щоб він повністю заповнив його контейнер", але я не знаю, як вони "ростуть" текст.
CommonsWare

8
android: gravity = "fill_horizontal" також не працював. Схоже, андроїд врешті не підтримує виправдання, ну добре :)

6
Ні, ви не можете встановити властивість, як гравітація. Але все ж ви можете встановити виправдання тексту, скориставшись веб-переглядом замість перегляду тексту. Ви можете посилатися на печатку.io/2010/12/only-way-how- to- align-text-in-block-in.html . (Вкрав з stackoverflow.com/questions/5976627 / ... )
jcaruso

2
@CommonsWare Тепер будь-який правильний спосіб виправдати текст?
Джон Р

1
Людина, я живу з важким веб-переглядом, щоб досягти цього, і повірте, мій інтерфейс плаче за новинками, які ще потрібно додати до API, тому що це чортово повільно для таких компонентів, як чат у listview.
nobalG

156

Відповідь @CommonsWare правильна. Android 8.0+ підтримує "Повне обгрунтування" (або просто "Обгрунтування", як це іноді неоднозначно посилається).

Android також підтримує "Вирівнювання тексту вліво / вправо". Дивіться статтю у Вікіпедії щодо Обґрунтування розрізнення. Багато людей вважають, що поняття «виправдання» охоплює повне виправдання, а також вирівнювання тексту вліво / вправо. Це те, що вони шукають, коли хочуть вирівняти лівий / правий текст. Ця відповідь пояснює, як досягти вирівнювання тексту зліва / праворуч.

Можна домогтися вирівнювання тексту вліво / вправо (на відміну від повного обґрунтування, про яке задається питання). Для демонстрації я буду використовувати приклад основної форми з двома стовпцями (мітки в лівому стовпчику та текстові поля в правій колонці). У цьому прикладі текст у мітках у лівій колонці буде вирівнюватися правою стороною, так що вони виглядають наближеними до їх текстових полів у правій колонці.

У макеті XML ви можете отримати самі елементи TextView (лівий стовпець) для вирівнювання праворуч, додавши наступний атрибут усередині TextView:

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

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

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

Таким чином, атрибут gravity визначає, як вирівняти текст всередині TextView layout_gravity, визначає, як вирівняти / розташувати сам елемент TextView.


12
Якщо я правильно розумію, і з огляду на результати тестування цього, все це - це вирівнювання тексту вліво або вправо. Це не виправдовує текст, чи не так?
Пол Ламмертсма

14
Відмінно. Просто додати, якщо ви хочете виправдати центр, ви можете зробити android:layout_gravity="center_horizontal|center" android:gravity="center".
Луїс А. Флорит

напевно працює в моєму випадку над введеннямтексту та перегляду тексту для арабської мови справа наліво введення та відображення
shareef

1
Це просто вирівнювання, а не виправдання. Прочитайте уважно посилання Вікіпедії. Різниця між різними типами обґрунтування впливає лише на останній рядок абзацу. Немає лівого / правого / центрального обґрунтування для абзаців, у яких є лише один рядок.
Кару

Тоді навіщо навіть відповідати на це тут, якщо мова не йде проjustify
user924

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. Тега тіла з вирівнюванням тексту достатньо.
гнак

5
Це добре працює. Зверніть увагу , що ви можете зробити фон прозорим, слідуючи view.loadData()з view.setBackgroundColor("#00000000").
Пол Ламмертсма

Однак я не мав успіху в завантаженні користувальницького шрифту / шрифту. Я спробував це і цю пропозицію, без жодної удачі.
Пол Ламмертсма

2
Як я вже згадував у цих потоках, я знайшов дозвіл: якщо створити HTML-файл і розмістити його в активах, завантажуючи його через view.loadUrl()твори, тоді як view.loadData()ні. Я не маю поняття, чому останній цього не робить.
Пол Ламмертсма

1
@PaulLammertsma, setBackgroundColor (0x00000000) швидше буде правильним форматом для встановлення прозорого фону.
richey

100

ОНОВЛЕНО

Ми створили для цього простий клас. В даний час існує два способи досягнення того, що ви шукаєте. І те, і інше вимагає НЕ ОГЛЯДУВАННЯ WEBVIEW та ПІДТРИМКИ .

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

ПІДТРИМКИ : Android 2.0 до 5.X

НАСТРОЙКА

// Please visit Github for latest setup instructions.

ЕКРАН

Порівняння.png


Це справді допомога, але використовуючи його, мої TextViews не зберігають оригінальний формат, я реферую: поля, стиль тексту, і я вважаю, що розмір тексту ні, Плесе продовжуйте працювати в ньому, повинен бути справді чудовою допомогою
Леонардо Сапуй

Ну я не можу встановити ці заняття. один з них не мав жодного імені пакета, інший дає жовту помилку. Власне, я не можу довіряти.
mehmet

Хороша вкладка, але я досі не знаю, як додати будь-яке форматування до тексту за допомогою цієї бібліотеки.
Semanticer

4
Дякуємо за цю велику спільну бібліотеку, але вона не може підтримувати персидський або арабський текст. Коли я задаю напрямок, моє слово малює від останнього до початку, а не від початку до останнього. Я маю на увазі це: моє Слово: "سلام", і його малюнок виглядає так: "مالس". (якщо ви не розумієте персидський, дивіться цей приклад: дозвольте мені "1234" -> "4321")
Наруто Узумакі,

1
На основі scrollView ... Хороше рішення, проте не можу знайти жодної відповіді, яка робить його можливим при перегляді тексту. :(
superUser

88

TextViewв Android Oпропозиціях повного обгрунтування (нова розстановка друкарською) сам по собі.

Вам просто потрібно зробити це:

Котлін

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

Java

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

за замовчуванням є JUSTIFICATION_MODE_NONE.


3
Будемо сподіватися, що він повернеться назад до бібліотеки підтримки O :)
Stefan Haustein

2
pls додати сюди бібліотеку !!
Kunal Dharaiya

4
як виправдати використання XML?
Вікаш Параджулі

14
Ви можете використовувати android: justificationMode = "inter_word" у xml.
Крістіан Д

5
API 26 необхідний для android: justificationMode.
Бінк

42

Ви можете використовувати JustifiedTextView для проекту Android в github. це спеціальний вигляд, який імітує виправданий текст для вас. Він підтримує Android 2.0+ та мови праворуч наліво. введіть тут опис зображення


він не підтримує розтягувану рядок
MSepehr

як ми можемо додати власний текст?
Каран

Будь ласка, дивіться зразок на github.
Саїд Зарінфам

привіт Saeed, tnx для вашої допомоги, чи є можливість підтримати обґрунтовані перегляди тексту ?!
Хамід Реза

@SaeedZarinfam Я спробував використати "JustifiedTextView для Android", але у мене з'явилася помилка в тезі xml ir.noghteh.JustifiedTextView, що я можу допомогти мені у цьому питанні stackoverflow.com/questions/37911376/…
Jumong

30

Я пишу базу віджетів на рідному текстовому перегляді, щоб це зробити.

github


Я б порекомендував це, здебільшого тому, що його базується на оригінальному текстовому огляді з офіційного sdk для android, який, на мою особисту думку, є набагато легшим за техніку веб-перегляду, яку багато людей публікують щодо цієї загальної теми. Якщо ви створюєте додаток, який потребує пам'яті, використовуючи, наприклад, об'єкти списку перегляду, ви можете розглянути щось подібне. Ï все вже спробуйте, і працює, як очікувалося. Якщо ви знаєте ще одного кращого, як цей 1, будь ласка, поділіться своїм досвідом зі мною.
superUser

Гарна робота BTW. Що я шукав.
superUser

5
не підтримує мови RTL, як перська
вогонь у норі

1
@Frank Cheng Дуже корисна бібліотека. У кінці абзацу я отримую багато пробілів. Як я можу це виправити?
iSrinivasan27

1
працював на мене, але останній рядок перегляду тексту перервався. Мені довелося тримати забивання 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

Огляд:

Огляд


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 на новий простір імен
  • замініть свій TextViews на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"


Це рішення, засноване на веб-перегляді. Будь-який знайшов ще заснований на перегляді текст, вважаючи, що перегляд тексту легший, ніж веб-перегляд та прокрутка.
superUser



6

Я пишу свій клас, щоб вирішити цю проблему. Ось тільки Ви повинні викликати функцію статичного виправдання, яка бере два аргументи

  1. Об'єкт перегляду тексту
  2. Ширина вмісту (загальна ширина перегляду тексту)

// MainActivity

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

4

Для цієї проблеми існує CustomView. Цей власний перегляд тексту підтримує вигляд обґрунтованого тексту.

Лут у цьому: 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);

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" />

Визначте змінну і встановіть виправдання для істинного,

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

жирний текст не працює, будь ласка, допоможіть, якщо у вас є якісь виправлення?
praveenb

4

Вирівнювання тексту Android для TextView XML

Просто андроїд текст-виправдання, використовуючи в 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 поки не підтримує повного виправдання. Ми можемо використовувати веб-перегляд та виправдовувати HTML замість текстового перегляду. Це так чудово працює. Якщо вам не зрозуміло, сміливо запитайте мене :)


Це можна зробити. Але чи можемо ми встановити тло WebView transparent. У мене фонове зображення
МістерІндія

Я не думаю, що це може бути пам'яттю.
superUser

1

Спробуйте це рішення за посиланням нижче, просто створіть цей клас у папці проекту та використовуйте його. це добре працює для мене :)

Обґрунтуйте текст у програмі Android за допомогою WebView, але представляючи інтерфейс, подібний TextView?


Будь ласка, дайте детальну інформацію.
Саєда Зунайра

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 >(обов'язково заповнити_parent), а потім просто додайте android:layout_alignParentLeft="true"та

android:layout_alignParentRight="true" до елементів, які ви хотіли б із зовнішньої сторони Ліворуч і Право.

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


Прекрасний приклад тут: stackoverflow.com/questions/2099249 / ...
esharp

3
Ще не те, що він шукає. Дивіться обґрунтування у Вікіпедії: en.wikipedia.org/wiki/Justification_(typesetting)
Кевін Коппок

Це не виправдання
Араш Хатамі

-5

Ви повинні встановити

android:layout_height="wrap_content"

і

android:layout_centerInParent="true"

11
У центрі уваги текст не є повним обґрунтуванням
Януш

-12

Це насправді не виправдовує ваш текст, але

android:gravity="center_horizontal"

- найкращий вибір у вас.


9
Ні, це центр тексту. Це не виправдовує. Цитуючи Вікіпедію : "У виправданому тексті пробіли між словами і, меншою мірою, між гліфами чи літерами (кернінг) розтягуються або іноді стискаються для того, щоб текст вирівнювався як з лівого, так і з правого поля".
CommonsWare

текст не є виправданим вашим кодом, але по центру горизонтальний текст
Matteo
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.