How to prevent EditText from breaking a line after

2019-01-24 17:07发布

问题:

As default, an Android EditText will break a line if the line is longer than the view, like this:

Thisisalineanditisveryverylongs (end of view)
othisisanotherline

or if the line contains a punctuation character, like this:

Thisisalineanditsnotsolong;     (several characters from the end of view)
butthisisanotherline

As a requirement of my work, the text has to break a line only if the line is longer than the view, like this:

Thisisalineanditsnotsolong;andt (end of view)
hisisanotherline

There must be a way to achieve this, am I right? So far I haven't found anyway to do this.

回答1:

The way TextView (and EditText) breaks the text is through private function calls to BoringLayout internally. So, the best way would be to sublcass EditText and rewrite these functions. But it will not be a trivial task.

So, in the TextView class there are creations of different classes for text style. The one we look is DynamicLayout. In this class we reach to a reference of the class StaticLayout (in a variable called reflowed). In the constructor of this class you will find the text wrap algorithm:

/*
* From the Unicode Line Breaking Algorithm:
* (at least approximately)
*  
* .,:; are class IS: breakpoints
*      except when adjacent to digits
* /    is class SY: a breakpoint
*      except when followed by a digit.
* -    is class HY: a breakpoint
*      except when followed by a digit.
*
* Ideographs are class ID: breakpoints when adjacent,
* except for NS (non-starters), which can be broken
* after but not before.
*/

if (c == ' ' || c == '\t' ||
((c == '.'  || c == ',' || c == ':' || c == ';') &&
(j - 1 < here || !Character.isDigit(chs[j - 1 - start])) &&
(j + 1 >= next || !Character.isDigit(chs[j + 1 - start]))) ||
((c == '/' || c == '-') &&
(j + 1 >= next || !Character.isDigit(chs[j + 1 - start]))) ||
(c >= FIRST_CJK && isIdeographic(c, true) &&
j + 1 < next && isIdeographic(chs[j + 1 - start], false))) {
okwidth = w;
ok = j + 1;

Here's where all the wrapping goes. So you will need to subclass take care for StaticLayout, DynamicLayout, TextView and finally EditText which - I am sure - will be a nightmare :( I am not even sure how all the flow goes. If you want - take a look at TextView first and check for getLinesCount calls - this will be the starting point.



回答2:

This Line Breaking algorithm in Android really sucks, it isn't even logically correct - a comma can not be the last character of a line. it only produces unnecessary line breaks, which results in extremely weird text layout.



回答3:

Hi Here is one method I first get from another guy and then make a little bit changes, it really works for me you can have a try.

//half ASCII transfer to full ASCII
public static String ToSBC(String input) { 
    char[] c = input.toCharArray(); 
    for (int i = 0; i< c.length; i++) { 
    if (c[i] == 32) { 
    c[i] = (char) 12288; 
    continue; 
    } 
    if (c[i]<=47 && c[i]>32 ) 
    c[i] = (char) (c[i] + 65248); 
    } 
    return new String(c); 
    }
}

here it is. I change some special characters from half corner to full corner, such as "," ".", and the effect is pretty good. You can have try.