中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Android實現可點擊展開的TextView

發布時間:2020-10-14 20:23:01 來源:腳本之家 閱讀:592 作者:碼卡農 欄目:移動開發

概述

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 方法),傳送門:

如何寫一個可以展開的TextView
android Textview 使用之一:伸縮效果

參考文章:

用SpannableString和ImageSpan在textview中插入圖片
自定義可點擊的ImageSpan并在TextView中內置“View“

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

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

闸北区| 大荔县| 乌兰县| 卓资县| 静宁县| 江源县| 鲁甸县| 孟州市| 光泽县| 大丰市| 井陉县| 志丹县| 那曲县| 孟州市| 浦东新区| 潮州市| 勃利县| 仁怀市| 桃江县| 阿瓦提县| 杭州市| 苍溪县| 确山县| 蓬安县| 嘉义县| 延庆县| 怀柔区| 南通市| 乌海市| 黄梅县| 靖西县| 和静县| 白朗县| 彝良县| 京山县| 沭阳县| 苏尼特左旗| 阿克陶县| 疏附县| 方城县| 柳河县|