Android TextView 文字实现左右对齐(分散对齐、两端对齐)的一个思路

来源:互联网 发布:旅行商问题和背包算法 编辑:程序博客网 时间:2024/05/17 21:44

事先陈列一下我这个完成方法的特点:

  1. 支持中英文和符号的混合排版
  2. 支持动态更改文本和字体大小,会自动完成对齐适配
  3. 因为我目前只拿这个来做菜单显示,并没有考虑多行多段的情况,目前只支持单行左右对齐,当字体超出单行显示本方法是无效的。有兴趣的朋友可以在我基础上扩展一哈,我想了一下实现起来应该不难

    方法思路:

    总得来说,还是空格填充,通过自动适配的空格设置来实现对齐效果,字号越小的话空格精度越高,对齐效果越好。
    代码如下,很简单,在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;            }        });

保留所有权,转载请注明!!!

阅读全文
0 0