Android 单个TextView 点击“显示全部”功能实现方法
来源:互联网 发布:墨泥学车软件破解版 编辑:程序博客网 时间:2024/05/22 00:13
网上很多TextView的“显示全部”,“显示更多”的方案实现都是两个TextView,一个在上面显示内容,一个在下面用来点击。但是我在实际工作中遇到的需求是“显示全部”提示要内联在原文的后面,使用一个TextView进行显示,不能放在原文的下面,下面把代码贴一下,主要实现的功能如下:
1、“显示全部”/“显示更多”紧连在正文的后面,不能另起一行
2、当字数超过一定数量显示“显示更多”,
3、当行数超过一定数量显示“显示更多”,比如每行只有一个字,不停的换行,虽然字少但是行数多,也应该将限制之外的行全部省略掉
效果展示
实现起来非常简单,主要步骤如下
1、首先判断要处理段落的字数是否超过限制,如果超过就在后面缀上“显示更多”
2、判断要处理段落在某个TextView上完整显示的行数,如果行数超过限制,那么就显示“显示全部”
3、使用SpannableString,构造:削减后的段落+“...显示更多”。然后将最后“...显示更多”这个字使用ClickableSpan设置上点击事件
有以下几个难点
1、如何在不进行UI绘制的情况下拿到TextView显示某段文字能显示多少行
2、如何获得第x行最后一个字的下标以便从此截取
3、在异步处理的环境中,如何在不进行绘制的情况下获得TextView会画多高以便预留位置
首先下面这段代码是通过传入一个TextView及其宽度,然后获得任意一行最末那个字符的下标的方法,只是为了业务方便,获取的是最大行限制的那一行最后一个字符,如果传入的文字不到最大行数限制,那么就返回-1,这个函数的作用是如果你要做行数“显示全部”限制的话,你知道该从一段文字的哪个地方开始截断。注意下面这个函数一定要在主线程进行执行
/** * get the last char index for max limit row,if not exceed the limit,return -1 * @param textView * @param content * @param width * @param maxLine * @return */ public static int getLastCharIndexForLimitTextView(TextView textView, String content, int width, int maxLine){ Log.i("Alex","宽度是"+width); TextPaint textPaint = textView.getPaint(); StaticLayout staticLayout = new StaticLayout(content, textPaint, width, Layout.Alignment.ALIGN_NORMAL, 1, 0, false); if(staticLayout.getLineCount()>maxLine) return staticLayout.getLineStart(maxLine) - 1;//exceed else return -1;//not exceed the max line }下面这个函数是在上面函数的基础上,在不绘制UI的前提下,计算一段文本显示的高度,获得它高度的主要目的是为了站位,方便异步的显示这些文字。下面的代码在逻辑上做了相应的具体业务的处理,如果文字没有超出最大行数,那么就返回这段文字实际高度,如果超过了最大行数,那么就只返回最大行数之内的文本的高度
/** * 在不绘制textView的情况下算出textView的高度,并且根据最大行数得到应该显示最后一个字符的下标,请在主线程顺序执行,第一个返回值是最后一个字符的下标,第二个返回值是高度 * @param textView * @param content * @param width * @param maxLine * @return */ public static int[] measureTextViewHeight(TextView textView, String content, int width, int maxLine){ Log.i("Alex","宽度是"+width); TextPaint textPaint = textView.getPaint(); StaticLayout staticLayout = new StaticLayout(content, textPaint, width, Layout.Alignment.ALIGN_NORMAL, 1, 0, false); int[] result = new int[2]; if(staticLayout.getLineCount()>maxLine) {//如果行数超出限制 int lastIndex = staticLayout.getLineStart(maxLine) - 1; result[0] = lastIndex; result[1] = new StaticLayout(content.substring(0, lastIndex), textPaint, width, Layout.Alignment.ALIGN_NORMAL, 1, 0, false).getHeight(); return result; }else {//如果行数没有超出限制 result[0] = -1; result[1] = staticLayout.getHeight(); return result; } }
下面的函数就是上面效果展示中展示的例子,通过上面在不绘制UI的前提下获得最大行末尾文字下标,然后让源字符串subString这个下标,在获得的结果上加上“...read more”,然后将添加这一段文字设置点击事件,一个“显示更多”的功能就做好了。
/** * 限制为300字符,并且添加showmore和show more的点击事件 * @param summerize * @param textView * @param clickListener textview的clickListener */ public static void limitStringTo140(String summerize, final CustomTextView textView, final View.OnClickListener clickListener){ final long startTime = System.currentTimeMillis(); if(textView==null)return; int width = textView.getWidth();//在recyclerView和ListView中,由于复用的原因,这个TextView可能以前就画好了,能获得宽度 if(width==0)width = 1000;//获取textview的实际宽度,这里可以用各种方式(一般是dp转px写死)填入TextView的宽度 int lastCharIndex = AlxTextView.getLastCharIndexForLimitTextView(textView,summerize,width,10); if(lastCharIndex<0 && summerize.length() <= 300){//如果行数没超过限制 textView.setText(summerize); return; } //如果超出了行数限制 textView.setMovementMethod(LinkMovementMethod.getInstance());//this will deprive the recyclerView's focus if(lastCharIndex>300 || lastCharIndex<0)lastCharIndex=300; String explicitText = null; if(summerize.charAt(lastCharIndex)=='\n'){//manual enter explicitText = summerize.substring(0,lastCharIndex); }else if(lastCharIndex > 12){//TextView auto enter JLogUtils.i("Alex","the last char of this line is --"+lastCharIndex); explicitText = summerize.substring(0,lastCharIndex-12); } int sourceLength = explicitText.length(); String showmore = "show more"; explicitText = explicitText + "..." + showmore; final SpannableString mSpan = new SpannableString(explicitText); final String finalSummerize = summerize; mSpan.setSpan(new ClickableSpan() { @Override public void updateDrawState(TextPaint ds) { super.updateDrawState(ds); ds.setColor(textView.getResources().getColor(R.color.blue4d9cf2)); ds.setAntiAlias(true); ds.setUnderlineText(false); } @Override public void onClick(View widget) {//"...show more" click event JLogUtils.i("Alex", "click showmore"); AMPTrack.trackCLReadMoreReview(textView.getContext()); textView.setText(finalSummerize); textView.setOnClickListener(null); new Handler().postDelayed(new Runnable() { @Override public void run() { if (clickListener != null) textView.setOnClickListener(clickListener);//prevent the double click } }, 20); } }, sourceLength, explicitText.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); textView.setText(mSpan); Log.i("Alex", "字符串处理耗时" + (System.currentTimeMillis() - startTime)); }
- Android 单个TextView 点击“显示全部”功能实现方法
- android中textview中文字显示过长、使其用省略号代替,点击显示全部
- android 单个textview 中显示多种style
- textview最多显示3行点击事件展开显示全部
- TextView 内容太多用省略号...,点击显示全部
- android中textview竖排显示,只能说功能实现了
- Android textview实现局部点击
- TextView属性android:ellipsize实现跑马灯效果,TextView内容过长加省略号,点击显示全部内容
- Android TextView 显示网络图片,点击放大
- iOS TextView 中的文字 点击一次全部展开, 在点击一次 显示原有大小。
- JS实现显示部分文字点击显示全部
- android Textview 实现展开收缩功能+部分文字点击 (SpannableString)
- 【TextView】自己实现的TextView,只有显示文字功能。
- Android TextView实现点击展开动画效果
- Android - TextView 实现部分文本点击事件
- android TextView 实现自定义文字点击效果
- Android TextView ClickableSpan 分段点击实现
- Android TextView部分文字实现点击事件
- springmvc 中controller与jsp传值
- Mybatis-mapper-xml-基础
- mysql创建定时执行存储过程任务
- C语言中的static 详细分析
- Spring-AOP实践 - 统计访问时间
- Android 单个TextView 点击“显示全部”功能实现方法
- Oracle 11g学习笔记--知识碎片
- TimePickerDialog 5.0以上无法直接输入
- 使用Apache Server 的ab进行web请求压力测试
- Codeforces 724E 最大流=最小割+dp求最小割
- Mybatis-update - 数据库死锁 - 获取数据库连接池等待
- 发送命令
- hdu43700 or 1【01规划模型 最短路】
- Mybatis高级查询之关联查询