近来天气渐冷啊!晚上加班加很晚回来的路上有点扛不住啊!好在桂花开了。还挺香的!

  • 需求原型
    最近有个需求看图:
    android中根据控件宽度,实现展示文本内容,解决中英文自动换行_第1张图片
    要求还行,不怎么奇怪。其中如果显示一行的话我们完全可以用view 自带的ellipsize属性配合singleLine来实现。比如:
 android:ellipsize="start" android:singleLine="true"
 android:ellipsize="middle" android:singleLine="true"
 android:ellipsize="end" android:singleLine="true"
 android:ellipsize="marquee" android:singleLine="true"

可以看到elilipsize一共有4个可选值。看名称其实很容易理解,开始,中间,结尾和无限。实现的效果分别是如果文本内容超过textview 的宽度,那么分别显示…在开头中间,结尾和循环。注意一定要配合singleLine=true来使用,不然会失效。当然marquee这个属性再配合一些其他属性我们就可以实现跑马灯效果了。如下:

 android:marqueeRepeatLimit="marquee_forever" android:focusableInTouchMode="true" android:ellipsize="marquee" android:singleLine="true"

好了,那么现在我们要求是2行,那么singleline这个属性不能用。那么我们上面的属性当然也不能实现了。我们该怎么办呢。想了很多办法,其实挺难的。最终我的理解为:第一行显示最前面,中间…第二行显示最后的内容就行了。所以网上查找了一番,发现控件上能显示多少文字还是比较简单的。具体代码是如下:

TextView textView = (TextView) findViewById(R.id.test);textView.setText(text);int spec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);textView.measure(spec, spec);// getMeasuredWidth 获得控件宽度int measuredWidth = textView.getMeasuredWidth();// textView getPaint measureText 获得控件的TextView的对象TextPaint textPaint = textView.getPaint();// 获得输入的text 的宽度float textPaintWidth = textPaint.measureText(text);

根据网上这些基础的提示我的脑子就有了想法。既然控件宽度能获取到,对应的文本内容的宽度也能拿到,那么一行能显示多少文本就很容易得到了。

//获取我们需要展示的文本内容String content=textView.getText().toString();// getMeasuredWidth 获得控件宽度int measuredWidth = textView.getMeasuredWidth();// textView getPaint measureText 获得控件的TextView的对象TextPaint textPaint = textView.getPaint();// 获得输入的text 的宽度float textPaintWidth = textPaint.measureText(content);//先判断文本是否超过2行if(textPaintWidth2 ){    return content;//能显示完全我们直接返回就行了。无需操作}    //当前的textview 的textSize为15sp 其实很明显文字大小不同,每个字符占用的长度也是不同的,这里假设为15。我通过日志知道:".",0,"a","A","好",“ ” 等。这些分别占用的数值为:8,10,16,17,30,30。所以说其实挺麻烦的,因为区别很大。这里明显中文的显示是最大的为30。所以我们长度给一个最低范围-30。    // 首先计算一共能显示多少个字符:        num = (measuredWidth -30) ;//统计文本总长度        int sumLenth=0;        //定义第一行应该显示的sb        StringBuilder sbfor = new StringBuilder();        //通过循环从content中找出第一行能显示的所有文本        for(int i=0;iif(sumLenth16){//继续缩小化一点            //获取每个位置的文本                String str=content.substring(i,i+1);                //计算长度并且统计    sumLenth=sumLenth+(int)textPaint.measureText(str);                                          if(sumLenth16){                //当第一行还能显示我们就拼接                    sbfor.append(str);                }            }else{            //超出长度我们就退出循环并且拿到内容:sbfor                i=content.length();            }        }        //接下来计算第二行 的文本内容。也就是文本最后的内容。很好理解这次我们从后往前遍历截取。        num=measuredWidth-8;        sumLenth=0;        String sb="";        for(int i=content.length()-1;i>0;i--){            if(sumLenthstr="";                if(i==content.length()-1){//拿最后一位                    str=content.substring(i);                }else{                    str=content.substring(i,i+1);                }    sumLenth=sumLenth+(int) textPaint.measureText(str);                if(sumLenthstr+sb;                }            }else{            //退出循环                i=0;            }        }//好了这里我们既获得了第一行文本以及第二行文本,那我们就可以拼接得到最终内容了. return sbfor.toString()+" "+"..."+sb;

最终显示效果如下:
android中根据控件宽度,实现展示文本内容,解决中英文自动换行_第2张图片
android中根据控件宽度,实现展示文本内容,解决中英文自动换行_第3张图片

大家可以看到上图中已经实现了我们想要实现的效果。其实不然,我当时做完上面操作之后发现还有问题,可以看到上图被我圈红色的地方,很多做过小说app的朋友肯定知道,汉字和字符的编码方式不同,导致如果像上图中“天翼-V2.1.0-1310-9-7(2016092110934).apk”其中前面天翼是汉字用的utf-8编码,而后面的V以及一串数字编码采用的是unicode编码,所以,如果后面的一串数字如果一行不能完全显示,并且前面存在汉字,那么它会在汉字后面直接换行,选择和后面的靠在一起。不信大家可以试试。也就是会这么显示: 天翼-
V2.1.0-1310-9-7(2016092110934).apk这种方式,这明显不是我们想要的效果。所以得解决这个问题。网上搜了很多,有说都转成统一编码方式,或者选择自定义控件。自定义控件其实实现的效果是把“天翼-”这个两个字的间距拉宽,充满整行,让你看的不是那么生硬。其实这种并不能完全达到效果。后来我自己想了想,解决这个办法最好的方式就是在一行的最后加上一个空格,就能解决上面的问题。所以其实上面那个效果能实现,是因为我在
“天翼-V2.1.0-1310-9-7(201609211 “ 加了空格”0934).apk”
所以代码如下:

//计算一行显示数量float num = (measuredWidth -30);        if(textPaintWidth <(2*measuredWidth -30)){        //对于大于一行,小于2行的文本            int sumLenth=0;            StringBuilder sbfor = new StringBuilder();            //依然遍历            for(int i=0;iif(sumLenth16){                    String str=content.substring(i,i+1);        sumLenth=sumLenth+(int) textPaint.measureText(str);                    if(sumLenth16){                        sbfor.append(str);                    }                }else{                //找到一行的位置,并且加上空格,并且再加上后面的文本        sbfor.append(" ").append(content.substring(i));                    return sbfor.toString();                }            }        }

好了到达这里我们就解决问题了。其实这个问题目前很少有人去解决,最然我这个暂时解决了,但是效果不能说百分百。大家可以看一下小米自带的本地文件应用,也没有对这个进行解决。如图:
android中根据控件宽度,实现展示文本内容,解决中英文自动换行_第4张图片
很明显大家看到。黑笔圈的地方。自动换行了。并且小米系统并没有做处理。所以说目前这个技术实现的人还是比较少的所以拿出来分享一下。

补充说明一下。如何正确获取控件的宽度:

TextPaint paint = mTvProgramName.getPaint();paint.setTextSize(mTvProgramName.getTextSize());// paint.measureText(mTvProgramName.getText().toString()); //这个方法能把文本所占宽度衡量出来.Log.i(TAG, "getFocus paint.measureText(mTvProgramName.getText().toString())="           + paint.measureText(mTvProgramName.getText().toString()));mTvProgramName.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {                @Override    public void onLayoutChange(final View v, final int left, final int top, final int right, final int bottom, final int oldLeft, final int oldTop, final int oldRight,                        final int oldBottom) {                        //在此,得到TextView控件的宽度   Log.i(TAG, "onLayoutChange  mTvProgramName.getWidth()=" + v.getWidth());                }            });

我是这么获取的。

//获取屏幕宽度,高度dpi,分辨率Map<String,Float> map=Constants.getScreenWidth(activity);//由于明确知道textview 之外的宽度为110dp,那么通过dip和dp的转换可获得textview的实际dip//屏幕宽度减去占用的dpimeasuredWidth =map.get("width")-map.get("density")*110;

更多相关文章

  1. Android常用复杂控件使用(三)--Fragment
  2. android:gravity="start" Android 多行文本框设置光标从头开始无
  3. Android控件EditText之点击软键盘中的回车键不换行,而是跳到下一
  4. Android圆环形自定义进度条控件的绘制
  5. android中textview设置为多行文本时,如何让文字从最顶开始显示
  6. Android--自定义SeekBarPreference控件
  7. Android 各种基础控件布局
  8. Android 控件之DatePicker,TimePicker,Calender

随机推荐

  1. Android 应用程序退出后不在运行列表中显
  2. Android TextView前加图标垂直居中第一行
  3. Android(安卓)View(四)-View相关属性详解
  4. Android(安卓)重用Layout
  5. android手势实现图片的拖动和缩放效果
  6. android nfc中Ndef格式的读写
  7. Android开发新手常见的10个误区
  8. Android设置TextView的Selector来控制点
  9. Android Lottie动画
  10. Android(安卓)Kotlin 做的开源音乐 APP