因此,正如大多数人所知,Android中的TextView内部没有文本证明。所以,我构建了一个自定义TextView来解决问题。但是,出于某种原因,有时标点符号会因某些原因在某些设备中断线。我测试了LG G3和模拟器(运行最新版本的Nexus 4)和逗号",#34;例如,打破了LG G3上的理由,但没有打破模拟器上的理由。
如果我添加至少为2的填充开始和结束(或左右),问题就解决了。这看起来非常武断。
基本上,我的逻辑是,为了证明文本的合理性,我需要知道TextView本身的宽度,将文本构造成最大长度的行。然后,通过查找行中的空格数和剩余的空白空间,拉伸" " (空格)根据剩余像素(或视图中的空间)缩放的字符。
它几乎完美地工作,并且大多数时候它也支持RTL文本。
这里有一些文本图片(一个简单的lorem impsum)有和没有违规标记(第一个是在模拟器nexus 4上运行7.1.1,第二个在LG G3上运行v5.0)
以下是代码:
public class DTextView extends AppCompatTextView {
private boolean justify;
public DTextView(Context context) {
super(context);
}
public DTextView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
init(attrs);
}
public DTextView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(attrs);
}
private void setJustify(boolean justify) {
this.justify = justify;
if (justify) {
justify();
}
}
private void init(@Nullable AttributeSet attrs) {
TypedArray ta = getContext().obtainStyledAttributes(attrs, R.styleable.DTextView, 0, 0);
justify = ta.getBoolean(R.styleable.DTextView_justify, false);
ta.recycle();
}
private SpannableStringBuilder justifyText() {
String[] words = getText().toString().split(" ");
setText("");
int maxLineWidth = getWidth() - getPaddingLeft() - getPaddingRight();
SpannableStringBuilder justifiedTextSpannable = new SpannableStringBuilder();
//This will build the new text with the lines rearranged so that they will have a width
//bigger than the View's own width
ArrayList<String> lines = new ArrayList<>(0);
String line = "";
for (String word : words) {
if (getWordWidth(line + word) < maxLineWidth) {
line += word + " ";
} else {
line = line.substring(0, line.length() - 1);
lines.add(line);
line = word + " ";
}
}
//Add the last line
lines.add(line);
for (int i = 0; i < lines.size() - 1; i++) {
justifiedTextSpannable.append(justifyLine(lines.get(i), maxLineWidth));
justifiedTextSpannable.append("\n");
}
justifiedTextSpannable.append(lines.get(lines.size() - 1));
return justifiedTextSpannable;
}
private SpannableString justifyLine(String line, float maxWidth) {
SpannableString sLine = new SpannableString(line);
float spaces = line.split(" ").length - 1;
float spaceCharSize = getWordWidth(" ");
float emptySpace = maxWidth - getWordWidth(line);
float newSpaceSize = (emptySpace / spaces) + spaceCharSize;
float scaleX = newSpaceSize / spaceCharSize;
for (int i = 0; i < line.length(); i++) {
if (line.charAt(i) == ' ') {
sLine.setSpan(new ScaleXSpan(scaleX), i, i + 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
}
}
return sLine;
}
private void justify() {
justify = false;
setText(justifyText());
invalidate();
}
private float getWordWidth(String word) {
return getPaint().measureText(word);
}
@Override
protected void onDraw(Canvas canvas) {
if (!justify)
super.onDraw(canvas);
else
justify();
}
}
我非常感谢能够对此有所了解的任何人。
答案 0 :(得分:2)
所以,在看了一下这个:https://github.com/ufo22940268/android-justifiedtextview和TextView之后,我发现我的主要问题是我的方法。
使用缩放“”字符宽度的方法在理论上是合理的,但在这样做之后,线条的宽度再次改变,因为线条的宽度似乎不是其各部分的总和。
我已经改变了我的方法并从上面的链接中获取灵感,因此在我的新方法中,我自己绘制每个角色,而不是画出整条线。如果文本需要被证明(基于自定义的“justify”布尔属性),那么它将绘制线并对其进行对齐,否则它将只绘制线。
编辑:我现在更改了代码,因此它也支持RTL文本。我将在接下来的几天内上传代码。
以下是代码:
public class DTextView extends AppCompatTextView {
private boolean justify;
private float textAreaWidth;
private float spaceCharSize;
private float lineY;
public DTextView(Context context) {
super(context);
}
public DTextView(Context context, AttributeSet attrs) {
super(context, attrs);
init(attrs);
}
public DTextView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(attrs);
}
/**
* @param attrs the attributes from the xml
* This function loads all the parameters from the xml
*/
private void init(AttributeSet attrs) {
TypedArray ta = getContext().obtainStyledAttributes(attrs, R.styleable.DTextView, 0, 0);
justify = ta.getBoolean(R.styleable.DTextView_justify, false);
ta.recycle();
}
@Override
protected void onDraw(Canvas canvas) {
drawText(canvas);
}
private void drawText(Canvas canvas) {
TextPaint paint = getPaint();
paint.setColor(getCurrentTextColor());
paint.drawableState = getDrawableState();
textAreaWidth = getMeasuredWidth() - (getPaddingLeft() + getPaddingRight());
spaceCharSize = paint.measureText(" ");
String text = getText().toString();
lineY = getTextSize();
Layout textLayout = getLayout();
if (textLayout == null)
return;
Paint.FontMetrics fm = paint.getFontMetrics();
int textHeight = (int) Math.ceil(fm.descent - fm.ascent);
textHeight = (int) (textHeight * getLineSpacingMultiplier() + textLayout.getSpacingAdd());
for (int i = 0; i < textLayout.getLineCount(); i++) {
int lineStart = textLayout.getLineStart(i);
int lineEnd = textLayout.getLineEnd(i);
float lineWidth = StaticLayout.getDesiredWidth(text, lineStart, lineEnd, paint);
String line = text.substring(lineStart, lineEnd);
if (line.charAt(line.length() - 1) == ' ') {
line = line.substring(0, line.length() - 1);
}
if (justify && i < textLayout.getLineCount() - 1) {
drawLineJustified(canvas, line, lineWidth);
} else {
canvas.drawText(line, 0, lineY, paint);
}
lineY += textHeight;
}
}
private void drawLineJustified(Canvas canvas, String line, float lineWidth) {
TextPaint paint = getPaint();
float emptySpace = textAreaWidth - lineWidth;
int spaces = line.split(" ").length - 1;
float newSpaceSize = (emptySpace / spaces) + spaceCharSize;
float charX = 0;
for (int i = 0; i < line.length(); i++) {
String character = String.valueOf(line.charAt(i));
float charWidth = StaticLayout.getDesiredWidth(character, paint);
if (!character.equals(" ")) {
canvas.drawText(character, charX, lineY, paint);
}
if (character.equals(" ") && i != line.length() - 1)
charX += newSpaceSize;
else
charX += charWidth;
}
}
}
和XML:
<il.co.drapp.views.text.DTextView
android:layout_width="match_parent"
android:inputType="textMultiLine|textNoSuggestions"
app:justify="true"
android:id="@+id/justifyText"
android:text="@string/article_dummy_text"
android:layout_height="wrap_content" />
感谢Aditya Vyas-Lakhan的链接
答案 1 :(得分:0)
答案 2 :(得分:0)
尝试这种方式来证明文本,它适用于我
public class MainActivity extends Activity {
private JustifiedTextView mJTv;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mJTv=(JustifiedTextView) findViewById(R.id.activity_main_jtv_text);
mJTv.setText(getResources().getString(R.string.test));
mJTv.setTextSize(TypedValue.COMPLEX_UNIT_SP,20);
mJTv.setLineSpacing(15);
mJTv.setBackgroundColor(Color.RED);
mJTv.setAlignment(Align.LEFT);
mJTv.setTypeFace(Typeface.createFromAsset(getAssets(), "fonts/naskh_bold.ttf"));
}
}
XML
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main_jsv"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<ir.noghteh.JustifiedTextView
android:id="@+id/activity_main_jtv_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="right"
android:padding="25dp"
xmlns:noghteh="http://noghteh.ir"
noghteh:text="@string/hello_world"
noghteh:textColor="@color/text"
noghteh:textSize="18sp"
>
</ir.noghteh.JustifiedTextView>
</ScrollView>
https://github.com/navabi/JustifiedTextView
答案 3 :(得分:0)
就像波纹管一样使用者
awk '
{
line=""
while(match($0,/65510[^i]*/)){
val=substr($0,RSTART,RLENGTH+1)
gsub(/,/,"_",val)
line=(line?line:"")substr($0,1,RSTART-1) val
$0=substr($0,RSTART+RLENGTH+1)
}
if($0!=""){
line=line $0
}
print line
}
' Input_file