[Android]TextView实现分散对齐(两端对齐)
TextView是个特别基础的Android控件,只要有文本基本就少不了它。但是最近在项目开发的过程中我发现TextView存在很多局限 性,其中最令我头疼的就是TextView文本排版方面的问题。我们都知道在word中文字对齐方式有靠左、靠右、居中、分散对齐等,但是 TextView中就偏偏没有分散对齐这个属性设置。这就导致了TextView中一段文字会出现右边参差不齐的问题,中文由于每个字等宽看起来还不是特 别糟糕,英文看起来就比较过分了。
为了解决这个问题,一个常用的解决方法是在TextView内使用html来 实现文本样式的设定,或者干脆放弃TextView而使用WebView来实现。但是,凡事都应该敢于解决问题,而不是回避问题,我相信即使仅用 TextView一样是可以实现,后来我发现stackoverflow上有个回答提供了一种思路,我按照这种思路果然实现了TextView文本的分散 对齐。 以下是我的实现过程:
MainActivity中:
Display display = getWindowManager().getDefaultDisplay(); DisplayMetrics dm = new DisplayMetrics(); display.getMetrics(dm); width = dm.widthPixels; //根据屏幕调整文字大小 mArticleTextView.setLineSpacing(0f, 1.5f); mArticleTextView.setTextSize(8*(float)width/320f); //设置TextView mArticleTextView.setText("TextView需要显示的文本内容"); TextJustification.justify(mArticleTextView,mArticleTextView.getWidth()); 首先设置TextView的显示字体大小和文本内容,这里设置字体大小根据屏幕尺寸调整。然后调用自定义的类Textustification中的 justify方法来实现TextView的分散对齐,两个参数分别是TextView控件以及控件的宽度。 自定义的类TextJustification内容如下: import java.util.ArrayList; import android.graphics.Paint; import android.text.TextUtils; import android.widget.TextView; import android.widget.TextView.BufferType; public class TextJustification { public static void justify(TextView textView, float contentWidth) { String text=textView.getText().toString(); String tempText; String resultText = ""; Paint paint=textView.getPaint(); ArrayList<String> paraList = new ArrayList<String>(); paraList = paraBreak(text); for(int i = 0; i<paraList.size(); i++) { ArrayList<String> lineList=lineBreak(paraList.get(i).trim(),paint,contentWidth); tempText = TextUtils.join(" ", lineList).replaceFirst("\\s*", ""); resultText += tempText.replaceFirst("\\s*", "") + "\n"; } textView.setText(resultText); } //分开每个段落 public static ArrayList<String> paraBreak(String text, TextView textview) { ArrayList<String> paraList = new ArrayList<String>(); String[] paraArray = text.split("\\n+"); for(String para:paraArray) { paraList.add(para); } return paraList; } //分开每一行,使每一行填入最多的单词数 private static ArrayList<String> lineBreak(String text, Paint paint, float contentWidth){ String [] wordArray=text.split("\\s"); ArrayList<String> lineList = new ArrayList<String>(); String myText=""; for(String word:wordArray){ if(paint.measureText(myText+" "+word)<=contentWidth) myText=myText+" "+word; else{ int totalSpacesToInsert=(int)((contentWidth-paint.measureText(myText))/paint.measureText(" ")); lineList.add(justifyLine(myText,totalSpacesToInsert)); myText=word; } } lineList.add(myText); return lineList; } //已填入最多单词数的一行,插入对应的空格数直到该行满 private static String justifyLine(String text,int totalSpacesToInsert){ String[] wordArray=text.split("\\s"); String toAppend=" "; while((totalSpacesToInsert)>=(wordArray.length-1)){ toAppend=toAppend+" "; totalSpacesToInsert=totalSpacesToInsert-(wordArray.length-1); } int i=0; String justifiedText=""; for(String word:wordArray){ if(i<totalSpacesToInsert) justifiedText=justifiedText+word+" "+toAppend; else justifiedText=justifiedText+word+toAppend; i++; } return justifiedText; }
}这个类完成了TextView内部文字的排版工作,主要分3个步骤:
1、将一篇文章按段落分成若干段(如果只有一段可以略去该步骤);
2、将每一段的文字拆分成各个单词,然后根据控件长度确定每一行最多可以填入的单词数,并且算出排满该行还需要填入几个空格。
3、填入空格。
注意代码中用到了一些正则表达式进行文章内容操作,若不清楚可以自行搜索含义。
这样就完成了TextView内部文字分散对齐的排版过程。总结一下,这样操作还是有点蛋疼的,虽然不算复杂,但还是对文本内容进行了完全的重新处 理;并且仅是使用了已有的文本和空格数来实现对齐,并不是严格的分散对齐。但不管怎么说,终究是用TextView自身的操作来实现了,并且效果还算不 错。