使用 WebView 对齐 Android 应用程序中的文本但呈现类似 TextView 的界面?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/11922861/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Justify text in an Android app using a WebView but presenting a TextView-like interface?
提问by Juan Cortés
I'm looking for a simple way to forget that I'm using a WebView
to have justified text in my TextView
. Has someone made a custom view for this? I'm well aware that I can do something like this:
我正在寻找一种简单的方法来忘记我正在使用 aWebView
在我的TextView
. 有人为此制作了自定义视图吗?我很清楚我可以做这样的事情:
WebView view = new WebView(this);
view.loadData("my html with text justification","text/html","utf-8");
But it gets ugly when you want to set the size, the color or other common properties of the TextView
. There must be a more convenient way of doing it.
但是当你想设置TextView
. 必须有更方便的方法来做到这一点。
回答by Juan Cortés
It was getting on my nerves, I admit it. I like the TextViews
to look like TextViews
in the code, and even if I'm using a WebView
as the means of achieving the text-align:justified formatting, I don't want to look at it that way.
这让我很紧张,我承认。我喜欢代码中的TextViews
to TextViews
,即使我使用 aWebView
作为实现 text-align:justified 格式的方法,我也不想那样看。
I created a custom view (ugly, probably bad) that implements the methods that I commonly use from the TextView
and modifies the content of the WebView in order to reflect those changes.
Wether it's useful for someone else or a potential hazard I really don't know, for me it works, I've used it in several projects and haven't run into any issues. The only minor inconvenience is that I assume it as a bigger toll memory-wise but nothing to worry about if it's just one or two (correct me if I'm wrong).
我创建了一个自定义视图(丑陋,可能很糟糕),它实现了我常用的方法,TextView
并修改了 WebView 的内容以反映这些更改。无论它对其他人有用还是潜在危险我真的不知道,对我来说它有效,我已经在几个项目中使用了它并且没有遇到任何问题。唯一的小不便是我认为它是一个更大的记忆力,但如果它只是一两个,则无需担心(如果我错了,请纠正我)。
The result is the following:
结果如下:
And the code for setting it programmatically is as simple as this:
以编程方式设置它的代码就像这样简单:
JustifiedTextView J = new JustifiedTextView();
J.setText("insert your text here");
Of course it'd be stupid to leave it like that so I also added the methods for changing the font-size and the font-color which are basically all I use TextViews for. Meaning I can do something like this:
当然,这样留下它是愚蠢的,所以我还添加了更改字体大小和字体颜色的方法,这些方法基本上都是我使用 TextViews 的。这意味着我可以做这样的事情:
JustifiedTextView J = new JustifiedTextView();
J.setText("insert your text here");
J.setTextColor(Color.RED);
J.setTextSize(30);
And obtain the following result (images are cropped):
并获得以下结果(图像被裁剪):
But, this is not to show us how it looks, it's to share how you've done it!
但是,这不是要向我们展示它的外观,而是要分享您是如何做到的!
I know, I know. Here's the full code. It also addresses Problems when setting transparent background and loading UTF-8 strings into the view. See the comments in reloadData() for details.
我知道我知道。这是完整的代码。它还解决了设置透明背景和将 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();
}
}
回答by Merter
Without webview solution is : https://github.com/merterhk/JustifiedTextView
没有 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;
}
}
}
回答by Srikar Reddy
In just three steps, you can justify your web view text.
只需三个步骤,您就可以调整您的 Web 视图文本。
1)
1)
// Justify tag
String justifyTag = "<html><body style='text-align:justify;'>%s</body></html>";
2)
2)
// Concatenate your string with the tag to Justify it
String dataString = String.format(Locale.US, justifyTag, "my html with text justification");
3)
3)
// Load the data in the web view
webView.loadDataWithBaseURL("", dataString, "text/html", "UTF-8", "");
回答by sulai
This is the same JustifiedTextView class given by Juan (and edited by me), but extended to work with custom xml attributes you can use in your layout xml files. Even Eclipse layout editor will show your custom attributes in the attribute table, which is cool. I put this into an additional answer, in case you want to keep things clean and don't need xml attributes.
这与 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);
}
}
Either add this as justified_text_view_attr.xmlinto your res/values/ folder, or merge it into your existing attrs.xml:
将此作为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>
Feel free to edit if you find any bugs.
如果您发现任何错误,请随时进行编辑。
回答by Ronald
I believe this simplest form. And I worked perfectly
我相信这个最简单的形式。我工作得很好
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())));
}
}
Insert xml example
插入 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>
回答by Amin Tavassolian
Take a look at this link. It uses a WebView to be bale to fully justify the text of a CheckBox in Android. It also can be used exactly the same in TextView, since each CheckBox is in fact a TextView and a Button. http://www.collegemobile.com/2014/09/justify-text-android-checkbox/
看看这个链接。它使用一个 WebView 来完全对齐 Android 中 CheckBox 的文本。它也可以在 TextView 中使用完全相同,因为每个 CheckBox 实际上是一个 TextView 和一个 Button。 http://www.collegemobile.com/2014/09/justify-text-android-checkbox/