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

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

  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;
            }
        });

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

你可能感兴趣的:(android)