Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
205 views
in Technique[技术] by (71.8m points)

Justify text in an Android app using a WebView but presenting a TextView-like interface?

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:

 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.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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.

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).

The result is the following:

enter image description here

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:

 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):

enter image description here

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.

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();
    }
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...