您好,登錄后才能下訂單哦!
這篇文章主要介紹了如何使用Android實現知乎選項卡動態隱藏效果,具有一定借鑒價值,感興趣的朋友可以參考下,希望大家閱讀完這篇文章之后大有收獲,下面讓小編帶著大家一起了解一下。
前言
因為最近手上項目也是資訊閱讀類,簡書,掘金,知乎的效果都想往項目上加,沒事就來仿寫。
選項卡動態隱藏.gif
效果呢,和知乎首頁一樣,可以去知乎看看;點擊back鍵可以返回頂部。下面話不多說了,來一起看看詳細的介紹吧。
想法:
列表上拉,選項卡隱藏,下滑出現;recycleView滾動監聽(OnScrollListener)中onScrolled方法的dy參數,dy>0表示上拉,dy<0表示下滑,剛好合適。
選項卡怎么隱藏呢,屬性動畫,移動選項卡的相對位置View.TRANSLATION_Y(Y軸方向移動肯定是_Y),View.TRANSLATION系列都是相對運動,參考系是view原本的位置。
還有個問題,對于選項卡來說,它需要的顯隱時機是列表滑動方向改變,而不是只監聽它的滑動;上拉改下滑,下滑改上拉這2個時機才能執行動畫,不能在列表同一方向持續滾動時重復調用動畫。
步驟:
要寫多少代碼呢? fragmeng中一個recycleView的監聽要寫,一個接口要寫;activity中接口實現。沒了,代碼不多。
Fragment:
public interface RvScrollListener { //滑動方向監聽 void scrollType(boolean direction); //是否滑動到頂部監聽 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第一個監聽方法:
@Override public void onScrollStateChanged(RecyclerView recyclerView, int newState) {}
這個里面就做一件事情,判斷當前recycleView是否滑動到頂部,然后通過接口傳遞到activity中,當點擊back鍵時,如果不在頂部,則調用方法滾動到頂部。
recycleView第二個監聽方法:
@Override public void onScrolled(RecyclerView recyclerView, int dx, int dy) {}
做2件事,一是recyleView的item做動畫時,因為上拉和下滑動畫不一樣,代碼中 isUp 就是用來區分上拉下滑的((給recycleView的item做加載動畫使用));
二是判斷滑動方向,接口傳遞到activity中。
Activity:
//上拉狀態 private boolean hasup = true; //下滑狀態 private boolean hasdown = true; //是否在頂部 private boolean inTop = true; //從fragment傳遞過來的recycleView private RecyclerView topRecyclerView; BlankFragment.RvScrollListener mRvScrollListener = new BlankFragment.RvScrollListener() { @Override public void scrollType(boolean direction) { //上拉 if (direction) { hasdown = true; //連續上拉,第一次有效 if (hasup) { ObjectAnimator.ofFloat(mTablayout, View.TRANSLATION_Y, mTablayout.getTranslationY(), PixelChange.dp2px(XjwTablayoutActivity.this, 50)).setDuration(400).start(); hasup = false; } } else {//下滑 hasup = true; //連續下滑,第一次有效 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; } }; @Override public 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); }
實現接口第一個方法:
@Override public void scrollType(boolean direction) {}
方法里用到三個boolean值 direction ,hasup, hasdown ,direction判斷執行上拉動畫或者下滑動畫;hasup和hasdown作用是:滑動有上拉,下滑2個狀態,處于一種狀態時動畫只執行一次;比如列表正在持續上拉,監聽也會觸發多次,上拉的多次觸動中只執行一次動畫。
實現接口第二個方法:
@Override public void inTop(boolean top, RecyclerView recyclerView) {}
就一個賦值作用,用在back鍵的點擊事件中onKeyDown。
back鍵點擊
@Override public boolean onKeyDown(int keyCode, KeyEvent event) {}
一點需要注意:recycleView滾動到頂部,調用的是smoothScrollToPosition()
方法,這個最簡單,調用別的方法譬如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 這個參數要寫對,
另外一個是動畫的起始值:
如果隱藏動畫是從0dp移動到50dp,快速切換上拉下滑狀態時(手指快速上下滑動)控件就會閃。所以隱藏動畫中從 mTablayout.getTranslationY()
的位置移動到 50 dp的位置,動態獲取當前選項卡位置就好了,顯示動畫同理。(寫50dp是因為我選項卡高度就是50dp)
另外把recycleView的item加載動畫代碼給出來:(這個寫在Adapter里面的,因為要在onBindViewHolder時調用)
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) }; } @Override public 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
這種參數改一改,多試試效果,注意起始值。
感謝你能夠認真閱讀完這篇文章,希望小編分享的“如何使用Android實現知乎選項卡動態隱藏效果”這篇文章對大家有幫助,同時也希望大家多多支持億速云,關注億速云行業資訊頻道,更多相關知識等著你來學習!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。