失眠网,内容丰富有趣,生活中的好帮手!
失眠网 > Android 单个TextView 点击“显示全部”功能实现方法

Android 单个TextView 点击“显示全部”功能实现方法

时间:2019-09-30 09:43:18

相关推荐

Android 单个TextView 点击“显示全部”功能实现方法

网上很多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;//exceedelse return -1;//not exceed the max line}

下面这个函数是在上面函数的基础上,在不绘制UI的前提下,计算一段文本显示的高度,获得它高度的主要目的是为了占位高度,免得上下滑动的时候屏幕跳跃,方便异步的显示这些文字。下面的代码在逻辑上做了相应的具体业务的处理,如果文字没有超出最大行数,那么就返回这段文字实际高度,如果超过了最大行数,那么就只返回最大行数之内的文本的高度

/*** 在不绘制textView的情况下算出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 TextView 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 = 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 focusif(lastCharIndex>300 || lastCharIndex<0)lastCharIndex=300;String explicitText = null;if(summerize.charAt(lastCharIndex)=='\n'){//manual enterexplicitText = summerize.substring(0,lastCharIndex);}else if(lastCharIndex > 12){//TextView auto enterJLogUtils.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() {@Overridepublic void updateDrawState(TextPaint ds) {super.updateDrawState(ds);ds.setColor(textView.getResources().getColor(R.color.blue4d9cf2));ds.setAntiAlias(true);ds.setUnderlineText(false);}@Overridepublic void onClick(View widget) {//"...show more" click eventLog.i("Alex", "click showmore");textView.setText(finalSummerize);textView.setOnClickListener(null);new Handler().postDelayed(new Runnable() {@Overridepublic 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 点击“显示全部”功能实现方法》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。