RecyclerView系列(六)加載更多的RecyclerView封裝

下拉刷新完成之后界逛,接下來(lái)當(dāng)然是加載更多,加載更多也是在下拉刷新的基礎(chǔ)上封裝的纺座。具體邏輯差不多仇奶,下面直接上代碼

一、RecyclerView封裝類(lèi)

public class LoadRefreshRecyclerView extends RefreshRecyclerView {
// 上拉加載更多的輔助類(lèi)
private LoadViewCreator mLoadCreator;
// 上拉加載更多頭部的高度
private int mLoadViewHeight = 0;
// 上拉加載更多的頭部View
private View mLoadView;
// 手指按下的Y位置
private int mFingerDownY;
// 當(dāng)前是否正在拖動(dòng)
private boolean mCurrentDrag = false;
// 當(dāng)前的狀態(tài)
private int mCurrentLoadStatus;
// 默認(rèn)狀態(tài)
public int LOAD_STATUS_NORMAL = 0x0011;
// 上拉加載更多狀態(tài)
public static int LOAD_STATUS_PULL_DOWN_REFRESH = 0x0022;
// 松開(kāi)加載更多狀態(tài)
public static int LOAD_STATUS_LOOSEN_LOADING = 0x0033;
// 正在加載更多狀態(tài)
public int LOAD_STATUS_LOADING = 0x0044;

public LoadRefreshRecyclerView(Context context) {
    super(context);
}

public LoadRefreshRecyclerView(Context context, @Nullable AttributeSet attrs) {
    super(context, attrs);
}

public LoadRefreshRecyclerView(Context context, @Nullable AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
}

// 先處理上拉加載更多比驻,同時(shí)考慮加載列表的不同風(fēng)格樣式该溯,確保這個(gè)項(xiàng)目還是下一個(gè)項(xiàng)目都能用
// 所以我們不能直接添加View,需要利用輔助類(lèi)
public void addLoadViewCreator(LoadViewCreator loadCreator) {
    this.mLoadCreator = loadCreator;
    addRefreshView();
}

@Override
public void setAdapter(Adapter adapter) {
    super.setAdapter(adapter);
    addRefreshView();
}

@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
    switch (ev.getAction()) {
        case MotionEvent.ACTION_DOWN:
            // 記錄手指按下的位置 ,之所以寫(xiě)在dispatchTouchEvent那是因?yàn)槿绻覀兲幚砹藯l目點(diǎn)擊事件别惦,
            // 那么就不會(huì)進(jìn)入onTouchEvent里面狈茉,所以只能在這里獲取
            mFingerDownY = (int) ev.getRawY();
            break;

        case MotionEvent.ACTION_UP:
            if (mCurrentDrag) {
                restoreLoadView();
            }
            break;
    }
    return super.dispatchTouchEvent(ev);
}

/**
 * 重置當(dāng)前加載更多狀態(tài)
 */
private void restoreLoadView() {
    int currentBottomMargin = ((MarginLayoutParams) mLoadView.getLayoutParams()).bottomMargin;
    int finalBottomMargin = 0;
    if (mCurrentLoadStatus == LOAD_STATUS_LOOSEN_LOADING) {
        mCurrentLoadStatus = LOAD_STATUS_LOADING;
        if (mLoadCreator != null) {
            mLoadCreator.onLoading();
        }
        if (mListener != null) {
            mListener.onLoad();
        }
    }

    int distance = currentBottomMargin - finalBottomMargin;

    // 回彈到指定位置
    ValueAnimator animator = ObjectAnimator.ofFloat(currentBottomMargin, finalBottomMargin).setDuration(distance);
    animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
        @Override
        public void onAnimationUpdate(ValueAnimator animation) {
            float currentTopMargin = (float) animation.getAnimatedValue();
            setLoadViewMarginBottom((int) currentTopMargin);
        }
    });
    animator.start();
    mCurrentDrag = false;
}


@Override
public boolean onTouchEvent(MotionEvent e) {
    switch (e.getAction()) {
        case MotionEvent.ACTION_MOVE:
            // 如果是在最底部才處理,否則不需要處理
            if (canScrollDown() || mCurrentLoadStatus == LOAD_STATUS_LOADING
                    || mLoadCreator == null || mLoadView == null) {
                // 如果沒(méi)有到達(dá)最頂端掸掸,也就是說(shuō)還可以向上滾動(dòng)就什么都不處理
                return super.onTouchEvent(e);
            }

            if (mLoadCreator != null) {
                mLoadViewHeight = mLoadView.getMeasuredHeight();
            }
            // 解決上拉加載更多自動(dòng)滾動(dòng)問(wèn)題
            if (mCurrentDrag) {
                scrollToPosition(getAdapter().getItemCount() - 1);
            }

            // 獲取手指觸摸拖拽的距離
            int distanceY = (int) ((e.getRawY() - mFingerDownY) * mDragIndex);
            // 如果是已經(jīng)到達(dá)頭部氯庆,并且不斷的向下拉,那么不斷的改變r(jià)efreshView的marginTop的值
            if (distanceY < 0) {
                setLoadViewMarginBottom(-distanceY);
                updateLoadStatus(-distanceY);
                mCurrentDrag = true;
                return true;
            }
            break;
    }

    return super.onTouchEvent(e);
}

/**
 * 更新加載的狀態(tài)
 */
private void updateLoadStatus(int distanceY) {
    if (distanceY <= 0) {
        mCurrentLoadStatus = LOAD_STATUS_NORMAL;
    } else if (distanceY < mLoadViewHeight) {
        mCurrentLoadStatus = LOAD_STATUS_PULL_DOWN_REFRESH;
    } else {
        mCurrentLoadStatus = LOAD_STATUS_LOOSEN_LOADING;
    }

    if (mLoadCreator != null) {
        mLoadCreator.onPull(distanceY, mLoadViewHeight, mCurrentLoadStatus);
    }
}

/**
 * 添加底部加載更多View
 */
private void addRefreshView() {
    Adapter adapter = getAdapter();
    if (adapter != null && mLoadCreator != null) {
        // 添加底部加載更多View
        View loadView = mLoadCreator.getLoadView(getContext(), this);
        if (loadView != null) {
            addFooterView(loadView);
            this.mLoadView = loadView;
        }
    }
}

/**
 * 設(shè)置加載View的marginBottom
 */
public void setLoadViewMarginBottom(int marginBottom) {
    MarginLayoutParams params = (MarginLayoutParams) mLoadView.getLayoutParams();
    if (marginBottom < 0) {
        marginBottom = 0;
    }
    params.bottomMargin = marginBottom;
    mLoadView.setLayoutParams(params);
}


/**
 * @return Whether it is possible for the child view of this layout to
 * scroll up. Override this if the child view is a custom view.
 * 判斷是不是滾動(dòng)到了最頂部扰付,這個(gè)是從SwipeRefreshLayout里面copy過(guò)來(lái)的源代碼
 */
public boolean canScrollDown() {
    return ViewCompat.canScrollVertically(this, 1);
}

/**
 * 停止加載更多
 */
public void onStopLoad() {
    mCurrentLoadStatus = LOAD_STATUS_NORMAL;
    restoreLoadView();
    if (mLoadCreator != null) {
        mLoadCreator.onStopLoad();
    }
}

// 處理加載更多回調(diào)監(jiān)聽(tīng)
private OnLoadMoreListener mListener;

public void setOnLoadMoreListener(OnLoadMoreListener listener) {
    this.mListener = listener;
}

public interface OnLoadMoreListener {
    void onLoad();
}}

二堤撵、輔助類(lèi)

 public abstract class LoadViewCreator {
/**
 * 獲取上拉加載更多的View
 *
 * @param context 上下文
 * @param parent  RecyclerView
 */
public abstract View getLoadView(Context context, ViewGroup parent);

/**
 * 正在上拉
 *
 * @param currentDragHeight    當(dāng)前拖動(dòng)的高度
 * @param loadViewHeight    總的加載高度
 * @param currentLoadStatus 當(dāng)前狀態(tài)
 */
public abstract void onPull(int currentDragHeight, int loadViewHeight, int currentLoadStatus);

/**
 * 正在加載中
 */
public abstract void onLoading();

/**
 * 停止加載
 */
public abstract void onStopLoad();
}

使用和下來(lái)加載差不多

三、下拉刷新和上拉加載更多使用

    // 添加頭部和底部刷新效果
    mRecyclerView.addRefreshViewCreator(new DefaultRefreshCreator());
    mRecyclerView.addLoadViewCreator(new DefaultLoadCreator());
    mRecyclerView.setOnRefreshListener(this);
    mRecyclerView.setOnLoadMoreListener(this);

 @Override
  public void onRefresh() {
    new Handler().postDelayed(new Runnable() {
        @Override
        public void run() {
            mRecyclerView.onStopRefresh();
        }
    }, 2000);
}

@Override
public void onLoad() {
    new Handler().postDelayed(new Runnable() {
        @Override
        public void run() {
            initData();
            mRecyclerView.onStopLoad();
            mAdapter.notifyDataSetChanged();
        }
    }, 2000);
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末羽莺,一起剝皮案震驚了整個(gè)濱河市实昨,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌盐固,老刑警劉巖荒给,帶你破解...
    沈念sama閱讀 217,657評(píng)論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件丈挟,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡志电,警方通過(guò)查閱死者的電腦和手機(jī)曙咽,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,889評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)挑辆,“玉大人例朱,你說(shuō)我怎么就攤上這事∮悴酰” “怎么了洒嗤?”我有些...
    開(kāi)封第一講書(shū)人閱讀 164,057評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)蚀乔。 經(jīng)常有香客問(wèn)我,道長(zhǎng)菲茬,這世上最難降的妖魔是什么吉挣? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,509評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮婉弹,結(jié)果婚禮上睬魂,老公的妹妹穿的比我還像新娘。我一直安慰自己镀赌,他們只是感情好氯哮,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,562評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著商佛,像睡著了一般喉钢。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上良姆,一...
    開(kāi)封第一講書(shū)人閱讀 51,443評(píng)論 1 302
  • 那天肠虽,我揣著相機(jī)與錄音,去河邊找鬼玛追。 笑死税课,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的痊剖。 我是一名探鬼主播韩玩,決...
    沈念sama閱讀 40,251評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼陆馁!你這毒婦竟也來(lái)了找颓?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,129評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤叮贩,失蹤者是張志新(化名)和其女友劉穎叮雳,沒(méi)想到半個(gè)月后想暗,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,561評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡帘不,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,779評(píng)論 3 335
  • 正文 我和宋清朗相戀三年说莫,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片寞焙。...
    茶點(diǎn)故事閱讀 39,902評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡储狭,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出捣郊,到底是詐尸還是另有隱情辽狈,我是刑警寧澤,帶...
    沈念sama閱讀 35,621評(píng)論 5 345
  • 正文 年R本政府宣布呛牲,位于F島的核電站刮萌,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏娘扩。R本人自食惡果不足惜着茸,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,220評(píng)論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望琐旁。 院中可真熱鬧涮阔,春花似錦、人聲如沸灰殴。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,838評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)牺陶。三九已至伟阔,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間掰伸,已是汗流浹背减俏。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,971評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留碱工,地道東北人娃承。 一個(gè)月前我還...
    沈念sama閱讀 48,025評(píng)論 2 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像怕篷,于是被迫代替她去往敵國(guó)和親历筝。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,843評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,116評(píng)論 25 707
  • 內(nèi)容抽屜菜單ListViewWebViewSwitchButton按鈕點(diǎn)贊按鈕進(jìn)度條TabLayout圖標(biāo)下拉刷新...
    皇小弟閱讀 46,759評(píng)論 22 665
  • 今天本來(lái)很好的心情廊谓,去廠里陪伴她梳猪。她說(shuō)要放假了,我聽(tīng)著多高興啊。于是我就試探性的說(shuō)我們不如回老家吧春弥,結(jié)果又是錢(qián)呀神...
    壩周閱讀 157評(píng)論 0 0
  • 我是我所有幻想的主角呛哟, 在你的劇情里苦澀的演了很久。 我被選擇的用第一人稱(chēng)匿沛, 流著淚哭了很久很久扫责。 你與所有人相襯...
    糜情閱讀 186評(píng)論 0 1
  • 導(dǎo)讀: 林拜得知德仁的現(xiàn)狀鳖孤,鼓勵(lì)鄭秋冬這正是轉(zhuǎn)型的好時(shí)機(jī),拋開(kāi)情分抡笼,德仁的財(cái)務(wù)數(shù)據(jù)和公司業(yè)績(jī)都是上升狀態(tài)苏揣,不過(guò)是走...
    課后輔導(dǎo)陳老師閱讀 988評(píng)論 0 1