国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 系統(tǒng) > Android > 正文

Android實(shí)現(xiàn)網(wǎng)易嚴(yán)選標(biāo)簽欄滑動(dòng)效果

2019-12-12 02:26:57
字體:
供稿:網(wǎng)友

標(biāo)簽欄是一個(gè)非常常見的控件,似乎也是一個(gè)比較簡(jiǎn)單的控件,但如果在標(biāo)簽下方加個(gè)下劃線的話,就還是可以玩出挺多花來的。

網(wǎng)易嚴(yán)選的標(biāo)簽欄就做的很不錯(cuò),里面隱藏著諸多細(xì)節(jié):

  • 手動(dòng)滑動(dòng)頁面,下劃線會(huì)跟著滑動(dòng)。
  • 選擇一個(gè)標(biāo)簽后,下劃線會(huì)有滑動(dòng)過去的動(dòng)畫。
  • 選擇最左端或最右端的標(biāo)簽,標(biāo)簽欄會(huì)進(jìn)行滑動(dòng),使得標(biāo)簽向中間靠攏(如果可以滑的話)。

仔細(xì)分析下,需要在簡(jiǎn)單標(biāo)簽欄的基礎(chǔ)上實(shí)現(xiàn)以下邏輯:

  • 畫出下劃線。
  • 監(jiān)聽手動(dòng)滑動(dòng)頁面事件,實(shí)時(shí)更新下劃線位置。
  • 切換標(biāo)簽時(shí),開始下劃線滑動(dòng)的動(dòng)畫,并判斷是否要同時(shí)滑動(dòng)標(biāo)簽欄。

我做了一個(gè)樣例程序,其中的較難點(diǎn)在于計(jì)算下劃線的位置,和下劃線的動(dòng)畫效果。

// 根據(jù)當(dāng)前選定的tab,得到indicator應(yīng)該移動(dòng)到的位置 private Pair<Float, Float> getIndicatorTargetLeftRight(int position, float positionOffset) {   View tab = tabsContainer.getChildAt(position);   Pair<Float, Float> indicator = getIndicatorLeftRight(tab);   float targetLeft = indicator.first;   float targetRight = indicator.second;   // 如果positionOffset不為0,indicator正處于兩個(gè)tab之間,需進(jìn)行加權(quán)計(jì)算得到它的位置   if (positionOffset > 0f && position < tabCount - 1) {     View nextTab = tabsContainer.getChildAt(position + 1);     Pair<Float, Float> indicatorForNextTab = getIndicatorLeftRight(nextTab);     float left = indicatorForNextTab.first;     float right = indicatorForNextTab.second;     targetLeft = (positionOffset * left + (1f - positionOffset) * targetLeft);     targetRight = (positionOffset * right + (1f - positionOffset) * targetRight);   }   return new Pair<>(targetLeft, targetRight); }  private Pair<Float, Float> getIndicatorLeftRight(View tab) {   float left = tab.getLeft();   float right = tab.getRight();   if (indicatorMode == IndicatorMode.WRAP && tab instanceof TextView) {     TextView tabTextView = (TextView) tab;     paint.setTextSize(tabTextView.getTextSize());     float textLength = paint.measureText(tabTextView.getText().toString());     float middle = (left + right) / 2f;     left = middle - textLength / 2f;     right = middle + textLength / 2f;   }   return new Pair<>(left, right); } 

上面是計(jì)算下劃線位置的代碼,通過傳入在onPageScrolled()中獲得的position和positionOffset,計(jì)算下劃線是在某一個(gè)標(biāo)簽下,或者某兩個(gè)標(biāo)簽之間的位置。需要注意的是,由于各標(biāo)簽的長度可能不一,所以下劃線的長度在滑動(dòng)中也可能發(fā)生變化,所以需分別計(jì)算下劃線的left和right。

private boolean isAnimateRunning = false; private static final String TARGET_LEFT = "targetLeft"; private static final String TARGET_RIGHT = "targetRight";  private void startIndicatorAnimate(final float targetLeft, final float targetRight) {   // 在indicator超出屏幕范圍時(shí),讓其從屏幕邊界處開始移動(dòng)   float move = 0;   if (indicatorCurrentRight < getScrollX()) {     move = getScrollX() - indicatorCurrentRight;   } else if (indicatorCurrentLeft > getScrollX() + DimenUtil.getScreenWidth(getContext())) {     move = getScrollX() + DimenUtil.getScreenWidth(getContext()) - indicatorCurrentLeft;   }   indicatorCurrentLeft += move;   indicatorCurrentRight += move;    PropertyValuesHolder valuesHolderLeft = PropertyValuesHolder.ofFloat(       TARGET_LEFT, indicatorCurrentLeft, targetLeft);   PropertyValuesHolder valuesHolderRight = PropertyValuesHolder.ofFloat(       TARGET_RIGHT, indicatorCurrentRight, targetRight);   ValueAnimator animator = ValueAnimator.ofPropertyValuesHolder(valuesHolderLeft, valuesHolderRight)       .setDuration(SCROLL_DURATION);   animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {     @Override     public void onAnimationUpdate(ValueAnimator animation) {       if (indicatorCurrentLeft != targetLeft) {         indicatorCurrentLeft = (float) animation.getAnimatedValue(TARGET_LEFT);       }       if (indicatorCurrentRight != targetRight) {         indicatorCurrentRight = (float) animation.getAnimatedValue(TARGET_RIGHT);       }       if (indicatorCurrentLeft == targetLeft && indicatorCurrentRight == targetRight) {         isAnimateRunning = false;       }       invalidate();     }   });   animator.start();   isAnimateRunning = true; } 

這是切換標(biāo)簽時(shí)下劃線運(yùn)行滑動(dòng)動(dòng)畫的代碼,使用ValueAnimator實(shí)現(xiàn),并且對(duì)下劃線超出邊界的情況做了特殊處理,以防止滑動(dòng)距離過大時(shí),滑動(dòng)速度過快。

更多的細(xì)節(jié),請(qǐng)見https://github.com/wlkdb/page_sliding

以上就是本文的全部內(nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持武林網(wǎng)。

發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 南华县| 灌阳县| 东丽区| 沅江市| 襄汾县| 鸡泽县| 新泰市| 高要市| 新沂市| 铜鼓县| 井研县| 海南省| 朝阳区| 尉犁县| 安塞县| 玉山县| 莲花县| 丹巴县| 内乡县| 肇源县| 涿州市| 铜鼓县| 山东省| 西畴县| 阿荣旗| 赤壁市| 会东县| 曲靖市| 洱源县| 柳江县| 永顺县| 平和县| 青岛市| 台北县| 白玉县| 瓦房店市| 东兴市| 宁明县| 化州市| 宁明县| 年辖:市辖区|