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


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.