Android TextViewalignment文本
你如何得到一个TextView
的文本是alignment的(文本在左侧和右侧齐平)?
我在这里find了一个可能的解决scheme,但是它不起作用(即使你把vertical-center改成center_vertical等等)。
我不相信Android支持完整的理由。
@CommonsWare的答案是正确的。 Android不支持“完整的理由”(或者简单地称为“理由”,因为它有时被模棱两可地提到)。
但是,Android不支持“冲洗左/右文本alignment”。 请参阅维基百科关于理由的文章。 很多人认为“理由”这个概念包含了完整的理由和左/右的文本alignment,当他们想要做左/右文本alignment时,他们最终search的就是这个alignment。 这个答案解释了如何实现左/右文本alignment。
有可能实现冲洗左/右文本alignment(不是全面的理由,因为问题是关于)。 为了演示,我将使用一个基本的2列表格(左栏中的标签和右栏中的文本框)作为示例。 在本例中,左列标签中的文本将右alignment,因此它们在右列中显示为与其文本字段齐平。
在XML布局中,通过在所有TextView中添加以下属性,您可以将TextView元素本身(左列)alignment到右边:
<TextView ... android:layout_gravity="center_vertical|right"> ... </TextView>
但是,如果文本换行为多行,那么文本仍然会在TextView中左alignment。 添加下面的属性使实际的文本在TextView内右alignment(左边不齐):
<TextView ... android:gravity="right"> ... </TextView>
所以重力属性指定如何alignmentTextView中的文本layout_gravity指定如何alignment/布局TextView元素本身。
为了certificateAndroid中的文本,我使用了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>
我还不能上传图像来certificate它,但“它适用于我”。
更新
我们已经为此创build了一个简单的类。 目前有两种方法来实现你正在寻找的东西。 两者都不需要WEBVIEW和SUPPORTS SPANNABLES 。
图书馆 : https : //github.com/bluejamesbond/TextJustify-Android
支持 :Android 2.0至5.X
build立
// Please visit Github for latest setup instructions.
屏幕截图
你可以在github中使用JustifiedTextView for Android项目。 这是一个自定义视图,为您模拟合理的文本。 它支持Android 2.0+和从左到右的语言。
我编写一个基于本地textview的小部件来做到这一点。
github上
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");
这可能会解决你的问题。 它完全为我工作。
我是这么做的,我想我是最优雅的。 有了这个解决scheme,您在布局中唯一需要做的事情是:
- 添加一个额外的
xmlns
声明 - 将您的
TextView
的源文本命名空间从android更改为新的命名空间 - 用
xyzJustifiedTextView
replace你的TextView
这是代码。 在我的手机上工作得很好(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"
虽然仍然没有完整的alignment文本,但现在可以使用API 23中的android:breakStrategy="balanced"
来平衡行长度
http://developer.android.com/reference/android/widget/TextView.html#attr_android:breakStrategy
Android O
TextView
提供了完全的理由(新的印刷alignment)本身。
你只需要这样做,
textView.setJustificationMode(JUSTIFICATION_MODE_INTER_WORD);
默认是JUSTIFICATION_MODE_NONE
。
FILL_HORIZONTAL
等同于CENTER_HORIZONTAL
。 你可以在textview的源代码中看到这个代码片段:
case Gravity.CENTER_HORIZONTAL: case Gravity.FILL_HORIZONTAL: return (mLayout.getLineWidth(0) - ((mRight - mLeft) - getCompoundPaddingLeft() - getCompoundPaddingRight())) / getHorizontalFadingEdgeLength();
我觉得有两个select:
-
使用类似于Pango的东西,通过NDK专门做这件事,并将文本渲染到OpenGL或其他表面。
-
使用Paint.measureText()和朋友来获取单词的长度,并在自定义视图中手动放置在canvas上。
我写我自己的类来解决这个问题,在这里它只是你必须调用静态alignment函数,它带有两个参数
- 文本视图对象
- 内容宽度(文本视图的总宽度)
//主要活动
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>
在下面的链接中尝试这个解决scheme,只需在项目文件夹中创build该类,然后使用它。 它为我工作正常:)
使用WebView在Android应用程序中alignment文本,但呈现类似于TextView的界面?
对于html格式化,您不需要调用Webkit,您可以使用Html.fromHtml(text)
来完成这项工作。
来源: http : //developer.android.com/guide/topics/resources/string-resource.html
Android尚不支持完整的理由。 我们可以使用Webview来certificateHTML而不是使用textview。 它工作得很好。 如果你们不清楚,请随时问我:)
这个问题有一个CustomView,这个自定义文本视图支持alignment文本视图。
拿起这个: 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);
在Android上,为了左alignment文本,而不是截断背景颜色,试试这个,它为我工作,在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中留下或alignment代码的结果都是只有半宽的背景。
我find了解决这个问题的办法,但是这可能不是很优雅,但是效果还不错。
其原理是将每行的空格replace为固定宽度的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
概述:
你必须设置
android:layout_height="wrap_content"
和
android:layout_centerInParent="true"
这并不能certificate你的文字
android:gravity="center_horizontal"
是你有的最好的select。
此外,沃尔芬
尝试使用< RelativeLayout >
(确保fill_parent),然后添加android:layout_alignParentLeft="true"
和
android:layout_alignParentRight="true"
,你想要在外部的左和右。
BLAM,有道理!