The @CommonsWare answer is correct. Android 8.0+ does support "Full Justification" (or simply "Justification", as it is sometimes ambiguously referred to).
Android also supports "Flush Left/Right Text Alignment". See the wikipedia article on Justification for the distinction. Many people consider the concept of 'justification' to encompass full-justification as well as left/right text alignment, which is what they end up searching for when they want to do left/right text alignment. This answer explains how to achieve the left/right text alignment.
It is possible to achieve Flush Left/Right Text Alignment (as opposed to Full Justification, as the question is asking about). To demonstrate I will be using a basic 2-column form (labels in the left column and text fields in the right column) as an example. In this example the text in the labels in the left column will be right-aligned so they appear flush up against their text fields in the right column.
In the XML layout you can get the TextView elements themselves (the left column) to align to the right by adding the following attribute inside all of the TextViews:
However, if the text wraps to multiple lines, the text would still be flush left aligned inside the TextView. Adding the following attribute makes the actual text flush right aligned (ragged left) inside the TextView:
// Please visit Github for latest setup instructions.
屏幕截图
UPDATED
We have created a simple class for this. There are currently two methods to achieve what you are looking for. Both require NO WEBVIEW and SUPPORTS SPANNABLES.
You can use JustifiedTextView for Android project in github. this is a custom view that simulate justified text for you. It support Android 2.0+ and right to left languages.
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");
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");
This may Solve your problem.
Its Fully worked for me.
Here's how I did it, I think the most elegant way I could. With this solution, the only things you need to do in your layouts are:
add an additional xmlns declaration
change your TextViews source text namespace from android to your new namespace
replace your TextViews with x.y.z.JustifiedTextView
Here's the code. Works perfectly fine on my phones (Galaxy Nexus Android 4.0.2, Galaxy Teos Android 2.1). Feel free, of course, to replace my package name with yours.
/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;
}
}
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);
}
}
We need to set the rendering to software in order to get transparent background on Android 3+. Hence the try-catch for older versions of Android.
Hope this helps!
PS: please not that it might be useful to add this to your whole activity on Android 3+ in order to get the expected behavior: android:hardwareAccelerated="false"
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);
There is a CustomView for this problem, this custom text view is support Justified Text View.
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;
}
}
}
Add above class to your src folder and use this sample code to add to your layout:
JustifiedTextView jtv= new JustifiedTextView(getApplicationContext(), "Lorem ipsum dolor sit amet... ");
LinearLayout place = (LinearLayout) findViewById(R.id.book_profile_content);
place.addView(jtv);
Android does not yet support full justification. We can use Webview and justify HTML instead of using textview. It works so fine. If you guys not clear, feel free to ask me :)
You can use justificationMode as inter_word in xml. You have to remember that this attribute is available for api level 26 and higher. For that you can assign targetApi as o. The full code is given bellow
发布评论
评论(23)
我不相信 Android 支持完全合理。
更新 2018-01-01:Android 8.0+ 支持 带有
TextView
的对齐模式< /a>.I do not believe Android supports full justification.
UPDATE 2018-01-01: Android 8.0+ supports justification modes with
TextView
.Android O 中的
TextView
本身提供了完整的理由(新的排版对齐方式)。您只需执行以下操作:
Kotlin
Java
XML
默认为
JUSTIFICATION_MODE_NONE
(none
在 XML 中)。TextView
in Android O offers full justification (new typographic alignment) itself.You just need to do this:
Kotlin
Java
XML
Default is
JUSTIFICATION_MODE_NONE
(none
in xml).@CommonsWare 的答案是正确的。 Android 8.0+ 确实支持“完全合理化”(或简称为“合理化”,因为它有时被含糊地提及)。
Android 还支持“左/右文本对齐”。 有关区别,请参阅关于理由的维基百科文章。 许多人认为“对齐”的概念包含完全对齐以及左/右文本对齐,这就是他们想要进行左/右文本对齐时最终搜索的内容。 这个答案解释了如何实现左/右文本对齐。
可以实现左/右文本对齐(与问题所询问的完全对齐相反)。 为了进行演示,我将使用基本的 2 列表单(左列中的标签和右列中的文本字段)作为示例。 在此示例中,左列标签中的文本将右对齐,以便它们与右列中的文本字段齐平。
在 XML 布局中,您可以通过在所有 TextView 中添加以下属性来使 TextView 元素本身(左列)向右对齐:
但是,如果文本换行为多行,则文本仍将左对齐在 TextView 内部。 添加以下属性使 TextView 内的实际文本右对齐(左对齐):
因此 gravity 属性指定如何对齐 TextView 内的文本 layout_gravity 指定如何对齐对齐/布局 TextView 元素本身。
The @CommonsWare answer is correct. Android 8.0+ does support "Full Justification" (or simply "Justification", as it is sometimes ambiguously referred to).
Android also supports "Flush Left/Right Text Alignment". See the wikipedia article on Justification for the distinction. Many people consider the concept of 'justification' to encompass full-justification as well as left/right text alignment, which is what they end up searching for when they want to do left/right text alignment. This answer explains how to achieve the left/right text alignment.
It is possible to achieve Flush Left/Right Text Alignment (as opposed to Full Justification, as the question is asking about). To demonstrate I will be using a basic 2-column form (labels in the left column and text fields in the right column) as an example. In this example the text in the labels in the left column will be right-aligned so they appear flush up against their text fields in the right column.
In the XML layout you can get the TextView elements themselves (the left column) to align to the right by adding the following attribute inside all of the TextViews:
However, if the text wraps to multiple lines, the text would still be flush left aligned inside the TextView. Adding the following attribute makes the actual text flush right aligned (ragged left) inside the TextView:
So the gravity attribute specifies how to align the text inside the TextView layout_gravity specifies how to align/layout the TextView element itself.
为了在 android 中对齐文本,我使用了 WebView
和 html。
我还无法上传图像来证明这一点,但“它对我有用”。
To justify text in android I used WebView
and html.
I can't yet upload images to prove it but "it works for me".
更新
我们为此创建了一个简单的类。 目前有两种方法可以实现您的需求。 两者都需要无WEBVIEW和支持SPANNABLES。
库:https://github.com/bluejamesbond/TextJustify-Android
支持:Android 2.0 至 5.X
设置
屏幕截图
UPDATED
We have created a simple class for this. There are currently two methods to achieve what you are looking for. Both require NO WEBVIEW and SUPPORTS SPANNABLES.
LIBRARY: https://github.com/bluejamesbond/TextJustify-Android
SUPPORTS: Android 2.0 to 5.X
SETUP
SCREENSHOT
您可以使用 github 中的 JustifiedTextView for Android 项目。 这是一个自定义视图,可以为您模拟对齐文本。 它支持 Android 2.0+ 和从右到左的语言。
You can use JustifiedTextView for Android project in github. this is a custom view that simulate justified text for you. It support Android 2.0+ and right to left languages.
我基于本机文本视图编写了一个小部件来做到这一点。
github
I write a widget base on native textview to do it.
github
我找到了解决这个问题的方法,不过这个可能不是很优雅,但是效果还不错。
其原理是将每行的空格替换为固定宽度的ImageSpan(颜色透明)。
我把代码放到了GitHub上:
https://github.com/twiceyuan/TextJustification
概述:
I found a way to solve this problem, but this may not be very grace, but the effect is not bad.
Its principle is to replace the spaces of each line to the fixed-width ImageSpan (the color is transparent).
I put the code on GitHub:
https://github.com/twiceyuan/TextJustification
Overview:
很简单
我们可以在 xml 文件中做到这一点
Very Simple
We can do that in the xml file
XML 布局:声明 WebView 而不是 TextView
Java 代码:将文本数据设置为 WebView
这可能会解决您的问题。
它完全适合我。
XML Layout: declare WebView instead of TextView
Java code: set text data to WebView
This may Solve your problem.
Its Fully worked for me.
这就是我的做法,我认为这是我能做到的最优雅的方式。 使用此解决方案,您在布局中唯一需要做的事情是:
xmlns
声明TextView
的源文本命名空间从 android 更改为新的命名空间TextView
与xyzJustifiedTextView
这是代码。 在我的手机(Galaxy Nexus Android 4.0.2、Galaxy Teos Android 2.1)上运行得非常好。 当然,请随意将我的包名称替换为您的包名称。
/assets/justified_textview.css:/res/values/attrs.xml:/res/layout/test.xml:/
src/net/bicou/myapp/widget/JustifiedTextView.java:
我们需要将渲染设置为软件,以便在 Android 3+ 上获得透明背景。 因此,旧版本的 Android 需要 try-catch。
希望这可以帮助!
PS:请注意,将其添加到 Android 3+ 上的整个 Activity 中可能会很有用,以获得预期的行为:
android:hardwareAccelerated="false"
Here's how I did it, I think the most elegant way I could. With this solution, the only things you need to do in your layouts are:
xmlns
declarationTextView
s source text namespace from android to your new namespaceTextView
s withx.y.z.JustifiedTextView
Here's the code. Works perfectly fine on my phones (Galaxy Nexus Android 4.0.2, Galaxy Teos Android 2.1). Feel free, of course, to replace my package name with yours.
/assets/justified_textview.css:
/res/values/attrs.xml:
/res/layout/test.xml:
/src/net/bicou/myapp/widget/JustifiedTextView.java:
We need to set the rendering to software in order to get transparent background on Android 3+. Hence the try-catch for older versions of Android.
Hope this helps!
PS: please not that it might be useful to add this to your whole activity on Android 3+ in order to get the expected behavior:
android:hardwareAccelerated="false"
虽然仍未完成对齐文本,但从 API 23 开始,您现在可以使用
android:breakStrategy="balanced"
来平衡行长度http://developer.android.com/reference/android/widget/TextView.html#attr_android:breakStrategy
While still not complete justified text, you can now balance line lengths using
android:breakStrategy="balanced"
from API 23 onwardshttp://developer.android.com/reference/android/widget/TextView.html#attr_android:breakStrategy
我写了自己的类来解决这个问题,这就是
只是你必须调用带有两个参数的静态对齐函数
//MainActivity
//TextJustificationClass
//XML
I write my own class to solve this problem, Here it is
Just you have to call the static justify function that takes two arguments
//MainActivity
//TextJustificationClass
//XML
FILL_HORIZONTAL
相当于CENTER_HORIZONTAL
。你可以在textview的源代码中看到这段代码:
FILL_HORIZONTAL
is equivalent toCENTER_HORIZONTAL
.You can see this code snippet in textview's source code:
有一个CustomView可以解决这个问题,这个自定义文本视图是支持Justified Text View的。
抢劫一下: JustifiedTextView
将上述类添加到您的 src 文件夹并使用此示例代码添加到您的布局:
There is a CustomView for this problem, this custom text view is support Justified Text View.
Loot at this: JustifiedTextView
Add above class to your src folder and use this sample code to add to your layout:
请参阅此处 在 github 中
只需导入两个文件“TextJustifyUtils.java”和“TextViewEx.java”即可。 java”在你的项目中。
现在
,如果您使用普通的文本视图,例如:
只需使用
定义变量并将 justify 设置为 true,
see here in the github
Just import the two files "TextJustifyUtils.java" and "TextViewEx.java" in your project.
and
Now, if you use normal textView like:
Simply use
Define a variable and set justify to be true,
我认为有两种选择:
使用 Pango 之类的东西,通过 NDK 专门处理此问题,并将文本渲染到 OpenGL 或其他表面。
使用
使用 Paint.measureText() 和朋友获取单词的长度,并在自定义视图中手动将它们布局在画布上。
I think there are two options:
Use something like Pango that specializes in this via the NDK and render text to an OpenGL or other surface.
Use Paint.measureText() and friends to get the lengths of words and lay them out manually on a Canvas in a custom view.
Android 尚不支持完整的理由。 我们可以使用 Webview 并调整 HTML,而不是使用 textview。 它工作得很好。 如果大家不清楚的话可以问我:)
Android does not yet support full justification. We can use Webview and justify HTML instead of using textview. It works so fine. If you guys not clear, feel free to ask me :)
只需在 xml 文件中使用此属性即可
Just use this property in xml file
Simplay我们可以使用android:justificationMode="inter_word"
Simplay we can use android:justificationMode="inter_word"
您可以使用 justificationMode 作为 xml 中的 inter_word。 您必须记住,此属性适用于 api 级别 26 及更高级别。 为此,您可以将 targetApi 指定为 o。 完整代码如下
You can use justificationMode as inter_word in xml. You have to remember that this attribute is available for api level 26 and higher. For that you can assign targetApi as o. The full code is given bellow
请在 8.0 以下尝试此代码
Please try this code for below 8.0
对于 Compose
用法:
TextAlign.Justify
For Compose
usage :
TextAlign.Justify