안드로이드 텍스트보기 텍스트를 정당화


395

당신은 어떻게 텍스트를 얻을 TextView왼쪽과 오른쪽의 텍스트 플러시를 사용하여 정당화 합니까?

나는 가능한 해결책을 찾았 여기 지만 (이 등, center_vertical 수직 중심을 변경하는 경우에도) 작업을하지 않습니다.


@Jimbo 답변의 definetly에 대한 올바른 작동하고 내 경우 에 InputText]를 및 텍스트 뷰 왼쪽 입력 및 디스플레이 오른쪽에서 아랍어 언어에 대한 것은 있지만, 입력 텍스트 나 또한 중력 = "오른쪽"추가했다
— 샤리프를

답변:


239

나는 안드로이드가 완전한 정당성을 지원한다고 믿지 않는다.

2018-01-01 업데이트 : Android 8.0 이상은으로 자리 맞추기 모드를TextView 지원합니다 .


5
추가 분석 후 android : gravity = "fill_horizontal"에 샷을 줄 수 있습니다. 그것은 "필요한 경우 개체의 가로 크기를 늘려서 컨테이너를 완전히 채 웁니다"라고 설명하지만 텍스트가 어떻게 "성장"하는지 모르겠습니다.
— CommonsWare

8
android : gravity = "fill_horizontal"도 작동하지 않았습니다. 안드로이드가 결국 정당화를 지원하지 않는 것 같습니다. :)

6
아니요, 중력과 같은 속성을 설정할 수 없습니다. 그러나 여전히 텍스트보기 대신 웹보기를 사용하여 텍스트에 대한 정당성을 설정할 수 있습니다. seal.io/2010/12/only-way-how-to-align-text-in-block-in.html을 참조하십시오 . ( stackoverflow.com/questions/5976627/… 에서 스톨 )
— jcaruso

2
@CommonsWare 이제 텍스트를 정당화하는 적절한 방법이 있습니까?
— John R

1
Man, 나는 이것을 달성하기 위해 무거운 webview와 함께 살고 있으며, UI는 아직 새로운 것들을 API에 추가하려고 울고 있다고 생각합니다.
— nobalG

156

@CommonsWare 답변이 정확합니다. Android 8.0 이상에서는 "완전 정렬"(또는 "모호하게 참조되기 때문에 간단히"정의 ")을 지원합니다.

Android는 "왼쪽 / 오른쪽 텍스트 플러시"도 지원합니다. 정당성 에 대한 위키 백과 기사를 참조하십시오구별 대한 . 많은 사람들은 왼쪽 / 오른쪽 텍스트 정렬뿐만 아니라 왼쪽 / 오른쪽 텍스트 정렬을 포함하기 위해 완전 정렬 및 왼쪽 / 오른쪽 텍스트 정렬을 포괄하는 '정리'개념을 고려합니다. 이 답변은 왼쪽 / 오른쪽 텍스트 정렬을 달성하는 방법을 설명합니다.

왼쪽 / 오른쪽 텍스트 정렬 플러시를 수행 할 수 있습니다 (질문과 관련하여 전체 정렬과 반대). 시연을 위해 기본 2 열 양식 (왼쪽 열의 레이블과 오른쪽 열의 텍스트 필드)을 예로 사용합니다. 이 예에서 왼쪽 열의 레이블에있는 텍스트는 오른쪽 정렬되어 오른쪽 열의 텍스트 필드와 같은 높이로 나타납니다.

XML 레이아웃에서는 모든 TextView 내에 다음 속성을 추가하여 TextView 요소 자체 (왼쪽 열)를 오른쪽에 맞출 수 있습니다.

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

그러나 텍스트가 여러 줄로 줄 바꿈되면 TextView 내부에서 텍스트가 왼쪽으로 정렬됩니다. 다음 속성을 추가하면 실제 텍스트가 텍스트 뷰 내에서 오른쪽 정렬 (왼쪽으로 정렬)됩니다.

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

따라서 gravity 속성은 TextView 안에 텍스트를 정렬하는 방법을 지정합니다. layout_gravity 는 TextView 요소 자체를 정렬 / 레이아웃하는 방법을 지정합니다.


12
내가 올바르게 이해하고 이것을 테스트 한 결과, 텍스트를 왼쪽 또는 오른쪽으로 정렬하면됩니다. 이것은 텍스트를 정당화하지 않습니까?
— Paul Lammertsma

14
우수한. 추가로, 센터 자리 맞추기를 원한다면 할 수 있습니다 android:layout_gravity="center_horizontal|center" android:gravity="center".
— Luis A. Florit

의 definetly에 내 경우 근무 InputText]를 및 텍스트 뷰 왼쪽 입력 및 디스플레이 오른쪽에서 아랍어 언어
— 샤리프

1
이것은 정당화가 아니라 정렬입니다. Wikipedia 링크를주의 깊게 읽으십시오. 다른 유형의 자리 맞추기의 차이점은 단락의 마지막 줄에만 영향을줍니다. 한 줄만있는 단락에 대해서는 왼쪽 / 오른쪽 / 중앙 정렬이 없습니다.
— Karu

그렇다면 왜 여기에 대답하지 않더라도 여기에 대답하십시오justify
— user924

136

안드로이드에서 텍스트를 정당화하기 위해 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
여기 좋은 해결책이 있습니다. 그러나 대부분의 추가 HTML이 필요하지 않습니다. 텍스트가 정렬 된 본문 태그로 충분합니다.
— gnac

5
이것은 잘 작동합니다. 당신이 따라 배경을 투명하게 만들 수 있습니다 view.loadData()로 view.setBackgroundColor("#00000000").
— Paul Lammertsma

그러나 사용자 정의 글꼴 / 서체를로드하는 데 성공하지 못했습니다. 나는 해봤 이 와 이 운이없는 제안을.
— Paul Lammertsma

2
그 스레드에서 언급했듯이 해결책을 찾았습니다 .HTML 파일을 만들어 자산에 배치하면 view.loadUrl()작품 을 통해로드 하지만 view.loadData()그렇지는 않습니다. 나는 왜 후자가 그렇지 않은지 전혀 모른다.
— Paul Lammertsma

1
@PaulLammertsma, setBackgroundColor (0x00000000)은 투명한 배경을 설정하기에 올바른 형식입니다.
— richey

100

업데이트

이를 위해 간단한 클래스를 만들었습니다. 현재 원하는 것을 달성하는 두 가지 방법이 있습니다. 둘 다 웹뷰 및 지원 SPANNABLES가 필요하지 않습니다 .

라이브러리 : https://github.com/bluejamesbond/TextJustify-Android

지원 : 안드로이드 2.0에서 5.X

설정

// Please visit Github for latest setup instructions.

스크린 샷

비교 .png


여백, 텍스트 스타일을, 그리고 그 텍스트 크기는 둘 다, Plese 그것에서 작업을 계속, 정말 큰 도움이 될하지한다고 생각 : 내 TextViews 원래의 형식을 유지하지 않습니다, 정말 도움이되지만를 사용하여, 나는 refeer
— 레오나르도 Sapuy

글쎄, 나는 그 수업을 만들 수 없습니다. 그중 하나는 패키지 이름이 없었고 다른 하나는 노란색 오류를 나타냅니다. 실제로 나는 믿을 수 없다.
— mehmet

좋은 라이브러리이지만 여전히이 라이브러리를 사용하여 텍스트에 서식을 추가하는 방법을 모르겠습니다.
— Semanticer

4
이 훌륭한 공유 라이브러리에 감사하지만 페르시아어 또는 아랍어 텍스트를 지원할 수 없습니다. 방향을 설정하면 시작에서 끝이 아닌 마지막에서 시작까지 단어가 그려집니다. 내 말은 : "سلام"그리고 다음과 같은 표현 : "مالس". (페르시아어를 이해하지 못하는 경우이 예를 참조하십시오 : "1234"-> "4321")
— Naruto Uzumaki

1
scrollView를 기반으로 ... 그러나 멋진 솔루션은 textview를 사용하여 가능한 대답을 찾지 못했습니다. :(
— superUser

88

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
pls는 여기에 라이브러리를 추가!
— Kunal Dharaiya

4
XML을 사용하여 정당화하는 방법?
— Vikash Parajuli

14
xml에서 android : justificationMode = "inter_word"를 사용할 수 있습니다.
— Christian D

5
android : justificationMode에는 API 26이 필요합니다.
— Bink

42

github에서 JustifiedTextView for Android 프로젝트를 사용할 수 있습니다 . 이것은 사용자에게 적합한 텍스트를 시뮬레이트하는 사용자 정의보기입니다. Android 2.0 이상 및 오른쪽에서 왼쪽 언어를 지원합니다. 여기에 이미지 설명을 입력하십시오


확장 가능한 문자열을 지원하지 않습니다
— MSepehr

우리는 어떻게 우리 자신의 텍스트를 추가 할 수 있습니까?
— Karan

github의 샘플을 참조하십시오.
— Saeed Zarinfam

안녕하십니까, 귀하의 도움을위한 tnx, 확장 가능한 텍스트 뷰를 지원할 수있는 방법이 있습니까?
— 하미드 레자

@SaeedZarinfam 나는 "안드로이드에 대한 JustifiedTextView"를 사용하려하지만 난 XML 태그 ir.noghteh.JustifiedTextView에 오류가 발생했습니다 것 U PLZ이 질문에 대한 도움말 나가에 stackoverflow.com/questions/37911376/...
— 주몽

30

네이티브 textview를 기반으로 위젯 기반을 작성합니다.

깃 허브


나는 이것이 안드로이드 공식 SDK의 원본 텍스트 뷰를 기반으로하기 때문에 이것을 추천했다. 내 개인적인 견해로는 많은 사람들 이이 공통 주제에 관해 게시하는 웹 뷰 기술보다 더 가볍다. 예를 들어 listview 객체를 사용하여 메모리가 현명한 앱을 빌드하는 경우 이와 같은 것을 사용하는 것이 좋습니다. Ï 모두 시도해보고 예상대로 작동합니다. 사람들 이이 1과 같은 다른 것을 더 잘 알고 있다면 나에게 경험을 공유 할 수 있습니다.
— 수퍼 유저

잘 했어. 내가 찾던 것.
— 수퍼 유저

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

개요 :

개요


1
XML 미리보기에서는 작동하지 않지만 실제 장치에서는 훌륭하게 작동 :)
— pgreze

15

XML 레이아웃 : TextView 대신 WebView 선언

<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새 네임 스페이스에 안드로이드에서의 소스 텍스트 네임 스페이스를
  • 당신 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에서는 시험 사용이 가능합니다.

도움이 되었기를 바랍니다!

추신 : 예상되는 동작을 얻으려면 Android 3 이상에서 전체 활동에 이것을 추가하는 것이 유용 할 수 있습니다.
android:hardwareAccelerated="false"


이것은 webView 기반 솔루션입니다. textview는 webview 및 scrollview보다 가볍다는 점을 고려하여 textview 기반을 찾았습니다.
— 수퍼 유저



6

이 문제를 해결하기 위해 내 자신의 클래스를 작성합니다. 여기에는 두 가지 인수를 취하는 정적 정당화 함수를 호출해야합니다.

  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>

청원 : 또는, System.getProperty ( "line.separator")에 존중 "n \"를 적어도이 예를 완료
— 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가 있으며이 사용자 정의 텍스트보기는 Justified 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);

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

변수를 정의하고 정당성을 true로 설정하십시오.

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

굵은 글씨가 작동하지 않습니다. 해결 방법이 있으면 도와주세요.
— praveenb

4

TextView XML에 대한 Android 텍스트 정당화

XML을 사용하여 단순히 안드로이드 텍스트를 정당화하십시오. textview 위젯에서 간단히 구현할 수 있습니다.

 <TextView
    android:justificationMode="inter_word"
/>

기본은 android:justificationMode="none"


2

두 가지 옵션이 있다고 생각합니다.

  • NDK를 통해이를 전문화하고 텍스트를 OpenGL 또는 다른 표면에 렌더링하는 Pango와 같은 것을 사용하십시오.

  • Paint.measureText () 및 friends를 사용 하여 단어 길이를 가져 와서 사용자 정의보기에서 수동으로 Canvas에 배치하십시오.


2

안드로이드에서 텍스트를 왼쪽 정렬하고 배경색을 자르지 않으려면 이것을 시도해보십시오. 안드로이드, ff, 즉 크롬에서 일관된 결과를 생성하지만 텍스트 사이에 남아있는 공간을 측정해야합니다. 패딩을 계산할 때.

<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

안드로이드는 아직 완전한 정당성을 지원하지 않습니다. textview를 사용하는 대신 Webview를 사용하고 HTML을 정당화 할 수 있습니다. 너무 잘 작동합니다. 당신이 명확하지 않으면, 나에게 물어 주시기 바랍니다 :)


할 수 있습니다. 그러나의 배경을 설정할 수 있습니까 WebView transparent? 배경 이미지가 있습니다.
— Mr.India

나는 이것이 현명한 메모리라고 생각하지 않습니다.
— 수퍼 유저


1

TextView 컨텐츠 정당성 : TextView 태그 내에서 android : justificationMode = "inter_word"를 사용하는 것은 쉬운 일입니다.

 <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" 왼쪽 및 오른쪽 외부에서 원하는 요소에.

BLAM, 정당화!


여기에 좋은 예가 있습니다 : stackoverflow.com/questions/2099249/…
— esharp

3
아직도 그가 찾고있는 것이 아닙니다. Wikipedia의 정당화 참조 : en.wikipedia.org/wiki/Justification_(typesetting)
— Kevin Coppock

그것은 정당화 아니다
— 아라 쉬 하타미

-5

당신은 설정해야

android:layout_height="wrap_content"

과

android:layout_centerInParent="true"

11
이것은 완전한 정당성이 아닌 텍스트를 중심에 둔다
— Janusz

-12

이것은 실제로 텍스트를 정당화하지는 않지만

android:gravity="center_horizontal"

당신이 가진 최고의 선택입니다.


9
아니요, 텍스트 중심입니다. 그것을 정당화하지는 않습니다. 인용 위키피디아 : "맞춤 텍스트에서, 텍스트 사이의 간격이 덜 그리거나 글리프 또는 문자 (커닝) 사이의 간격이 늘어나거나 때때로 압축되어 텍스트가 왼쪽과 오른쪽 여백에 정렬되도록합니다."
— CommonsWare

텍스트가 코드에 의해 정당화되는 것이 아니라 텍스트의 중심이 수평입니다
— Matteo
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.