Обоснуйте текст в приложении для Android с помощью WebView, но представляя интерфейс, подобный TextView?
Я ищу простой способ забыть, что я использую WebView
, чтобы иметь оправданный текст в моем TextView
. Может быть, кто-то сделал для этого собственный вид? Я хорошо знаю, что могу сделать что-то вроде этого:
WebView view = new WebView(this);
view.loadData("my html with text justification","text/html","utf-8");
Но это становится уродливым, когда вы хотите установить размер, цвет или другие общие свойства TextView
. Должен быть более удобный способ сделать это.6 ответов:
Признаюсь, это действовало мне на нервы. Мне нравится, когда
TextViews
выглядит какTextViews
в коде, и даже если я используюWebView
в качестве средства достижения выравнивания текста:оправданное форматирование, я не хочу смотреть на это таким образом.Я создал пользовательское представление (уродливое, возможно, плохое), которое реализует методы, которые я обычно использую из
TextView
, и изменяет содержимое веб-представления, чтобы отразить эти изменения. Является ли это полезным для кого-то еще или потенциальной опасностью, я действительно не знаю. знаете, для меня это работает, я использовал его в нескольких проектах и не сталкивался ни с какими проблемами. Единственное незначительное неудобство заключается в том, что я предполагаю, что это большая плата за память, но ничего страшного, если это только один или два (поправьте меня, если я ошибаюсь).Результат следующий:
И код для установки его программно так прост, как это:
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(); } }
Без 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; } } }
Всего за три шага вы можете обосновать текст веб-представления.
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");
3)
// Load the data in the web view webView.loadDataWithBaseURL("", dataString, "text/html", "UTF-8", "");
Это тот же класс 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. Он также может быть использован точно так же в TextView, так как каждый флажок фактически является TextView и кнопкой. http://www.collegemobile.com/2014/09/justify-text-android-checkbox/