最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

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

 更新時間:2017年07月18日 15:55:05   作者:wlkdb  
這篇文章主要為大家詳細(xì)介紹了Android實現(xiàn)網(wǎng)易嚴(yán)選標(biāo)簽欄滑動效果,具有一定的參考價值,感興趣的小伙伴們可以參考一下

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

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

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

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

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

我做了一個樣例程序,其中的較難點在于計算下劃線的位置,和下劃線的動畫效果。

// 根據(jù)當(dāng)前選定的tab,得到indicator應(yī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正處于兩個tab之間,需進行加權(quán)計算得到它的位置 
  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); 
} 

上面是計算下劃線位置的代碼,通過傳入在onPageScrolled()中獲得的position和positionOffset,計算下劃線是在某一個標(biāo)簽下,或者某兩個標(biāo)簽之間的位置。需要注意的是,由于各標(biāo)簽的長度可能不一,所以下劃線的長度在滑動中也可能發(fā)生變化,所以需分別計算下劃線的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超出屏幕范圍時,讓其從屏幕邊界處開始移動 
  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)簽時下劃線運行滑動動畫的代碼,使用ValueAnimator實現(xiàn),并且對下劃線超出邊界的情況做了特殊處理,以防止滑動距離過大時,滑動速度過快。

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

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • Android DrawableTextView圖片文字居中顯示實例

    Android DrawableTextView圖片文字居中顯示實例

    在我們開發(fā)中,TextView設(shè)置Android:drawableLeft一定使用的非常多,但Drawable和Text同時居中顯示可能不好控制,小編想到通過自定義TextView實現(xiàn),具體詳情大家參考下本文
    2017-03-03
  • Android圓角頭像工具類詳解

    Android圓角頭像工具類詳解

    這篇文章主要為大家詳細(xì)介紹了Android圓角頭像工具類,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-07-07
  • Android仿微信選擇圖片和拍照功能

    Android仿微信選擇圖片和拍照功能

    這篇文章主要為大家詳細(xì)介紹了Android仿微信選擇圖片和拍照功能,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2016-11-11
  • Android 中 ThreadLocal使用示例

    Android 中 ThreadLocal使用示例

    這篇文章主要介紹了Android 中 ThreadLocal使用示例的相關(guān)資料,這里提供示例代碼幫助大家學(xué)習(xí)理解這部分內(nèi)容,需要的朋友可以參考下
    2017-09-09
  • 詳解android webView獨立進程通訊方式

    詳解android webView獨立進程通訊方式

    本篇文章主要介紹了android webView獨立進程通訊方式,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-09-09
  • Android仿小米安全中心檢測進度條效果

    Android仿小米安全中心檢測進度條效果

    這篇文章主要介紹了Android仿小米安全中心檢測進度條效果,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2016-10-10
  • Android Mms之:PDU的使用詳解

    Android Mms之:PDU的使用詳解

    本篇文章是對PDU的使用進行了詳細(xì)的分析介紹,需要的朋友參考下
    2013-05-05
  • 基于Manifest.xml中不要出現(xiàn)重復(fù)的uses permission的說明

    基于Manifest.xml中不要出現(xiàn)重復(fù)的uses permission的說明

    本篇文章對Manifest.xml中不要出現(xiàn)重復(fù)的uses permission進行了介紹。需要的朋友參考下
    2013-05-05
  • Android中實現(xiàn)ping功能的多種方法詳解

    Android中實現(xiàn)ping功能的多種方法詳解

    這篇文章主要介紹了Android中實現(xiàn)ping功能的多種方法詳解,本文通過實例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-03-03
  • Android FlowLayout流式布局實現(xiàn)詳解

    Android FlowLayout流式布局實現(xiàn)詳解

    這篇文章主要為大家詳細(xì)介紹了Android FlowLayout流式布局的實現(xiàn)方法,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-09-09

最新評論

旌德县| 清苑县| 将乐县| 大城县| 崇义县| 日土县| 西盟| 梅河口市| 郴州市| 利津县| 柞水县| 内黄县| 太谷县| 正镶白旗| 通河县| 巨野县| 金溪县| 盈江县| 鄂托克前旗| 芮城县| 五莲县| 满洲里市| 永兴县| 密山市| 建湖县| 晋宁县| 英超| 呼和浩特市| 莎车县| 吉安县| 平阴县| 沧州市| 雷山县| 金湖县| 广州市| 通河县| 子洲县| 抚顺县| 河源市| 松桃| 朝阳市|