国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 系統 > Android > 正文

Android實現可點擊展開的TextView

2019-10-22 18:22:44
字體:
來源:轉載
供稿:網友

概述

Android開發過程中,經常遇到 Textview 展示不完全的情況。

遇到此情況,通常的處理是:

方案一
Textview 添加 android:ellipsize 屬性,讓展示不完的部分使用省略號代替。
方案二
Textview 采用走馬燈效果,使其滾動展示全部文本內容。
對于方案一,如果想查看被省略后的內容,如何實現?通常情況下是在 TextView 文本后面或下邊添加一個可點擊的圖標,來實現 TextView 的展開與收縮。如下圖:

收縮狀態

Android,點擊展開,TextView

展開狀態

Android,點擊展開,TextView

實現原理

對于以上效果,大致的實現思路是:

  • 對 TextView 添加視圖高度監聽 (addOnGlobalLayoutListener),監控 TextView 的狀態。
  • 利用 SpannableString 在 TextView 文本的后面添加一個圖標。
  • 實現圖標的點擊效果(收縮或展開 TextView)。

下面用代碼來詳細描述實現的過程:

給TextView添加視圖高度監聽

 

  /**   * 添加監聽   * @param tv  要實現伸縮效果的 TextView   * @param desc TextView 要展示的文字   */  public static void toggleEllipsize(final TextView tv,final String desc){    if(desc == null){      return;    }    //去除點擊圖片后的背景色( SpannableString 在點擊時會使背景變色 ,填上這句則可不變色 )    tv.setHighlightColor(Color.TRANSPARENT);    //添加 TextView 的高度監聽    tv.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {      @SuppressWarnings("deprecation")      @SuppressLint("NewApi")      @Override      public void onGlobalLayout() {        int paddingLeft = tv.getPaddingLeft();        int paddingRight = tv.getPaddingRight();        TextPaint paint = tv.getPaint();        float moreText  = tv.getTextSize() * 3;        float availableTextWidth = (tv.getWidth() - paddingLeft - paddingRight) * 2 - moreText;        CharSequence ellipsizeStr = TextUtils.ellipsize(desc,paint,availableTextWidth,TextUtils.TruncateAt.END);        // TextView 實際顯示的文本長度 < 應該顯示文本的長度(收縮狀態)        if(ellipsizeStr.length() < desc.length()){          openFun(tv, ellipsizeStr, desc);//顯示收縮狀態的文本和圖標        }        // TextView 實際顯示的文本長度 == 應該顯示文本的長度(正常狀態)        else if(ellipsizeStr.length() == desc.length()){          tv.setText(desc);//正常顯示Textview        }        // TextView 實際顯示的文本長度 > 應該顯示文本的長度(展開狀態)        else{          closeFun(tv, ellipsizeStr, desc);//顯示展開狀態的文本和圖標        }        if(Build.VERSION.SDK_INT>=16){           tv.getViewTreeObserver().removeOnGlobalLayoutListener(this);         }else{           tv.getViewTreeObserver().removeGlobalOnLayoutListener(this);         }      }    });  }

使用 SpannableString

在 SpannableString 中,我們可以通過設置 ImageSpan 來給 TextView 添加圖標,但是普通的 ImageSpan 是不能響應點擊事件的而且也不能設置圖片的位置,那么我們要如何實現一個可以響應點擊事件并且可以設置圖片位置的 ImageSpan 呢?

Step 1:

新建一個 ClickableImageSpan 類,使之具有 ImageSpan 所有屬性的,并且可以點擊,圖片垂直居中 。

 

/** * ClickableImageSpan 繼承自 ImageSpan,使其能響應點擊事件,并圖片垂直居中顯示 * @author lee * */public abstract class ClickableImageSpan extends ImageSpan {  public ClickableImageSpan(Drawable b) {    super(b);  }  /** 圖片垂直居中顯示 */  @Override  public int getSize(Paint paint, CharSequence text, int start, int end,       Paint.FontMetricsInt fontMetricsInt) {    Drawable drawable = getDrawable();     Rect rect = drawable.getBounds();     if (fontMetricsInt != null) {       Paint.FontMetricsInt fmPaint = paint.getFontMetricsInt();       int fontHeight = fmPaint.bottom - fmPaint.top;       int drHeight = rect.bottom - rect.top;       int top = drHeight / 2 - fontHeight / 4;       int bottom = drHeight / 2 + fontHeight / 4;       fontMetricsInt.ascent = -bottom;       fontMetricsInt.top = -bottom;       fontMetricsInt.bottom = top;       fontMetricsInt.descent = top;     }     return rect.right;   }   /** 圖片垂直居中顯示 */  @Override   public void draw(Canvas canvas, CharSequence text, int start, int end,       float x, int top, int y, int bottom, Paint paint) {    Drawable drawable = getDrawable();     canvas.save();     int transY = 0;     transY = ((bottom - top) - drawable.getBounds().bottom) / 2 + top;     canvas.translate(x, transY);     drawable.draw(canvas);     canvas.restore();   }  /** 添加點擊事件 */  public abstract void onClick(View view);}

Step 2:

新建一個 ClickableMovementMethod (修改 LinkMovementMethod 的 onTouchEvent 方法), 使其支持 ClickableImageSpan 。

 

/** * ClickableMovementMethod 繼承自 LinkMovementMethod,使其能響應 ClickableImageSpan * @author lee * */public class ClickableMovementMethod extends LinkMovementMethod {  private static ClickableMovementMethod sInstance;  public static ClickableMovementMethod getInstance() {    if (sInstance == null) {      sInstance = new ClickableMovementMethod();    }    return sInstance;  }  public boolean onTouchEvent(TextView widget, Spannable buffer,      MotionEvent event) {    int action = event.getAction();    if (action == MotionEvent.ACTION_UP ||        action == MotionEvent.ACTION_DOWN) {      int x = (int) event.getX();      int y = (int) event.getY();      x -= widget.getTotalPaddingLeft();      y -= widget.getTotalPaddingTop();      x += widget.getScrollX();      y += widget.getScrollY();      Layout layout = widget.getLayout();      int line = layout.getLineForVertical(y);      int off = layout.getOffsetForHorizontal(line, x);      ClickableSpan[] link = buffer.getSpans(off, off, ClickableSpan.class);      /** 修改位置【1】 START **/      ClickableImageSpan[] imageSpans = buffer.getSpans(off, off, ClickableImageSpan.class);      /******  END  ******/      if (link.length != 0) {        if (action == MotionEvent.ACTION_UP) {          link[0].onClick(widget);        } else if (action == MotionEvent.ACTION_DOWN) {          Selection.setSelection(buffer,              buffer.getSpanStart(link[0]),              buffer.getSpanEnd(link[0]));        }        return true;      }       /** 修改位置【2】START **/      else if (imageSpans.length != 0) {        if (action == MotionEvent.ACTION_UP) {          imageSpans[0].onClick(widget);        } else if (action == MotionEvent.ACTION_DOWN) {          Selection.setSelection(buffer,              buffer.getSpanStart(imageSpans[0]),              buffer.getSpanEnd(imageSpans[0]));        }        return true;      }       /******  END   ******/      else {        Selection.removeSelection(buffer);      }    }    return false;  }}

將改好的 SpannableString 設置到 TextView 中

 

  // 顯示收縮狀態的文本,設置點擊圖標,并添加點擊事件  private static void openFun(final TextView tv,final CharSequence ellipsizeStr,final String desc){    CharSequence temp = ellipsizeStr+".";    SpannableStringBuilder ssb = new SpannableStringBuilder(temp);    Drawable dd = tv.getResources().getDrawable(R.drawable.ic_expand);    dd.setBounds(0, 0, dd.getIntrinsicWidth(), dd.getIntrinsicHeight());    ClickableImageSpan is = new ClickableImageSpan(dd) {      @Override      public void onClick(View view) {        closeFun(tv,ellipsizeStr,desc);      }    };    ssb.setSpan(is, temp.length()-1, temp.length(), Spannable.SPAN_INCLUSIVE_EXCLUSIVE);    tv.setText(ssb);    tv.setMovementMethod(ClickableMovementMethod.getInstance());  }  // 顯示展開狀態的文本,設置點擊圖標,并添加點擊事件  private static void closeFun(final TextView tv,final CharSequence ellipsizeStr,final String desc) {    SpannableStringBuilder ssb = new SpannableStringBuilder(desc);    Drawable dd = tv.getResources().getDrawable(R.drawable.ic_normal);    dd.setBounds(0, 0, dd.getIntrinsicWidth(), dd.getIntrinsicHeight());    ClickableImageSpan is = new ClickableImageSpan(dd) {      @Override      public void onClick(View view) {        openFun(tv,ellipsizeStr,desc);      }    };    ssb.setSpan(is, desc.length()-1, desc.length(), Spannable.SPAN_INCLUSIVE_EXCLUSIVE);    tv.setText(ssb);    tv.setMovementMethod(ClickableMovementMethod.getInstance());  }

在Activity 中調用

public class MainActivity extends Activity {  private TextView mTv;  private String str = "我有一只小毛驢,我從來也不騎~ "      + "有一天我心血來潮騎它去趕集,我手里拿著小皮鞭,我心里正得意~ "      + "不知怎么嘩啦啦啦啦,我摔了一身泥~";  @Override  protected void onCreate(Bundle savedInstanceState) {    super.onCreate(savedInstanceState);    setContentView(R.layout.activity_main);    mTv = (TextView) findViewById(R.id.tv_test);    //調用 toggleEllipsize 方法來設置 mTv    Utils.toggleEllipsize(mTv,str);  }}

完整Demo鏈接:ExpandableTextView

還有一些使用其他方法實現可伸縮的 TextView(使用 setMaxLines 方法),傳送門:

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持VEVB武林網。


注:相關教程知識閱讀請移步到Android開發頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 台东市| 东乌珠穆沁旗| 屏南县| 剑河县| 荆门市| 绿春县| 沾益县| 章丘市| 永和县| 剑河县| 湟源县| 纳雍县| 青岛市| 航空| 南漳县| 金秀| 巴中市| 万年县| 泽库县| 策勒县| 松原市| 高要市| 南和县| 永清县| 阳新县| 南乐县| 兖州市| 贵阳市| 信阳市| 铁岭市| 城市| 福泉市| 临海市| 青海省| 浦县| 肃宁县| 长武县| 乌什县| 永川市| 宁河县| 威远县|