1. 程式人生 > >Android實現朋友圈全文/收起的功能

Android實現朋友圈全文/收起的功能

看下效果圖:

這裡寫圖片描述

首先我們先理解收起和全文的邏輯:

假如產品設定:文字超過三行就要摺疊
1 如果文字不超過三行,那麼就不顯示“全文”和“收起”
2 如果超過了三行顯示“全文”,點選全文就可以看到所有文字,同時最下面顯示“收起”

難點在如何記錄每個Item的收起和全文的狀態?

我們知道RecyerView和ListView都是複用ViewHolder,所以免不了有一個Holder要分別渲染兩次資料,平時我們做的資料渲染只是把資料塗在了ViewHolder上,不影響Holder本身,但是這裡需要改變Holder裡面的狀態,改變之後會影響下一個Holder的顯示,如何解決呢?

關於這個BaseHolder和BaseAdapterAgency,大家可以看下我的上一篇文章打造一款簡化RecyclerView使用的開源庫

public class TextHolder extends BaseHolder<News> {
    private TextView content;
    private TextView all_text;
    private final int MAX_LINE_COUNT = 3;//最大顯示行數

    private final int STATE_UNKNOW = -1;//未知狀態

    private final int
STATE_NOT_OVERFLOW = 1;//文字行數小於最大可顯示行數 private final int STATE_COLLAPSED = 2;//摺疊狀態 private final int STATE_EXPANDED = 3;//展開狀態 private SparseArray<Integer> mTextStateList;//儲存文字狀態集合 public TextHolder(View itemView) { super(itemView); content = itemView.findViewById(R.id.content); all_text = itemView.findViewById(R.id.all_text); } @Override public
void bindViewHolder(News news) { bindViewHolder(news,null); } /** * 具體的繫結檢視的操作 * @param news * @param o */ public void bindViewHolder(final News news, final Object o) { mTextStateList = (SparseArray<Integer>) o; int state = mTextStateList.get(news.getId(), STATE_UNKNOW); //第一次初始化,未知狀態 if (state == STATE_UNKNOW) { content.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() { @Override public boolean onPreDraw() { //這個回掉會呼叫多次,獲取完行數後記得登出監聽 content.getViewTreeObserver().removeOnPreDrawListener(this); //content.getViewTreeObserver().addOnPreDrawListener(null); //如果內容顯示的行數大於最大顯示行數 if (content.getLineCount() > MAX_LINE_COUNT) { content.setMaxLines(MAX_LINE_COUNT);//設定最大顯示行數 all_text.setVisibility(View.VISIBLE);//顯示“全文” all_text.setText("全文"); mTextStateList.put(news.getId(), STATE_COLLAPSED);//儲存狀態 } else { all_text.setVisibility(View.GONE); mTextStateList.put(news.getId(), STATE_NOT_OVERFLOW); } return true; } }); content.setMaxLines(Integer.MAX_VALUE);//設定文字的最大行數,為整數的最大數值 content.setText(news.getContent()); } else { //如果之前已經初始化過了,則使用儲存的狀態。 switch (state) { case STATE_NOT_OVERFLOW: all_text.setVisibility(View.GONE); break; case STATE_COLLAPSED: content.setMaxLines(MAX_LINE_COUNT); all_text.setVisibility(View.VISIBLE); all_text.setText("全文"); break; case STATE_EXPANDED: content.setMaxLines(Integer.MAX_VALUE); all_text.setVisibility(View.VISIBLE); all_text.setText("收起"); break; } content.setText(news.getContent()); } //全文和收起的點選事件 all_text.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { int state = mTextStateList.get(news.getId(), STATE_UNKNOW); if (state == STATE_COLLAPSED) { content.setMaxLines(Integer.MAX_VALUE); all_text.setText("收起"); mTextStateList.put(news.getId(), STATE_EXPANDED); } else if (state == STATE_EXPANDED) { content.setMaxLines(MAX_LINE_COUNT); all_text.setText("全文"); mTextStateList.put(news.getId(), STATE_COLLAPSED); } } }); } }
public class NewsAgency extends BaseAdapterAgency<News> {
    private Context context;
    private Activity mContent;

    /**
     * 注意:儲存文字狀態集合的key一定要是唯一的,如果用position。
     * 如果使用position作為key,則刪除、增加條目的時候會出現顯示錯亂
     * 而且不能在Holder裡面建立!!!
     */
    private SparseArray<Integer> mTextStateList;//儲存文字狀態集合

    List<News> mList;

    public NewsAgency(List<News> list, Activity context) {
        super(context,list);
        mContent = context;
        this.mList = list;
        mTextStateList = new SparseArray<>();
    }

    @Override
    public void onBindViewHolder(BaseHolder holder, int position) {
        if(holder instanceof TextHolder){
            ((TextHolder) holder).bindViewHolder(mList.get(position),mTextStateList);
        }
    }

    @Override
    public int getItemCount() {
        return mList.size();
    }

    @Override
    public int getAdapterItemViewType(int i) {
        return 0;
    }

    @Override
    public BaseHolder createBaseHolder(ViewGroup viewGroup, int i) {
        return new TextHolder(mContent.getLayoutInflater().inflate(R.layout.item_text, viewGroup, false));
    }
}

最後想說的是:

雖然網上有開源的庫可以顯示全文和收起,但是我認為開源庫的最大問題是靈活的程度(擴充套件性),假如產品讓你把文字顯示為居中,居左,居右,顏色,字型,字號等等改變的時候,開源庫很少能做到如此面面俱到,所以還是使用這種原生的方式比較好~