Android 텍스트 보기 텍스트 정당화
당신은 어떻게 문자를 얻습니까?TextView
정당화될 것인가(왼쪽과 오른쪽에 텍스트 플러시 포함)?
여기서 가능한 해결책을 찾았지만 (수직-중심을 center_vertical 등으로 변경해도) 작동하지 않습니다.
나는 안드로이드가 완전한 정당성을 지지한다고 생각하지 않습니다.
업데이트 2018-01-01: Android 8.0+는 에서 정당화 모드를 지원합니다.
TextView
Android O에서는 완전한 정당성(새로운 타이포그래피 정렬) 자체를 제공합니다.
은 이것만: " 작업수됩니다면이하행만됩다니▁you면이▁this:"
코틀린
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);
}
XML
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:justificationMode="inter_word" />
기본값은 입니다.JUSTIFICATION_MODE_NONE
(none
xml)로 표시됩니다.
@CommonsWare의 대답은 정확합니다.Android 8.0+는 "전체 정당성"(또는 때때로 모호하게 언급되는 "정당성")을 지원합니다.
Android는 "왼쪽/오른쪽 텍스트 플러시 정렬"도 지원합니다.그 구별은 정당성에 관한 위키백과 기사를 참조하십시오.많은 사람들이 왼쪽/오른쪽 텍스트 정렬뿐만 아니라 전체 정렬을 포함하는 '정당화' 개념을 고려하는데, 이는 그들이 왼쪽/오른쪽 텍스트 정렬을 원할 때 검색하게 되는 것입니다.이 답변은 왼쪽/오른쪽 텍스트 정렬을 수행하는 방법을 설명합니다.
전체 맞춤과 반대로 질문과 같이 왼쪽/오른쪽 텍스트 정렬 플러시를 수행할 수 있습니다.예를 들어 기본적인 2열 양식(왼쪽 열의 레이블과 오른쪽 열의 텍스트 필드)을 사용합니다.이 예에서는 왼쪽 열의 레이블 텍스트가 오른쪽 정렬되어 오른쪽 열의 텍스트 필드에 대해 평평하게 표시됩니다.
XML 레이아웃에서 모든 TextView 내부에 다음 특성을 추가하여 TextView 요소 자체(왼쪽 열)를 오른쪽으로 정렬할 수 있습니다.
<TextView
...
android:layout_gravity="center_vertical|end">
...
</TextView>
그러나 텍스트가 여러 줄로 감겨도 텍스트 보기 내에서 텍스트가 수평으로 왼쪽으로 정렬됩니다.다음 특성을 추가하면 TextView 내에서 실제 텍스트가 오른쪽 정렬(왼쪽 래깅)됩니다.
<TextView
...
android:gravity="end">
...
</TextView>
따라서 중력 속성은 TextView layout_gravity 내에서 텍스트를 정렬하는 방법을 지정합니다. 중력은 TextView 요소 자체를 정렬/레이아웃하는 방법을 지정합니다.
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>
나는 아직 그것을 증명하기 위해 이미지를 업로드할 수 없지만 "그것은 나에게 효과가 있습니다."
업데이트됨
이를 위한 간단한 클래스를 만들었습니다.현재 두 가지 방법으로 원하는 것을 달성할 수 있습니다.둘 다 웹 뷰가 필요하지 않으며 스패너블을 지원합니다.
라이브러리: https://github.com/bluejamesbond/TextJustify-Android
지원:Android 2.0에서 5.x
세우다
// Please visit Github for latest setup instructions.
스크린샷
정당화됨을 사용할 수 있습니다.Github에서 Android 프로젝트용 TextView입니다.이것은 사용자를 위해 정당화된 텍스트를 시뮬레이션하는 사용자 정의 보기입니다.Android 2.0+ 및 오른쪽에서 왼쪽 언어를 지원합니다.
나는 그것을 하기 위해 네이티브 텍스트 뷰를 기반으로 위젯을 작성합니다.
나는 이 문제를 해결할 방법을 찾았지만, 이것은 그다지 은혜가 아닐 수도 있지만, 그 효과는 나쁘지 않습니다.
각 라인의 공간을 고정 너비 이미지 범위(색상 투명)로 바꾸는 것이 원칙입니다.
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
개요:
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");
이것으로 문제가 해결될 수 있습니다.제게 완전히 효과가 있었습니다.
매우 간단합니다. xml 파일에서 이 작업을 수행할 수 있습니다.
<TextView
android:justificationMode="inter_word"
/>
제가 한 방법은 이렇습니다. 제가 할 수 있는 가장 우아한 방법이라고 생각합니다.이 솔루션을 사용하면 레이아웃에서 수행해야 하는 작업은 다음과 같습니다.
- 덧을더다를 합니다.
xmlns
- ▁your▁change기를
TextView
Android에서 새 네임스페이스로 소스 텍스트 네임스페이스 - 합니다.
TextView
에 로으.x.y.z.JustifiedTextView
여기 코드가 있습니다.내 전화기에서 완벽하게 작동합니다(갤럭시 넥서스 안드로이드 4.0.2, 갤럭시 테오스 안드로이드 2.1).물론 저의 패키지 이름을 당신의 것으로 바꿔도 좋습니다.
/vmdk/dk_textview.vmdk:
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/sys/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"
아직 정확한 텍스트를 완성하지는 않았지만, 이제 다음을 사용하여 줄 길이의 균형을 맞출 수 있습니다.android:breakStrategy="balanced"
API 23 이후로
http://developer.android.com/reference/android/widget/TextView.html#attr_android:breakStrategy
나는 이 문제를 해결하기 위해 나만의 수업을 씁니다. 여기서 당신은 두 개의 인수를 갖는 정적 정당화 함수를 호출하면 됩니다.
- 텍스트 보기 개체
- 내용 너비(텍스트 보기의 전체 너비)
//주 활동
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;
}
}
//텍스트 맞춤 클래스
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>
FILL_HORIZONTAL
와 동등합니다.CENTER_HORIZONTAL
텍스트 뷰의 소스 코드에서 다음 코드 조각을 볼 수 있습니다.
case Gravity.CENTER_HORIZONTAL:
case Gravity.FILL_HORIZONTAL:
return (mLayout.getLineWidth(0) - ((mRight - mLeft) -
getCompoundPaddingLeft() - getCompoundPaddingRight())) /
getHorizontalFadingEdgeLength();
이 문제에 대한 사용자 정의 보기가 있으며, 이 사용자 정의 텍스트 보기는 정당화된 텍스트 보기를 지원합니다.
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);
"TextJustify" 파일 두 개만 가져오면 됩니다.프로젝트에 Utils.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
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);
두 가지 옵션이 있다고 생각합니다.
NDK를 통해 이를 전문으로 하는 Pango와 같은 것을 사용하고 OpenGL 또는 다른 표면으로 텍스트를 렌더링합니다.
그림판.measureText() 및 친구를 사용하여 단어의 길이를 가져오고 사용자 정의 보기의 캔버스에 수동으로 배치합니다.
Android는 아직 완전한 정당성을 지원하지 않습니다.우리는 텍스트 뷰 대신 웹 뷰를 사용하고 HTML을 정당화할 수 있습니다.작동이 아주 잘 됩니다.잘 모르겠으면 언제든지 물어봐요 :)
justificationMode는 xml에서 inter_word로 사용할 수 있습니다.이 속성은 api 레벨 26 이상에서 사용할 수 있습니다.이를 위해 대상 API도 할당할 수 있습니다.전체 코드는 다음과 같습니다.
<com.google.android.material.textview.MaterialTextView
...
android:justificationMode="inter_word"
tools:targetApi="o" />
8.0 이하의 코드를 사용해 보십시오.
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:gravity="center|start"/>
xml 파일에서 이 속성만 사용
android:justificationMode="inter_word"
간단하게 안드로이드를 사용할 수 있습니다.justificationMode="inter_word"
<TextView
android:justificationMode="inter_word"
android:id="@+id/messageTv"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="@dimen/text_margin"
android:paddingTop="15sp"
android:textAppearance="@style/TextAppearance.Material3.TitleMedium" />
언급URL : https://stackoverflow.com/questions/1292575/android-textview-justify-text
'programing' 카테고리의 다른 글
Capybara를 사용하여 드롭다운에서 옵션을 선택하는 방법 (0) | 2023.06.03 |
---|---|
여러 캐치 블록을 사용한 VB.NET 캐치 시도 (0) | 2023.06.03 |
장고 - 이메일로 로그인 (0) | 2023.06.03 |
JOIN과 UNION의 차이점은 무엇입니까? (0) | 2023.06.03 |
루비에서 UTC 타임스탬프를 얻는 방법은 무엇입니까? (0) | 2023.06.03 |