日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網(wǎng)為廣大站長提供免費收錄網(wǎng)站服務,提交前請做好本站友鏈:【 網(wǎng)站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(50元/站),

點擊這里在線咨詢客服
新站提交
  • 網(wǎng)站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會員:747

你們說的抖音效果是怎樣實現(xiàn)的!程序員:java面前都不是事

 

有朋友問,抖音的視頻效果怎么實現(xiàn),今天看到了作者做了一個實現(xiàn),真讓人感嘆:

sorry, RecyclerView真的可以為所欲為!文末附小編整理的JAVA的一些干貨敬請領取吧

首先看作者實現(xiàn)的抖音的效果:

 

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

有沒有更好的方式呢???

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

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

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

如果你接觸過SnapHelper應該了解一個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)聽器

public interface 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) {
 case RecyclerView.SCROLL_STATE_IDLE:
 View viewIdle = mPagerSnapHelper.findSnapView(this);
 int positionIdle = getPosition(viewIdle);
 if (mOnViewPagerListener != null && getChildCount() == 1) {
 mOnViewPagerListener.onPageSelected(positionIdle,positionIdle == getItemCount() - 1);
 }
 break;
 case RecyclerView.SCROLL_STATE_DRAGGING:
 View viewDrag = mPagerSnapHelper.findSnapView(this);
 int positionDrag = getPosition(viewDrag);
 break;
 case RecyclerView.SCROLL_STATE_SETTLING:
 View viewSettling = mPagerSnapHelper.findSnapView(this);
 int positionSettling = 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;
 return super.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;
 return super.scrollHorizontallyBy(dx, recycler, state);
 }
// 可以釋放資源的監(jiān)聽,也就是回收Item的時候
private RecyclerView.OnChildAttachStateChangeListener mChildAttachStateChangeListener = new RecyclerView.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 = new ViewPagerLayoutManager(this, OrientationHelper.VERTICAL);
 mAdapter = new MyAdapter();
 mRecyclerView.setLayoutManager(mLayoutManager);
 mRecyclerView.setAdapter(mAdapter);
}
private void initListener(){
 mLayoutManager.setOnViewPagerListener(new OnViewPagerListener() {
 @Override
 public void onPageRelease(boolean isNext,int position) {
 Log.e(TAG,"釋放位置:"+position +" 下一頁:"+isNext);
 int index = 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);
 }
 });
}

作者也曾指出,更多效果,等你來補充。最近的姿勢還是學會作者自定義LayoutManager的方式,掌握真正的內(nèi)功心法。

分享到:
標簽:音效
用戶無頭像

網(wǎng)友整理

注冊時間:

網(wǎng)站:5 個   小程序:0 個  文章:12 篇

  • 51998

    網(wǎng)站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會員

趕快注冊賬號,推廣您的網(wǎng)站吧!
最新入駐小程序

數(shù)獨大挑戰(zhàn)2018-06-03

數(shù)獨一種數(shù)學游戲,玩家需要根據(jù)9

答題星2018-06-03

您可以通過答題星輕松地創(chuàng)建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學四六

運動步數(shù)有氧達人2018-06-03

記錄運動步數(shù),積累氧氣值。還可偷

每日養(yǎng)生app2018-06-03

每日養(yǎng)生,天天健康

體育訓練成績評定2018-06-03

通用課目體育訓練成績評定