Android中模仿抖音的滑動RecycleView的實現(xiàn)

代碼下載:https://github.com/TangfeiJi/DouYinViewPager

時下最火的莫過抖音了,實現(xiàn)這個效果應(yīng)該很簡單嘛,用ViewPager就可以了。但是等你通過ViewPager來實現(xiàn)的時候,手機內(nèi)存不夠用的情況就會顯現(xiàn)出來。

每個人都會用RecyclerView吧,我們就用RecyclerView來實現(xiàn)這個效果,關(guān)于內(nèi)存的回收利用就交給RecyclerView就好了。

那么我們怎么通過RecyclerView來實現(xiàn)這個效果呢?如果你使用過SnapHelper的話,就會很好理解。


1.自定義LayoutManager,并且繼承LinearLayoutManager,這樣就得到一個可以水平排向或者豎向排向的布局策略。

如果你接觸過SnapHelper應(yīng)該了解一個LinearSnapHelper的類,可以實現(xiàn)讓列表的Item居中顯示的效果。但是這里我們不用這個類,我們要的效果是一次只能滑動一個Item,也就是一頁。PagerSnapHelper就可以做到哦。

@Override

public void onAttachedToWindow(RecyclerView view) {

super.onAttachedToWindow(view);

? ? mPagerSnapHelper.attachToRecyclerView(view);

this.mRecyclerView = view;

}

2.經(jīng)過第一步基本可以實現(xiàn)抖音的效果,但是寫完之后一會發(fā)現(xiàn),不知道哪里來開始播放視頻和在哪里釋放視頻。

不要著急,要監(jiān)聽滑動到哪頁,需要我們重寫onScrollStateChanged()函數(shù),這里面有三種狀態(tài):

SCROLL_STATE_IDLE(空閑)

SCROLL_STATE_DRAGGING(拖動)

SCROLL_STATE_SETTLING(要移動到最后位置時)

我們需要的就是RecyclerView停止時的狀態(tài),我們就可以拿到這個View的Position.注意這里還有一個問題,當你通過這個position去拿Item會報錯,這里涉及到RecyclerView的緩存機制,自己去腦補~~。

打印Log,你會發(fā)現(xiàn)RecyclerView.getChildCount()一直為1或者會出現(xiàn)為2的情況。好了,我們自己來實現(xiàn)一個接口然后通過接口把狀態(tài)傳遞出去。

監(jiān)聽器

publicinterface OnViewPagerListener {

/*釋放的監(jiān)聽*/

void onPageRelease(boolean isNext,int position);

/*選中的監(jiān)聽以及判斷是否滑動到底部*/

void onPageSelected(int position,boolean isBottom);

/*布局完成的監(jiān)聽*/

void onLayoutComplete();

}

獲取到RecyclerView空閑時選中的Item,重寫LinearLayoutManager的onScrollStateChanged方法

@Override

public void onScrollStateChanged(int state) {

switch(state) {

caseRecyclerView.SCROLL_STATE_IDLE:

View viewIdle = mPagerSnapHelper.findSnapView(this);

intpositionIdle = getPosition(viewIdle);

if(mOnViewPagerListener !=null&& getChildCount() ==1) {

mOnViewPagerListener.onPageSelected(positionIdle,positionIdle == getItemCount() -1);

? ? ? ? ?}

break;

caseRecyclerView.SCROLL_STATE_DRAGGING:

View viewDrag = mPagerSnapHelper.findSnapView(this);

intpositionDrag = getPosition(viewDrag);

break;

caseRecyclerView.SCROLL_STATE_SETTLING:

View viewSettling = mPagerSnapHelper.findSnapView(this);

intpositionSettling = getPosition(viewSettling);

break;

?}

}

3.列表的選中監(jiān)聽好了,我們就看看什么時候釋放視頻的資源,第二步中的三種狀態(tài),去打印getChildCount()的日志,你會發(fā)現(xiàn)getChildCount()在:

SCROLL_STATE_DRAGGING會為1

SCROLL_STATE_SETTLING為2

SCROLL_STATE_IDLE有時為1,有時為2

還是RecyclerView的緩存機制,這里不會去贅述緩存機制,我們要做的是要知道在什么時候去做釋放視頻的操作,還要分清是釋放上一頁還是下一頁,因為適配器adapter的position在這里不好使嘛,這里有兩個方法scrollHorizontallyBy()和scrollVerticallyBy()可以拿到滑動偏移量,可以判斷滑動方向,好~ 齊活了。

看代碼:

/**

?* 監(jiān)聽豎直方向的相對偏移量

?* @param dy

?* @param recycler

?* @param state

?* @return

?*/

@Override

public int scrollVerticallyBy(int dy, RecyclerView.Recycler recycler, RecyclerView.State state) {

this.mDrift = dy;

returnsuper.scrollVerticallyBy(dy, recycler, state);

}

/**

?* 監(jiān)聽水平方向的相對偏移量

?* @param dx

?* @param recycler

?* @param state

?* @return

?*/

@Override

public int scrollHorizontallyBy(int dx, RecyclerView.Recycler recycler, RecyclerView.State state) {

this.mDrift = dx;

returnsuper.scrollHorizontallyBy(dx, recycler, state);

}

// 可以釋放資源的監(jiān)聽,也就是回收Item的時候

privateRecyclerView.OnChildAttachStateChangeListener mChildAttachStateChangeListener =newRecyclerView.OnChildAttachStateChangeListener() {

@Override

public void onChildViewAttachedToWindow(View view) {

? ? }

@Override

public void onChildViewDetachedFromWindow(View view) {

if(mDrift >=0){

if(mOnViewPagerListener !=null) mOnViewPagerListener.onPageRelease(true,getPosition(view));

}else{

if(mOnViewPagerListener !=null) mOnViewPagerListener.onPageRelease(false,getPosition(view));

? ? ? ? }

? ? }

};

大功告成。

是不是覺得很不可思議就好了,貼一哈具體使用的代碼,初始化視頻和釋放視頻的地方:

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

? ?setContentView(R.layout.activity_view_pager_layout_manager);

? ?initView();

? ?initListener();

}

private void initView() {

? ?mRecyclerView = findViewById(R.id.recycler);

mLayoutManager =newViewPagerLayoutManager(this, OrientationHelper.VERTICAL);

mAdapter =newMyAdapter();

? ?mRecyclerView.setLayoutManager(mLayoutManager);

? ?mRecyclerView.setAdapter(mAdapter);

}

private void initListener(){

mLayoutManager.setOnViewPagerListener(newOnViewPagerListener() {

@Override

public void onPageRelease(boolean isNext,int position) {

Log.e(TAG,"釋放位置:"+position +" 下一頁:"+isNext);

intindex =0;

if(isNext){

index =0;

}else{

index =1;

? ? ? ? ? ?}

? ? ? ? ? ?releaseVideo(index);

? ? ? ?}

@Override

public void onPageSelected(int position,boolean isBottom) {

Log.e(TAG,"選中位置:"+position+" ?是否是滑動到底部:"+isBottom);

playVideo(0);

? ? ? ?}

@Override

public void onLayoutComplete() {

playVideo(0);

? ? ? ?}

? ?});

代碼下載:https://github.com/TangfeiJi/DouYinViewPager

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容