どのようにしてTextView
のテキストを正当化することができますか(テキストが左右両側で同じ高さになるように)。
私は可能な解決策を見つけました ここ 、しかし(垂直中心をcenter_verticalに変更したとしても)うまくいかない。
私はAndroidが完全な正当化をサポートするとは思わない。
UPDATE 2018-01-01 :Android 8.0以降は 正当化モードをTextView
でサポートしています。
@ CommonsWareの答えは正しいです。 Androidは「完全な正当化」(または「あいまいさ」とも呼ばれます)をサポートしていません。
ただし、Androidは「Flush Left/Right Text Alignment」をサポートしています。区別については 正当化 に関するウィキペディアの記事を参照してください。多くの人は「正当化」の概念を完全な正当化と左右のテキストの位置合わせを含むと考えています。これが、左右のテキストの位置合わせをしたいときに求められることです。この回答では、左右のテキストの配置方法を説明しています。
(問題が質問しているので、完全な正当化とは対照的に)左/右のテキスト位置合わせをフラッシュすることが可能です。例として、基本的な2列形式(左側の列にラベル、右側の列にテキストフィールド)を使用します。この例では、左側の列のラベルのテキストは右寄せされ、右側の列のテキストフィールドと同じ高さに表示されます。
XMLレイアウトでは、すべてのTextViewの内側に次の属性を追加することで、TextView要素自体(左の列)を右揃えにすることができます。
<TextView
...
Android:layout_gravity="center_vertical|end">
...
</TextView>
ただし、テキストが複数行に折り返されている場合でも、テキストはTextView内で左寄せになります。次の属性を追加すると、実際のテキストはTextView内で右寄せ(左寄せ)になります。
<TextView
...
Android:gravity="end">
...
</TextView>
そのため、 gravity 属性は、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>
それを証明するために画像をアップロードすることはまだできませんが、「それは私のために機能します」。
このために簡単なクラスを作成しました。あなたが探しているものを達成するために現在2つの方法があります。両方とも NO WEBVIEW および SUPPORTS SPANNABLES を必要としません。
_ライブラリ_ : https://github.com/bluejamesbond/TextJustify-Android
_サポート_ :Android 2.0 to 5.X
_ setup _
// Please visit Github for latest setup instructions.
_スクリーンショット_
Android O
のTextView
は、それ自体が完全な正当化(新しい活字印刷の位置合わせ)を提供します。
あなたはただこれをする必要があります、
textView.setJustificationMode(JUSTIFICATION_MODE_INTER_Word);
デフォルトはJUSTIFICATION_MODE_NONE
です。
Githubで Android用JustifiedTextView プロジェクトを使用できます。これは、正当化されたテキストをシミュレートするカスタムビューです。それはアンドロイド2.0+と右から左への言語をサポートします。
私はそれを行うためにネイティブのテキストビューに基づいてウィジェットを書きます。
私はこの問題を解決する方法を見つけました、しかし、これは非常に優雅ではないかもしれません、しかし効果は悪くありません。
その原則は、各行のスペースを固定幅の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レイアウト: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");
これはあなたの問題を解決するかもしれません。その完全に私のために働いた。
これが私のやり方です、私は私ができる最もエレガントな方法だと思います。このソリューションでは、あなたのレイアウトでする必要がある唯一のことは以下のとおりです。
xmlns
宣言を追加するTextView
sソーステキストのネームスペースをAndroidから新しいネームスペースに変更します。TextView
sを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の古いバージョンのためのtry-catch。
お役に立てれば!
シモンズ:それは予想される動作を得るためにアンドロイド3+上のあなたの全体の活動にこれを追加することが有用かもしれないことをご了承ください:Android:hardwareAccelerated="false"
正当化されたテキストはまだ完成していませんが、API 23以降のAndroid:breakStrategy="balanced"
を使用して行の長さを調整できます。
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があり、このカスタムテキストビューはJustifiedテキストビューをサポートしています。
これで略奪: 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"の2つのファイルをインポートするだけです。
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);
下のリンクでこの解決策を試してみてください。プロジェクトフォルダにそのクラスを作成して使用してください。それは私のためにうまくいきます:)
WebViewを使用しながらTextViewのようなインターフェースを表示するAndroidアプリのテキストを正当化しますか。
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でコードを左にしたり正当化したりしようとすると、背景の幅は半分になります。
Androidはまだ完全な正当化をサポートしていません。テキストビューを使用する代わりに、Webビューを使用してHTMLを正当化することができます。それはとてもうまくいきます。あなたが明確でないならば、私に聞いてください:)
私は2つの選択肢があると思います:
NDKを介してこれに特化したPangoのようなものを使用し、テキストをOpenGLまたは他の表面にレンダリングします。
Paint.measureText() や友人を使用して単語の長さを取得し、それらをカスタムビューのキャンバスに手動でレイアウトします。
とても簡単XMLでできること
<TextView
Android:justificationMode="iter_Word"
/>
HTMLフォーマットの場合、Webkitを呼び出す必要はありません。仕事をするためにHtml.fromHtml(text)
を使用することができます。
ソース: http://developer.Android.com/guide/topics/resources/string-resource.html