事先陈列一下我这个完成方法的特点:
- 支持中英文和符号的混合排版
- 支持动态更改文本和字体大小,会自动完成对齐适配
因为我目前只拿这个来做菜单显示,并没有考虑多行多段的情况,目前只支持单行左右对齐,当字体超出单行显示本方法是无效的。有兴趣的朋友可以在我基础上扩展一哈,我想了一下实现起来应该不难
方法思路:
总得来说,还是空格填充,通过自动适配的空格设置来实现对齐效果,字号越小的话空格精度越高,对齐效果越好。
代码如下,很简单,在TextView的onPreDraw里加一段算法即可:
static final String firstKG = "\u00A0";
static final String secondKG = "\u2009";//两种不同长度的空格
TextView epgtv2;
epgtv2.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
@Override
public boolean onPreDraw() {
if(epgtv2.getText().length() < 2){
return true; //字符个数小于2,没有对齐的必要
}
int width = epgtv2.getWidth();
int number;
Paint p = epgtv2.getPaint();
float fisrtLength = p.measureText(firstKG,0,1);
float secondLength = p.measureText(secondKG,0,1);
int sizeCha = (int)(fisrtLength - secondLength);//基于当前的Textsize,算出两种空格的长度和差值
number = epgtv2.getText().length();
StringBuilder stringBuilderNullFirst = new StringBuilder();
StringBuilder stringBuilderNullSecond = new StringBuilder();
StringBuilder stringBuilderValid = new StringBuilder();
for(int k = 0;k < number;k++){
if(epgtv2.getText().charAt(k) == '\u00A0'){
stringBuilderNullFirst.append(epgtv2.getText().charAt(k));
}else if(epgtv2.getText().charAt(k) == '\u2009'){
stringBuilderNullSecond.append(epgtv2.getText().charAt(k));
}else {
stringBuilderValid.append(epgtv2.getText().charAt(k));
}
}//计算当前文本所有字符的数量并归类,主要针对重新设置size导致的重绘
float checkSum = stringBuilderNullFirst.length()*fisrtLength + stringBuilderNullSecond.length()*secondLength + p.measureText(stringBuilderValid.toString(),0,stringBuilderValid.length());//算出按照目前的文字和size,总长度会是多少
if(checkSum > width){
epgtv2.setText(stringBuilderValid.toString());
/*因为size的增加,导致View容不下字,重新分配空格*/
}else if(checkSum == width){
/*完美显示,直接返回绘制*/
return true;
}else {
number = stringBuilderValid.length();
if((width - checkSum) > (sizeCha * (number - 1))){
if(stringBuilderNullSecond.length() != 0){
/*总余量大于每个缝隙的差值,且存在小空格,重置*/
epgtv2.setText(stringBuilderValid.toString());
}else {
/*只有大空格的情况,总余量大于每个缝隙插一个小空格,重置*/
if((width - checkSum) > (secondLength * (number - 1))){
epgtv2.setText(stringBuilderValid.toString());
}else {
return true;
}
}
}else {
return true;
}
}
number = epgtv2.getText().length();
int rest = width - (int)p.measureText(epgtv2.getText().toString(),0,epgtv2.getText().length());
if(rest < 0){
/*不加空格的情况下,字号超过组件需要换行了,本方法不生效*/
return true;
}
int restPer = rest / (number - 1);
int secondPer = restPer / (int)secondLength;
int secondLeft = restPer % (int)secondLength;//先用小字号空格填缝隙
int firstPer = 0;
if(sizeCha != 0) {
firstPer = secondLeft / sizeCha;
}
if(secondPer > firstPer){
secondPer -= firstPer;
}else {
firstPer = secondPer;
secondPer = 0;
}//根据计算剩下的空间,将相应的小空格替换为大空格进一步缩小误差
StringBuilder stringBuilder = new StringBuilder();
for(int j = 0;j < number;j++){
stringBuilder.append(epgtv2.getText().charAt(j));
if(j == number - 1){
break;
}else {
for (int i = 0; i < firstPer; i++) {
stringBuilder.append("\u00A0");
}
for (int n = 0; n < secondPer; n++) {
stringBuilder.append("\u2009");
}
}
}//重设我们的文本,完成!
epgtv2.setText(stringBuilder.toString());
return true;
}
});
保留所有权,转载请注明!!!
版权声明:本文为shenghuo59原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。