Android 单个TextView 点击“显示全部”功能实现方法
網上很多TextView的“顯示全部”,“顯示更多”的方案實現都是兩個TextView,一個在上面顯示內容,一個在下面用來點擊。但是我在實際工作中遇到的需求是“顯示全部”提示要內聯在原文的后面,使用一個TextView進行顯示,不能放在原文的下面,下面把代碼貼一下,主要實現的功能如下:
1、“顯示全部”/“顯示更多”緊連在正文的后面,不能另起一行
2、當字數超過一定數量顯示“顯示更多”,
3、當行數超過一定數量顯示“顯示更多”,比如每行只有一個字,不停的換行,雖然字少但是行數多,也應該將限制之外的行全部省略掉
效果展示
實現起來非常簡單,主要步驟如下
1、首先判斷要處理段落的字數是否超過限制,如果超過就在后面綴上“顯示更多”
2、判斷要處理段落在某個TextView上完整顯示的行數,如果行數超過限制,那么就顯示“顯示全部”
3、使用SpannableString,構造:削減后的段落+“...顯示更多”。然后將最后“...顯示更多”這個字使用ClickableSpan設置上點擊事件
有以下幾個難點
1、如何在不進行UI繪制的情況下拿到TextView顯示某段文字能顯示多少行
2、如何獲得第x行最后一個字的下標以便從此截取
3、在異步處理的環境中,如何在不進行繪制的情況下獲得TextView會畫多高以便預留位置
首先下面這段代碼是通過傳入一個TextView及其寬度,然后獲得任意一行最末那個字符的下標的方法,只是為了業務方便,獲取的是最大行限制的那一行最后一個字符,如果傳入的文字不到最大行數限制,那么就返回-1,這個函數的作用是如果你要做行數“顯示全部”限制的話,你知道該從一段文字的哪個地方開始截斷。注意下面這個函數一定要在主線程進行執行
/*** 在不繪制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 点击“显示全部”功能实现方法的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 51nod快乐排队 1431
- 下一篇: java调起喇叭,【音响知识】调音不求人