Prevent Android's TextView from breaking links

一个人想着一个人 提交于 2021-02-07 13:18:23

问题


This question is probably the same as this one, but since none of its answers really solve the problem, I'll ask again.

My app has a TextView that occasionally will display very long URLs. For aesthetic reasons (and since the URLs contain no spaces), the desirable behaviour would be to fill each line completely before jumping to the next one, something like this:

|http://www.domain.com/som|
|ething/otherthing/foobar/|
|helloworld               |

What happens instead, is the URL being broke near the bars, as if they were spaces.

|http://www.domain.com/   |
|something/otherthing/    |
|foobar/helloworld        |

I tried extending the TextView class and adding a modified version of the breakManually method (found here) to trick the TextView and do what I need, calling it on onSizeChanged (overridden). It works fine, except for the fact that the TextView is inside a ListView. When this custom TextView is hidden by the scrolling and brought back, its content goes back to the original breaking behaviour, due to the view being re-drawn without onSizeChanged being called.

I was able to work-around this problem by calling breakManually inside onDraw. This presents the expected behaviour at all times, but at a high performance cost: since onDraw is called whenever the ListView is scrolled and the breakManually method isn't exactly "lightweight", the scrolling gets unacceptably laggy, even on a high-end quad-core device.

Next step was to crawl through the TextView source code, trying to figure where and how it splits the text, and hopefully override it. This was a complete failure. I (a newbie) spent the whole day fruitlessly looking at code I mostly couldn't understand.

And that brings me here. Can someone please point me the right direction about what I should override (assuming that it's possible)? Or maybe there is a simpler way of achieving what I want?

Here's the breakManually method I mentioned. Due to the use of getWidth(), it only works if called after the view is measured.

private CharSequence breakManually (CharSequence text) {
        int width = getWidth() - getPaddingLeft() - getPaddingRight();
        // Can't break with a width of 0.
        if (width == 0) return text;
        Editable editable = new SpannableStringBuilder(text);
        //creates an array with the width of each character
        float[] widths = new float[editable.length()];
        Paint p = getPaint();
        p.getTextWidths(editable.toString(), widths);
        float currentWidth = 0.0f;
        int position = 0;
        int insertCount = 0;
        int initialLength = editable.length();
        while (position < initialLength) {
            currentWidth += widths[position];
            char curChar = editable.charAt(position + insertCount);
            if (curChar == '\n') {
                currentWidth = 0.0f;
            } else if (currentWidth > width) {
                editable.insert(position + insertCount , "\n");
                insertCount++;
                currentWidth = widths[position];
            }
            position++;
        }
        return editable.toString();
    }

To everyone who bothered reading this, thanks for your time.


回答1:


If you're not using a monospace font, then in some cases it's not even possible to align it very well. Since you have no whitespaces in a URL, it's not likely that a Justify-like alignment will solve the problem. I suggest that you use a monospace font for that particular TextView. Then, decide on a fixed number of characters per line and break the string to display with "\n" after those many characters.

This isn't answering your question but it's the smoothest way possible, I guess.



来源:https://stackoverflow.com/questions/23622005/prevent-androids-textview-from-breaking-links

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!