前言
因為最近手上項目也是資訊閱讀類,簡書,掘金,知乎的效果都想往項目上加,沒事就來仿寫。

選項卡動態(tài)隱藏.gif
效果呢,和知乎首頁一樣,可以去知乎看看;點擊back鍵可以返回頂部。下面話不多說了,來一起看看詳細的介紹吧。
想法:
步驟:
要寫多少代碼呢? fragmeng中一個recycleView的監(jiān)聽要寫,一個接口要寫;activity中接口實現(xiàn)。沒了,代碼不多。
Fragment:
public interface RvScrollListener { //滑動方向監(jiān)聽 void scrollType(boolean direction); //是否滑動到頂部監(jiān)聽 void inTop(boolean top,RecyclerView recyclerView);}private RecyclerView.OnScrollListener mOnScrollListener = new RecyclerView.OnScrollListener() { @Override public void onScrollStateChanged(RecyclerView recyclerView, int newState) { super.onScrollStateChanged(recyclerView, newState); if (fragmentposition != 0) { //如果不是第一個fragment則返回 return; } LinearLayoutManager layoutManager = (LinearLayoutManager) recyclerView.getLayoutManager(); //得到當前列表第一個完全顯示的item的position int position = layoutManager.findFirstCompletelyVisibleItemPosition(); if (position == 0) { //如果position為0表示列表正處于頂部 mRvScrollListener.inTop(true, recyclerView); } else { mRvScrollListener.inTop(false, recyclerView); } } @Override public void onScrolled(RecyclerView recyclerView, int dx, int dy) { super.onScrolled(recyclerView, dx, dy); //判斷滑動方向,recycleView item 上拉 下滑不同動畫 if (dy > 0) { isUp = true; } else { isUp = false; } if (fragmentposition != 0) { return; //如果不是第一個fragment則返回 } //過濾掉一些緩慢的滑動 if (Math.abs(dy) > 10) { //滑動方向 mRvScrollListener.scrollType(dy > 0); } }};recycleView第一個監(jiān)聽方法:
@Overridepublic void onScrollStateChanged(RecyclerView recyclerView, int newState) {}這個里面就做一件事情,判斷當前recycleView是否滑動到頂部,然后通過接口傳遞到activity中,當點擊back鍵時,如果不在頂部,則調(diào)用方法滾動到頂部。
recycleView第二個監(jiān)聽方法:
@Overridepublic void onScrolled(RecyclerView recyclerView, int dx, int dy) {}做2件事,一是recyleView的item做動畫時,因為上拉和下滑動畫不一樣,代碼中 isUp 就是用來區(qū)分上拉下滑的((給recycleView的item做加載動畫使用));
二是判斷滑動方向,接口傳遞到activity中。
Activity:
//上拉狀態(tài)private boolean hasup = true;//下滑狀態(tài)private boolean hasdown = true;//是否在頂部private boolean inTop = true;//從fragment傳遞過來的recycleViewprivate RecyclerView topRecyclerView;BlankFragment.RvScrollListener mRvScrollListener = new BlankFragment.RvScrollListener() { @Override public void scrollType(boolean direction) { //上拉 if (direction) { hasdown = true; //連續(xù)上拉,第一次有效 if (hasup) { ObjectAnimator.ofFloat(mTablayout, View.TRANSLATION_Y, mTablayout.getTranslationY(), PixelChange.dp2px(XjwTablayoutActivity.this, 50)).setDuration(400).start(); hasup = false; } } else {//下滑 hasup = true; //連續(xù)下滑,第一次有效 if (hasdown) { ObjectAnimator.ofFloat(mTablayout, View.TRANSLATION_Y, mTablayout.getTranslationY(), 0).setDuration(400).start(); hasdown = false; } } } @Override public void inTop(boolean top, RecyclerView recyclerView) { inTop = top; topRecyclerView = recyclerView; }};@Overridepublic boolean onKeyDown(int keyCode, KeyEvent event) { //點擊返回鍵 if (keyCode == KeyEvent.KEYCODE_BACK) { //如果當前不是第一個fragmeng則顯示第一個 if (mViewPager.getCurrentItem() != 0) { mViewPager.setCurrentItem(0); return true; } //如果當前recycleView沒有在頂部則返回頂部 if (!inTop) { topRecyclerView.smoothScrollToPosition(0); return true; } } return super.onKeyDown(keyCode, event);}實現(xiàn)接口第一個方法:
@Overridepublic void scrollType(boolean direction) {}方法里用到三個boolean值 direction ,hasup, hasdown ,direction判斷執(zhí)行上拉動畫或者下滑動畫;hasup和hasdown作用是:滑動有上拉,下滑2個狀態(tài),處于一種狀態(tài)時動畫只執(zhí)行一次;比如列表正在持續(xù)上拉,監(jiān)聽也會觸發(fā)多次,上拉的多次觸動中只執(zhí)行一次動畫。
實現(xiàn)接口第二個方法:
@Overridepublic void inTop(boolean top, RecyclerView recyclerView) {}就一個賦值作用,用在back鍵的點擊事件中onKeyDown。
back鍵點擊
@Overridepublic boolean onKeyDown(int keyCode, KeyEvent event) {} 一點需要注意:recycleView滾動到頂部,調(diào)用的是smoothScrollToPosition()方法,這個最簡單,調(diào)用別的方法譬如smoothScrollBy() ,還需要算距離,不過這個方法可以給插值器。
屬性動畫
//隱藏ObjectAnimator.ofFloat(mTablayout, View.TRANSLATION_Y, mTablayout.getTranslationY(), PixelChange.dp2px(XjwTablayoutActivity.this, 50)).setDuration(400).start();//顯示 ObjectAnimator.ofFloat(mTablayout, View.TRANSLATION_Y, mTablayout.getTranslationY(), 0).setDuration(400).start();
注意2個點,一個是 View.TRANSLATION_Y 這個參數(shù)要寫對,
另外一個是動畫的起始值:
如果隱藏動畫是從0dp移動到50dp,快速切換上拉下滑狀態(tài)時(手指快速上下滑動)控件就會閃。所以隱藏動畫中從 mTablayout.getTranslationY()的位置移動到 50 dp的位置,動態(tài)獲取當前選項卡位置就好了,顯示動畫同理。(寫50dp是因為我選項卡高度就是50dp)
另外把recycleView的item加載動畫代碼給出來:(這個寫在Adapter里面的,因為要在onBindViewHolder時調(diào)用)
protected Animator[] getAnimators(View view) { //上滑動畫 return new Animator[]{ ObjectAnimator.ofFloat(view, View.ROTATION, 120, 0).setDuration(400) };}protected Animator[] getAnimatorsDown(View view) { //下拉動畫 return new Animator[]{ ObjectAnimator.ofFloat(view, View.TRANSLATION_Y, -100, 0).setDuration(400), ObjectAnimator.ofFloat(view, View.SCALE_X, 0.7f, 1f).setDuration(400) };}@Overridepublic void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { if (isUp) { //上拉 Animator[] animators = getAnimators(holder.itemView); if (animators.length > 1) { AnimatorSet animatorSet = new AnimatorSet(); animatorSet.playTogether(animators); animatorSet.start(); } else { for (Animator annimator : animators) { annimator.start(); } } } else {//下拉 Animator[] animatorsDown = getAnimatorsDown(holder.itemView); if (animatorsDown.length > 1) { AnimatorSet animatorSet = new AnimatorSet(); animatorSet.playTogether(animatorsDown); animatorSet.start(); } else { for (Animator annimator : animatorsDown) { annimator.start(); } } }} item加載動畫和選項卡顯隱動畫差不多,你可以把 View.SCALE_X 這種參數(shù)改一改,多試試效果,注意起始值。
總結(jié)
以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學習或者工作具有一定的參考學習價值,如果有疑問大家可以留言交流,謝謝大家對VEVB武林網(wǎng)的支持。
新聞熱點
疑難解答
圖片精選