WebView
のテキストを正当化するためにTextView
を使用していることを忘れる簡単な方法を探しています。誰かがこれについてカスタムビューを作成しましたか?私は次のようなことができることをよく知っています:
WebView view = new WebView(this);
view.loadData("my html with text justification","text/html","utf-8");
ただし、TextView
のサイズ、色、またはその他の一般的なプロパティを設定する場合は、見苦しくなります。それを行うためのより便利な方法がなければなりません。
Webviewソリューションがない場合: https://github.com/merterhk/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;
}
}
}
それは私の神経質になっていた、私はそれを認めます。コード内でTextViews
がTextViews
のように見えるのが好きです。また、text-align:justifiedフォーマットを実現する手段としてWebView
を使用している場合でも、そのように見たくない。
TextView
から一般的に使用するメソッドを実装し、それらの変更を反映するためにWebViewのコンテンツを変更するカスタムビュー(醜い、おそらく悪い)を作成しました。それが他の誰かにとって有用であるか、私が本当に知らない潜在的な危険であるかどうか、私にとってそれは機能します、私はそれをいくつかのプロジェクトで使用しました、そして何の問題にも遭遇しませんでした。唯一の小さな不便は、メモリ的にはより大きな料金であると想定していることですが、それが1つか2つしかない場合は心配する必要はありません(間違っている場合は訂正してください)。
結果は次のとおりです。
そしてそれをプログラムで設定するためのコードはこれと同じくらい簡単です:
JustifiedTextView J = new JustifiedTextView();
J.setText("insert your text here");
もちろん、そのままにしておくのはばかげているので、基本的にTextViewsを使用するフォントサイズとフォントカラーを変更するメソッドも追加しました。意味私はこのようなことをすることができます:
JustifiedTextView J = new JustifiedTextView();
J.setText("insert your text here");
J.setTextColor(Color.RED);
J.setTextSize(30);
そして、次の結果を取得します(画像はトリミングされます):
しかし、これはそれがどのように見えるかを示すためではなく、あなたがそれをどのように行ったかを共有するためです!
分かってる。これが完全なコードです。また、透明な背景を設定し、UTF-8文字列をビューにロードする際の問題にも対処します。詳細については、reloadData()のコメントを参照してください。
public class JustifiedTextView extends WebView{
private String core = "<html><body style='text-align:justify;color:rgba(%s);font-size:%dpx;margin: 0px 0px 0px 0px;'>%s</body></html>";
private String textColor = "0,0,0,255";
private String text = "";
private int textSize = 12;
private int backgroundColor=Color.TRANSPARENT;
public JustifiedTextView(Context context, AttributeSet attrs) {
super(context, attrs);
this.setWebChromeClient(new WebChromeClient(){});
}
public void setText(String s){
this.text = s;
reloadData();
}
@SuppressLint("NewApi")
private void reloadData(){
// loadData(...) has a bug showing utf-8 correctly. That's why we need to set it first.
this.getSettings().setDefaultTextEncodingName("utf-8");
this.loadData(String.format(core,textColor,textSize,text), "text/html","utf-8");
// set WebView's background color *after* data was loaded.
super.setBackgroundColor(backgroundColor);
// Hardware rendering breaks background color to work as expected.
// Need to use software renderer in that case.
if(Android.os.Build.VERSION.SDK_INT >= 11)
this.setLayerType(WebView.LAYER_TYPE_SOFTWARE, null);
}
public void setTextColor(int hex){
String h = Integer.toHexString(hex);
int a = Integer.parseInt(h.substring(0, 2),16);
int r = Integer.parseInt(h.substring(2, 4),16);
int g = Integer.parseInt(h.substring(4, 6),16);
int b = Integer.parseInt(h.substring(6, 8),16);
textColor = String.format("%d,%d,%d,%d", r, g, b, a);
reloadData();
}
public void setBackgroundColor(int hex){
backgroundColor = hex;
reloadData();
}
public void setTextSize(int textSize){
this.textSize = textSize;
reloadData();
}
}
たった3つのステップで、Webビューのテキストを正当化できます。
1)
// Justify tag
String justifyTag = "<html><body style='text-align:justify;'>%s</body></html>";
2)
// Concatenate your string with the tag to Justify it
String dataString = String.format(Locale.US, justifyTag, "my html with text justification");
)
// Load the data in the web view
webView.loadDataWithBaseURL("", dataString, "text/html", "UTF-8", "");
これは、Juanによって提供された(そして私が編集した)JustifiedTextViewクラスと同じですが、レイアウトxmlファイルで使用できるカスタムxml属性で機能するように拡張されています。 Eclipseレイアウトエディターでさえ、カスタム属性を属性テーブルに表示します。これはすばらしいことです。あなたが物事をきれいに保ちたい、そしてxml属性を必要としない場合に備えて、私はこれを追加の答えに入れました。
public class JustifiedTextView extends WebView{
private String core = "<html><body style='text-align:justify;color:rgba(%s);font-size:%dpx;margin: 0px 0px 0px 0px;'>%s</body></html>";
private String text;
private int textColor;
private int backgroundColor;
private int textSize;
public JustifiedTextView(Context context, AttributeSet attrs) {
super(context, attrs);
init(attrs);
}
public JustifiedTextView(Context context, AttributeSet attrs, int i) {
super(context, attrs, i);
init(attrs);
}
@SuppressLint("NewApi")
public JustifiedTextView(Context context, AttributeSet attrs, int i, boolean b) {
super(context, attrs, i, b);
init(attrs);
}
private void init(AttributeSet attrs) {
TypedArray a=getContext().obtainStyledAttributes(
attrs,
R.styleable.JustifiedTextView);
text = a.getString(R.styleable.JustifiedTextView_text);
if(text==null) text="";
textColor = a.getColor(R.styleable.JustifiedTextView_textColor, Color.BLACK);
backgroundColor = a.getColor(R.styleable.JustifiedTextView_backgroundColor, Color.TRANSPARENT);
textSize = a.getInt(R.styleable.JustifiedTextView_textSize, 12);
a.recycle();
this.setWebChromeClient(new WebChromeClient(){});
reloadData();
}
public void setText(String s){
if(s==null)
this.text="";
else
this.text = s;
reloadData();
}
@SuppressLint("NewApi")
private void reloadData(){
if(text!=null) {
String data = String.format(core,toRgba(textColor),textSize,text);
Log.d("test", data);
this.loadDataWithBaseURL(null, data, "text/html","utf-8", null);
}
// set WebView's background color *after* data was loaded.
super.setBackgroundColor(backgroundColor);
// Hardware rendering breaks background color to work as expected.
// Need to use software renderer in that case.
if(Android.os.Build.VERSION.SDK_INT >= 11)
this.setLayerType(WebView.LAYER_TYPE_SOFTWARE, null);
}
public void setTextColor(int hex){
textColor = hex;
reloadData();
}
public void setBackgroundColor(int hex){
backgroundColor = hex;
reloadData();
}
public void setTextSize(int textSize){
this.textSize = textSize;
reloadData();
}
private String toRgba(int hex) {
String h = Integer.toHexString(hex);
int a = Integer.parseInt(h.substring(0, 2),16);
int r = Integer.parseInt(h.substring(2, 4),16);
int g = Integer.parseInt(h.substring(4, 6),16);
int b = Integer.parseInt(h.substring(6, 8),16);
return String.format("%d,%d,%d,%d", r, g, b, a);
}
}
これをjustified_text_view_attr.xmlとしてres/values /フォルダーに追加するか、既存のattrs.xmlにマージします。
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="JustifiedTextView">
<attr name="text" format="string" localization="suggested"/>
<attr name="textColor" format="color|reference" />
<attr name="backgroundColor" format="color|reference" />
<attr name="textSize" format="integer" min="1" />
</declare-styleable>
</resources>
バグを見つけたら、自由に編集してください。
私はこの最も単純な形を信じています。そして私は完璧に働きました
package domo.suichbt.util;
import Android.content.Context;
import Android.text.Html;
import Android.util.AttributeSet;
import Android.widget.TextView;
public class JustifiedTextView extends TextView
{
private final String CORE_TEMPLATE = "<html><body style='text-
align:justify;margin: 0px 0px 0px 0px;'>%s</body></html>";
public JustifiedTextView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
setText(Html.fromHtml(String.format(CORE_TEMPLATE,getText())));
}
public JustifiedTextView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
setText(Html.fromHtml(String.format(CORE_TEMPLATE,getText())));
}
public JustifiedTextView(Context context) {
super(context);
setText(Html.fromHtml(String.format(CORE_TEMPLATE,getText())));
}
public JustifiedTextView(Context context, AttributeSet attrs) {
super(context, attrs);
setText(Html.fromHtml(String.format(CORE_TEMPLATE,getText())));
}
}
Xmlの例を挿入
<domo.suichbt.util.JustifiedTextView
Android:layout_width="match_parent"
Android:layout_height="wrap_content"
Android:text="@string/sw_titulo"
Android:singleLine="false">
</domo.suichbt.util.JustifiedTextView>
このリンクを見てください。これは、WebViewを使用して、AndroidのCheckBoxのテキストを完全に正当化します。各チェックボックスは実際にはTextViewとボタンであるため、TextViewでもまったく同じように使用できます。 http://www.collegemobile.com/2014/09/justify-text-Android-checkbox/