คุณจะทำให้ข้อความของ a TextView
ถูกจัดชิดขอบ (ด้วยการล้างข้อความทางซ้ายและขวา) ได้อย่างไร?
ฉันพบวิธีแก้ปัญหาที่เป็นไปได้ที่นี่แต่มันไม่ทำงาน (แม้ว่าคุณจะเปลี่ยนศูนย์กลางแนวตั้งเป็น center_vertical ฯลฯ )
คุณจะทำให้ข้อความของ a TextView
ถูกจัดชิดขอบ (ด้วยการล้างข้อความทางซ้ายและขวา) ได้อย่างไร?
ฉันพบวิธีแก้ปัญหาที่เป็นไปได้ที่นี่แต่มันไม่ทำงาน (แม้ว่าคุณจะเปลี่ยนศูนย์กลางแนวตั้งเป็น center_vertical ฯลฯ )
คำตอบ:
ฉันไม่เชื่อว่า Android รองรับเหตุผลอย่างเต็มรูปแบบ
UPDATE 2018/01/01 : Android 8.0 ขึ้นไปรองรับโหมดเหตุผลด้วยTextView
คำตอบ @CommonsWare ถูกต้อง Android 8.0+ รองรับ "Full Justification" (หรือเพียงแค่ "Justification" เนื่องจากบางครั้งมีการอ้างอิงอย่างคลุมเครือ)
Android ยังรองรับ "การจัดแนวข้อความซ้าย / ขวา" ดูบทความวิกิพีเดียเกี่ยวกับเหตุผลสำหรับความแตกต่าง หลายคนพิจารณาแนวคิดของ 'การจัดชิดขอบ' เพื่อรวมการจัดชิดขอบเต็มรูปแบบรวมถึงการจัดแนวข้อความซ้าย / ขวาซึ่งเป็นสิ่งที่พวกเขาค้นหาเมื่อพวกเขาต้องการจัดแนวข้อความซ้าย / ขวา คำตอบนี้อธิบายวิธีการจัดแนวข้อความซ้าย / ขวา
เป็นไปได้ที่จะบรรลุการจัดข้อความแบบฟลัชซ้าย / ขวา (ตรงข้ามกับการจัดชิดขอบเต็มตามคำถามที่ถาม) ในการสาธิตฉันจะใช้รูปแบบ 2 คอลัมน์พื้นฐาน (ป้ายกำกับในคอลัมน์ด้านซ้ายและช่องข้อความในคอลัมน์ด้านขวา) เป็นตัวอย่าง ในตัวอย่างนี้ข้อความในป้ายกำกับในคอลัมน์ด้านซ้ายจะถูกจัดชิดขวาเพื่อให้ปรากฏขึ้นเมื่อเทียบกับเขตข้อมูลข้อความในคอลัมน์ด้านขวา
ในเค้าโครง XML คุณสามารถรับองค์ประกอบ TextView ด้วยตนเอง (คอลัมน์ซ้าย) เพื่อจัดเรียงทางด้านขวาด้วยการเพิ่มแอตทริบิวต์ต่อไปนี้ภายใน TextViews ทั้งหมด:
<TextView
...
android:layout_gravity="center_vertical|end">
...
</TextView>
อย่างไรก็ตามหากข้อความล้อมรอบหลายบรรทัดข้อความจะยังคงอยู่ทางซ้ายชิดชิดภายใน TextView การเพิ่มแอททริบิวต่อไปนี้ทำให้การจัดชิดข้อความจริงถูกจัดชิด (ซ้ายขาด) ภายใน TextView:
<TextView
...
android:gravity="end">
...
</TextView>
ดังนั้นแอตทริบิวต์แรงโน้มถ่วงระบุวิธีจัดแนวข้อความภายใน TextView layout_gravityระบุวิธีจัดแนว / เค้าโครงองค์ประกอบ TextView เอง
android:layout_gravity="center_horizontal|center"
android:gravity="center"
เพียงเพื่อเพิ่มถ้าคุณต้องการที่ศูนย์เหตุผลที่คุณสามารถทำได้
justify
เพื่อปรับข้อความใน 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>
ฉันยังไม่สามารถอัปโหลดภาพเพื่อพิสูจน์ได้ แต่ "ใช้งานได้สำหรับฉัน"
view.loadData()
view.setBackgroundColor("#00000000")
view.loadUrl()
งานโดยview.loadData()
ไม่ต้องทำ ฉันไม่รู้ว่าทำไมคนหลังถึงไม่ทำ
เราได้สร้างคลาสที่ง่ายสำหรับเรื่องนี้ ขณะนี้มีสองวิธีในการบรรลุสิ่งที่คุณต้องการ ทั้งสองต้องไม่ WebViewและรองรับ SPANNABLES
LIBRARY : https://github.com/bluejamesbond/TextJustify-Android
SUPPORTS : Android 2.0 ถึง 5.X
ติดตั้ง
// Please visit Github for latest setup instructions.
SCREENSHOT
TextView
ในAndroid O
ข้อเสนอที่เต็มไปด้วยเหตุผล (การจัดตำแหน่งตัวพิมพ์ใหม่) เอง
คุณเพียงแค่ต้องทำสิ่งนี้:
Kotlin
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
เริ่มต้นคือ
คุณสามารถใช้JustifiedTextView สำหรับโครงการAndroidใน github นี่เป็นมุมมองที่กำหนดเองที่จำลองข้อความที่เป็นธรรมสำหรับคุณ รองรับ Android 2.0+ และภาษาจากขวาไปซ้าย
ฉันเขียนวิดเจ็ตตาม textview ดั้งเดิมเพื่อทำ
ฉันพบวิธีที่จะแก้ปัญหานี้ แต่นี่อาจไม่ได้ดีมาก แต่ผลไม่เลว
หลักการของมันคือการแทนที่ช่องว่างของแต่ละบรรทัดเป็น 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
ข้อมูลทั่วไป:
โครงร่าง XML: ประกาศ WebView แทน TextView
<WebView
android:id="@+id/textContent"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
รหัส Java: ตั้งค่าข้อมูลข้อความเป็น WebView
WebView view = (WebView) findViewById(R.id.textContent);
String text;
text = "<html><body><p align=\"justify\">";
text+= "This is the text will be justified when displayed!!!";
text+= "</p></body></html>";
view.loadData(text, "text/html", "utf-8");
วิธีนี้อาจช่วยแก้ปัญหาของคุณได้ มันทำงานได้อย่างสมบูรณ์สำหรับฉัน
นี่คือวิธีที่ฉันทำฉันคิดว่าวิธีที่ดีที่สุดที่ฉันจะทำได้ ด้วยวิธีนี้สิ่งเดียวที่คุณต้องทำในเลย์เอาต์ของคุณคือ:
xmlns
ประกาศเพิ่มเติมTextView
เนมสเปซของข้อความต้นฉบับจาก Android เป็นเนมสเปซใหม่ของคุณTextView
ด้วยx.y.z.JustifiedTextView
นี่คือรหัส ทำงานได้อย่างสมบูรณ์แบบบนโทรศัพท์ของฉัน (Galaxy Nexus Android 4.0.2, Galaxy Teos Android 2.1) แน่นอนว่าต้องเปลี่ยนชื่อแพ็คเกจของฉันเป็นของคุณ
/assets/justified_textview.css :
body {
font-size: 1.0em;
color: rgb(180,180,180);
text-align: justify;
}
@media screen and (-webkit-device-pixel-ratio: 1.5) {
/* CSS for high-density screens */
body {
font-size: 1.05em;
}
}
@media screen and (-webkit-device-pixel-ratio: 2.0) {
/* CSS for extra high-density screens */
body {
font-size: 1.1em;
}
}
/res/values/attrs.xml :
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="JustifiedTextView">
<attr name="text" format="reference" />
</declare-styleable>
</resources>
/res/layout/test.xml :
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:myapp="http://schemas.android.com/apk/res/net.bicou.myapp"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >
<net.bicou.myapp.widget.JustifiedTextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
myapp:text="@string/surv1_1" />
</LinearLayout>
</ScrollView>
/src/net/bicou/myapp/widget/JustifiedTextView.java :
package net.bicou.myapp.widget;
import net.bicou.myapp.R;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Color;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.View;
import android.webkit.WebView;
public class JustifiedTextView extends WebView {
public JustifiedTextView(final Context context) {
this(context, null, 0);
}
public JustifiedTextView(final Context context, final AttributeSet attrs) {
this(context, attrs, 0);
}
public JustifiedTextView(final Context context, final AttributeSet attrs, final int defStyle) {
super(context, attrs, defStyle);
if (attrs != null) {
final TypedValue tv = new TypedValue();
final TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.JustifiedTextView, defStyle, 0);
if (ta != null) {
ta.getValue(R.styleable.JustifiedTextView_text, tv);
if (tv.resourceId > 0) {
final String text = context.getString(tv.resourceId).replace("\n", "<br />");
loadDataWithBaseURL("file:///android_asset/",
"<html><head>" +
"<link rel=\"stylesheet\" type=\"text/css\" href=\"justified_textview.css\" />" +
"</head><body>" + text + "</body></html>",
"text/html", "UTF8", null);
setTransparentBackground();
}
}
}
}
public void setTransparentBackground() {
try {
setLayerType(View.LAYER_TYPE_SOFTWARE, null);
} catch (final NoSuchMethodError e) {
}
setBackgroundColor(Color.TRANSPARENT);
setBackgroundDrawable(null);
setBackgroundResource(0);
}
}
เราจำเป็นต้องตั้งค่าการเรนเดอร์เป็นซอฟต์แวร์เพื่อให้พื้นหลังโปร่งใสบน Android 3+ ดังนั้นลองสำหรับ Android รุ่นเก่า
หวังว่านี่จะช่วยได้!
PS: โปรดอย่าว่ามันอาจจะมีประโยชน์ในการเพิ่มสิ่งนี้ไปยังกิจกรรมทั้งหมดของคุณใน Android 3+ เพื่อให้ได้พฤติกรรมที่คาดหวัง:
android:hardwareAccelerated="false"
ง่ายมากเราสามารถทำได้ในไฟล์ xml
<TextView
android:justificationMode="inter_word"
/>
ในขณะที่ยังไม่สมบูรณ์ข้อความที่เป็นธรรมคุณสามารถสมดุลความยาวบรรทัดโดยใช้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;
}
}
// 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>
FILL_HORIZONTAL
CENTER_HORIZONTAL
เทียบเท่ากับ คุณสามารถดูข้อมูลโค้ดนี้ในซอร์สโค้ดของ textview:
case Gravity.CENTER_HORIZONTAL:
case Gravity.FILL_HORIZONTAL:
return (mLayout.getLineWidth(0) - ((mRight - mLeft) -
getCompoundPaddingLeft() - getCompoundPaddingRight())) /
getHorizontalFadingEdgeLength();
มี CustomView สำหรับปัญหานี้มุมมองข้อความที่กำหนดเองนี้รองรับมุมมองข้อความที่ถูกต้อง
ยกเค้าที่นี้JustifiedTextView
import java.util.ArrayList;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Typeface;
import android.text.TextPaint;
import android.view.View;
public class JustifiedTextView extends View {
String text;
ArrayList<Line> linesCollection = new ArrayList<Line>();
TextPaint textPaint;
Typeface font;
int textColor;
float textSize = 42f, lineHeight = 57f, wordSpacing = 15f, lineSpacing = 15f;
float onBirim, w, h;
float leftPadding, rightPadding;
public JustifiedTextView(Context context, String text) {
super(context);
this.text = text;
init();
}
private void init() {
textPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
textColor = Color.BLACK;
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
if (font != null) {
font = Typeface.createFromAsset(getContext().getAssets(), "font/Trykker-Regular.ttf");
textPaint.setTypeface(font);
}
textPaint.setColor(textColor);
int minw = getPaddingLeft() + getPaddingRight() + getSuggestedMinimumWidth();
w = resolveSizeAndState(minw, widthMeasureSpec, 1);
h = MeasureSpec.getSize(widthMeasureSpec);
onBirim = 0.009259259f * w;
lineHeight = textSize + lineSpacing;
leftPadding = 3 * onBirim + getPaddingLeft();
rightPadding = 3 * onBirim + getPaddingRight();
textPaint.setTextSize(textSize);
wordSpacing = 15f;
Line lineBuffer = new Line();
this.linesCollection.clear();
String[] lines = text.split("\n");
for (String line : lines) {
String[] words = line.split(" ");
lineBuffer = new Line();
float lineWidth = leftPadding + rightPadding;
float totalWordWidth = 0;
for (String word : words) {
float ww = textPaint.measureText(word) + wordSpacing;
if (lineWidth + ww + (lineBuffer.getWords().size() * wordSpacing) > w) {// is
lineBuffer.addWord(word);
totalWordWidth += textPaint.measureText(word);
lineBuffer.setSpacing((w - totalWordWidth - leftPadding - rightPadding) / (lineBuffer.getWords().size() - 1));
this.linesCollection.add(lineBuffer);
lineBuffer = new Line();
totalWordWidth = 0;
lineWidth = leftPadding + rightPadding;
} else {
lineBuffer.setSpacing(wordSpacing);
lineBuffer.addWord(word);
totalWordWidth += textPaint.measureText(word);
lineWidth += ww;
}
}
this.linesCollection.add(lineBuffer);
}
setMeasuredDimension((int) w, (int) ((this.linesCollection.size() + 1) * lineHeight + (10 * onBirim)));
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawLine(0f, 10f, getMeasuredWidth(), 10f, textPaint);
float x, y = lineHeight + onBirim;
for (Line line : linesCollection) {
x = leftPadding;
for (String s : line.getWords()) {
canvas.drawText(s, x, y, textPaint);
x += textPaint.measureText(s) + line.spacing;
}
y += lineHeight;
}
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
public Typeface getFont() {
return font;
}
public void setFont(Typeface font) {
this.font = font;
}
public float getLineHeight() {
return lineHeight;
}
public void setLineHeight(float lineHeight) {
this.lineHeight = lineHeight;
}
public float getLeftPadding() {
return leftPadding;
}
public void setLeftPadding(float leftPadding) {
this.leftPadding = leftPadding;
}
public float getRightPadding() {
return rightPadding;
}
public void setRightPadding(float rightPadding) {
this.rightPadding = rightPadding;
}
public void setWordSpacing(float wordSpacing) {
this.wordSpacing = wordSpacing;
}
public float getWordSpacing() {
return wordSpacing;
}
public float getLineSpacing() {
return lineSpacing;
}
public void setLineSpacing(float lineSpacing) {
this.lineSpacing = lineSpacing;
}
class Line {
ArrayList<String> words = new ArrayList<String>();
float spacing = 15f;
public Line() {
}
public Line(ArrayList<String> words, float spacing) {
this.words = words;
this.spacing = spacing;
}
public void setSpacing(float spacing) {
this.spacing = spacing;
}
public float getSpacing() {
return spacing;
}
public void addWord(String s) {
words.add(s);
}
public ArrayList<String> getWords() {
return words;
}
}
}
เพิ่มคลาสข้างต้นลงในโฟลเดอร์ src ของคุณและใช้โค้ดตัวอย่างนี้เพื่อเพิ่มในเลย์เอาต์ของคุณ:
JustifiedTextView jtv= new JustifiedTextView(getApplicationContext(), "Lorem ipsum dolor sit amet... ");
LinearLayout place = (LinearLayout) findViewById(R.id.book_profile_content);
place.addView(jtv);
ดูที่นี่ใน GitHub
เพียงนำเข้าสองไฟล์ "TextJustifyUtils.java" และ "TextViewEx.java" ในโครงการของคุณ
public class TextJustifyUtils {
// Please use run(...) instead
public static void justify(TextView textView) {
Paint paint = new Paint();
String[] blocks;
float spaceOffset = 0;
float textWrapWidth = 0;
int spacesToSpread;
float wrappedEdgeSpace;
String block;
String[] lineAsWords;
String wrappedLine;
String smb = "";
Object[] wrappedObj;
// Pull widget properties
paint.setColor(textView.getCurrentTextColor());
paint.setTypeface(textView.getTypeface());
paint.setTextSize(textView.getTextSize());
textWrapWidth = textView.getWidth();
spaceOffset = paint.measureText(" ");
blocks = textView.getText().toString().split("((?<=\n)|(?=\n))");
if (textWrapWidth < 20) {
return;
}
for (int i = 0; i < blocks.length; i++) {
block = blocks[i];
if (block.length() == 0) {
continue;
} else if (block.equals("\n")) {
smb += block;
continue;
}
block = block.trim();
if (block.length() == 0)
continue;
wrappedObj = TextJustifyUtils.createWrappedLine(block, paint,
spaceOffset, textWrapWidth);
wrappedLine = ((String) wrappedObj[0]);
wrappedEdgeSpace = (Float) wrappedObj[1];
lineAsWords = wrappedLine.split(" ");
spacesToSpread = (int) (wrappedEdgeSpace != Float.MIN_VALUE ? wrappedEdgeSpace
/ spaceOffset
: 0);
for (String word : lineAsWords) {
smb += word + " ";
if (--spacesToSpread > 0) {
smb += " ";
}
}
smb = smb.trim();
if (blocks[i].length() > 0) {
blocks[i] = blocks[i].substring(wrappedLine.length());
if (blocks[i].length() > 0) {
smb += "\n";
}
i--;
}
}
textView.setGravity(Gravity.LEFT);
textView.setText(smb);
}
protected static Object[] createWrappedLine(String block, Paint paint,
float spaceOffset, float maxWidth) {
float cacheWidth = maxWidth;
float origMaxWidth = maxWidth;
String line = "";
for (String word : block.split("\\s")) {
cacheWidth = paint.measureText(word);
maxWidth -= cacheWidth;
if (maxWidth <= 0) {
return new Object[] { line, maxWidth + cacheWidth + spaceOffset };
}
line += word + " ";
maxWidth -= spaceOffset;
}
if (paint.measureText(block) <= origMaxWidth) {
return new Object[] { block, Float.MIN_VALUE };
}
return new Object[] { line, maxWidth };
}
final static String SYSTEM_NEWLINE = "\n";
final static float COMPLEXITY = 5.12f; // Reducing this will increase
// efficiency but will decrease
// effectiveness
final static Paint p = new Paint();
public static void run(final TextView tv, float origWidth) {
String s = tv.getText().toString();
p.setTypeface(tv.getTypeface());
String[] splits = s.split(SYSTEM_NEWLINE);
float width = origWidth - 5;
for (int x = 0; x < splits.length; x++)
if (p.measureText(splits[x]) > width) {
splits[x] = wrap(splits[x], width, p);
String[] microSplits = splits[x].split(SYSTEM_NEWLINE);
for (int y = 0; y < microSplits.length - 1; y++)
microSplits[y] = justify(removeLast(microSplits[y], " "),
width, p);
StringBuilder smb_internal = new StringBuilder();
for (int z = 0; z < microSplits.length; z++)
smb_internal.append(microSplits[z]
+ ((z + 1 < microSplits.length) ? SYSTEM_NEWLINE
: ""));
splits[x] = smb_internal.toString();
}
final StringBuilder smb = new StringBuilder();
for (String cleaned : splits)
smb.append(cleaned + SYSTEM_NEWLINE);
tv.setGravity(Gravity.LEFT);
tv.setText(smb);
}
private static String wrap(String s, float width, Paint p) {
String[] str = s.split("\\s"); // regex
StringBuilder smb = new StringBuilder(); // save memory
smb.append(SYSTEM_NEWLINE);
for (int x = 0; x < str.length; x++) {
float length = p.measureText(str[x]);
String[] pieces = smb.toString().split(SYSTEM_NEWLINE);
try {
if (p.measureText(pieces[pieces.length - 1]) + length > width)
smb.append(SYSTEM_NEWLINE);
} catch (Exception e) {
}
smb.append(str[x] + " ");
}
return smb.toString().replaceFirst(SYSTEM_NEWLINE, "");
}
private static String removeLast(String s, String g) {
if (s.contains(g)) {
int index = s.lastIndexOf(g);
int indexEnd = index + g.length();
if (index == 0)
return s.substring(1);
else if (index == s.length() - 1)
return s.substring(0, index);
else
return s.substring(0, index) + s.substring(indexEnd);
}
return s;
}
private static String justifyOperation(String s, float width, Paint p) {
float holder = (float) (COMPLEXITY * Math.random());
while (s.contains(Float.toString(holder)))
holder = (float) (COMPLEXITY * Math.random());
String holder_string = Float.toString(holder);
float lessThan = width;
int timeOut = 100;
int current = 0;
while (p.measureText(s) < lessThan && current < timeOut) {
s = s.replaceFirst(" ([^" + holder_string + "])", " "
+ holder_string + "$1");
lessThan = p.measureText(holder_string) + lessThan
- p.measureText(" ");
current++;
}
String cleaned = s.replaceAll(holder_string, " ");
return cleaned;
}
private static String justify(String s, float width, Paint p) {
while (p.measureText(s) < width) {
s = justifyOperation(s, width, p);
}
return s;
}
}
และ
public class TextViewEx extends TextView {
private Paint paint = new Paint();
private String[] blocks;
private float spaceOffset = 0;
private float horizontalOffset = 0;
private float verticalOffset = 0;
private float horizontalFontOffset = 0;
private float dirtyRegionWidth = 0;
private boolean wrapEnabled = false;
int left, top, right, bottom = 0;
private Align _align = Align.LEFT;
private float strecthOffset;
private float wrappedEdgeSpace;
private String block;
private String wrappedLine;
private String[] lineAsWords;
private Object[] wrappedObj;
private Bitmap cache = null;
private boolean cacheEnabled = false;
public TextViewEx(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
// set a minimum of left and right padding so that the texts are not too
// close to the side screen
// this.setPadding(10, 0, 10, 0);
}
public TextViewEx(Context context, AttributeSet attrs) {
super(context, attrs);
// this.setPadding(10, 0, 10, 0);
}
public TextViewEx(Context context) {
super(context);
// this.setPadding(10, 0, 10, 0);
}
@Override
public void setPadding(int left, int top, int right, int bottom) {
// TODO Auto-generated method stub
super.setPadding(left + 10, top, right + 10, bottom);
}
@Override
public void setDrawingCacheEnabled(boolean cacheEnabled) {
this.cacheEnabled = cacheEnabled;
}
public void setText(String st, boolean wrap) {
wrapEnabled = wrap;
super.setText(st);
}
public void setTextAlign(Align align) {
_align = align;
}
@SuppressLint("NewApi")
@Override
protected void onDraw(Canvas canvas) {
// If wrap is disabled then,
// request original onDraw
if (!wrapEnabled) {
super.onDraw(canvas);
return;
}
// Active canas needs to be set
// based on cacheEnabled
Canvas activeCanvas = null;
// Set the active canvas based on
// whether cache is enabled
if (cacheEnabled) {
if (cache != null) {
// Draw to the OS provided canvas
// if the cache is not empty
canvas.drawBitmap(cache, 0, 0, paint);
return;
} else {
// Create a bitmap and set the activeCanvas
// to the one derived from the bitmap
cache = Bitmap.createBitmap(getWidth(), getHeight(),
Config.ARGB_4444);
activeCanvas = new Canvas(cache);
}
} else {
// Active canvas is the OS
// provided canvas
activeCanvas = canvas;
}
// Pull widget properties
paint.setColor(getCurrentTextColor());
paint.setTypeface(getTypeface());
paint.setTextSize(getTextSize());
paint.setTextAlign(_align);
paint.setFlags(Paint.ANTI_ALIAS_FLAG);
// minus out the paddings pixel
dirtyRegionWidth = getWidth() - getPaddingLeft() - getPaddingRight();
int maxLines = Integer.MAX_VALUE;
int currentapiVersion = android.os.Build.VERSION.SDK_INT;
if (currentapiVersion >= android.os.Build.VERSION_CODES.JELLY_BEAN) {
maxLines = getMaxLines();
}
int lines = 1;
blocks = getText().toString().split("((?<=\n)|(?=\n))");
verticalOffset = horizontalFontOffset = getLineHeight() - 0.5f; // Temp
// fix
spaceOffset = paint.measureText(" ");
for (int i = 0; i < blocks.length && lines <= maxLines; i++) {
block = blocks[i];
horizontalOffset = 0;
if (block.length() == 0) {
continue;
} else if (block.equals("\n")) {
verticalOffset += horizontalFontOffset;
continue;
}
block = block.trim();
if (block.length() == 0) {
continue;
}
wrappedObj = TextJustifyUtils.createWrappedLine(block, paint,
spaceOffset, dirtyRegionWidth);
wrappedLine = ((String) wrappedObj[0]);
wrappedEdgeSpace = (Float) wrappedObj[1];
lineAsWords = wrappedLine.split(" ");
strecthOffset = wrappedEdgeSpace != Float.MIN_VALUE ? wrappedEdgeSpace
/ (lineAsWords.length - 1)
: 0;
for (int j = 0; j < lineAsWords.length; j++) {
String word = lineAsWords[j];
if (lines == maxLines && j == lineAsWords.length - 1) {
activeCanvas.drawText("...", horizontalOffset,
verticalOffset, paint);
} else if (j == 0) {
// if it is the first word of the line, text will be drawn
// starting from right edge of textview
if (_align == Align.RIGHT) {
activeCanvas.drawText(word, getWidth()
- (getPaddingRight()), verticalOffset, paint);
// add in the paddings to the horizontalOffset
horizontalOffset += getWidth() - (getPaddingRight());
} else {
activeCanvas.drawText(word, getPaddingLeft(),
verticalOffset, paint);
horizontalOffset += getPaddingLeft();
}
} else {
activeCanvas.drawText(word, horizontalOffset,
verticalOffset, paint);
}
if (_align == Align.RIGHT)
horizontalOffset -= paint.measureText(word) + spaceOffset
+ strecthOffset;
else
horizontalOffset += paint.measureText(word) + spaceOffset
+ strecthOffset;
}
lines++;
if (blocks[i].length() > 0) {
blocks[i] = blocks[i].substring(wrappedLine.length());
verticalOffset += blocks[i].length() > 0 ? horizontalFontOffset
: 0;
i--;
}
}
if (cacheEnabled) {
// Draw the cache onto the OS provided
// canvas.
canvas.drawBitmap(cache, 0, 0, paint);
}
}
}
ตอนนี้ถ้าคุณใช้ textView ปกติเช่น:
<TextView
android:id="@+id/original"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/lorum_ipsum" />
เพียงใช้
<yourpackagename.TextViewEx
android:id="@+id/changed"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/lorum_ipsum" />
กำหนดตัวแปรและตั้งค่าให้เป็นจริง
TextViewEx changed = (TextViewEx) findViewById(R.id.changed);
changed.setText(getResources().getString(R.string.lorum_ipsum),true);
ปรับข้อความ Android สำหรับ TextView XML
เพียงปรับข้อความหุ่นยนต์โดยใช้ใน XML คุณสามารถนำไปใช้ในวิดเจ็ตข้อความ
<TextView
android:justificationMode="inter_word"
/>
ค่าเริ่มต้นคือ android:justificationMode="none"
ฉันคิดว่ามีสองตัวเลือก:
ใช้บางอย่างเช่น Pango ที่เชี่ยวชาญเรื่องนี้ผ่าน NDK และแสดงข้อความไปยัง OpenGL หรือพื้นผิวอื่น ๆ
ใช้Paint.measureText ()และเพื่อน ๆ เพื่อรับความยาวของคำและวางคำเหล่านั้นลงบน Canvas ด้วยตนเองในมุมมองที่กำหนดเอง
สำหรับ Android เพื่อแสดงข้อความที่เหมาะสมและไม่มีการตัดทอนสีพื้นหลังลองใช้วิธีนี้ใช้ได้กับฉันสร้างผลลัพธ์ที่สอดคล้องกันบน Android, ff, & & chrome แต่คุณต้องวัดพื้นที่ที่เหลืออยู่ระหว่างข้อความ เมื่อคำนวณช่องว่างภายใน
<td style="font-family:Calibri,Arial;
font-size:15px;
font-weight:800;
background-color:#f5d5fd;
color:black;
border-style:solid;
border-width:1px;
border-color:#bd07eb;
padding-left:10px;
padding-right:1000px;
padding-top:3px;
padding-bottom:3px;
>
แฮ็คคือข้อความpadding-right:1000px;
ที่ผลักไปทางซ้ายสุด
ความพยายามใด ๆ ในการซ้ายหรือปรับรหัสใน css หรือ html ให้ผลลัพธ์ในพื้นหลังที่มีความกว้างเพียงครึ่งเดียว
สำหรับการจัดรูปแบบ html คุณไม่จำเป็นต้องเรียกใช้ Webkit คุณสามารถใช้Html.fromHtml(text)
ทำงานได้
ที่มา: http://developer.android.com/guide/topics/resources/string-resource.html
Android ยังไม่รองรับการอ้างเหตุผลอย่างเต็มรูปแบบ เราสามารถใช้ Webview และปรับ HTML แทนการใช้ textview มันใช้งานได้ดี หากพวกคุณไม่ชัดเจนอย่าลังเลที่จะถามฉัน :)
WebView
transparent
แต่เราสามารถตั้งค่าพื้นหลังของ ฉันมีภาพพื้นหลัง
ลองวิธีแก้ปัญหานี้ในลิงค์ด้านล่างเพียงแค่สร้างคลาสนั้นในโฟลเดอร์โครงการและใช้งาน มันใช้งานได้ดีสำหรับฉัน :)
จัดข้อความในแอพ Android โดยใช้ WebView แต่นำเสนออินเทอร์เฟซที่คล้าย TextView ใช่ไหม
การปรับเนื้อหาให้เป็นเนื้อหา TextView: พวกมันใช้งานง่ายเพียงใช้ android: justificationMode = "inter_word" ภายในแท็ก TextView ของคุณ
<TextView
android:id="@+id/textView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="92dp"
android:text="@string/contents"
android:layout_margin="20dp"
android:justificationMode="inter_word"
/>
ลองใช้ < RelativeLayout >
(ตรวจสอบให้แน่ใจว่าได้กรอกข้อมูล) แล้วเพิ่มandroid:layout_alignParentLeft="true"
และ
android:layout_alignParentRight="true"
องค์ประกอบที่คุณต้องการในด้านซ้ายและขวาด้านนอก
BLAM เป็นธรรม!
คุณต้องตั้งค่า
android:layout_height="wrap_content"
และ
android:layout_centerInParent="true"
สิ่งนี้ไม่ได้เป็นการพิสูจน์ข้อความของคุณจริงๆ
android:gravity="center_horizontal"
เป็นตัวเลือกที่ดีที่สุดที่คุณมี