Android实现网易严选标签栏滑动效果

  

标签栏是一个非常常见的控件,似乎也是一个比较简单的控件,但如果在标签下方加个下划线的话,就还是可以玩出挺多花来的。

  

 Android实现网易严选标签栏滑动效果

  

网易严选的标签栏就做的很不错,里面隐藏着诸多细节:

  
      <李>手动滑动页面,下划线会跟着滑动。   <李>选择一个标签后,下划线会有滑动过去的动画。   <李>选择最左端或最右端的标签,标签栏会进行滑动,使得标签向中间靠拢(如果可以滑的话)。   
  

仔细分析下,需要在简单标签栏的基础上实现以下逻辑:
  

  
      <李>画出下划线。   <李>监听手动滑动页面事件,实时更新下划线位置。   <李>切换标签时,开始下划线滑动的动画,并判断是否要同时滑动标签栏。   
  

 Android实现网易严选标签栏滑动效果

  

我做了一个样例程序,其中的较难点在于计算下划线的位置,和下划线的动画效果。

     //根据当前选定的选项卡,得到指示器应该移动到的位置   私人Pair<浮动,Float>getIndicatorTargetLeftRight (int位置,浮动positionOffset) {   视图选项卡=tabsContainer.getChildAt(位置);   Float> Pair<浮动;指标=getIndicatorLeftRight(选项卡);   浮动targetLeft=indicator.first;   浮动targetRight=indicator.second;//如果positionOffset不为0,指标正处于两个选项卡之间,需进行加权计算得到它的位置   如果(positionOffset比;0 f,,位置& lt;tabCount - 1) {   视图nextTab=tabsContainer。getChildAt(位置+ 1);   Float> Pair<浮动;indicatorForNextTab=getIndicatorLeftRight (nextTab);   左浮动=indicatorForNextTab.first;   浮动对=indicatorForNextTab.second;   targetLeft=(positionOffset *左+ (1 f - positionOffset) * targetLeft);   targetRight=(positionOffset *右+ (1 f - positionOffset) * targetRight);   }   返回新Pair<祝辞(targetLeft targetRight);   }      私人Pair<浮动,Float>getIndicatorLeftRight(视图选项卡){   左浮动=tab.getLeft ();   浮动对=tab.getRight ();   如果(indicatorMode==indicatorMode。包装,,选项卡instanceof TextView) {   TextView tabTextView=(TextView)选项卡;   paint.setTextSize (tabTextView.getTextSize ());   .toString浮动textLength=paint.measureText (tabTextView.getText () ());   浮动中间=f(左+右)/2;   左=中等textLength/2 f;   正确的中产+ textLength/2=f;   }   返回新Pair<祝辞(左、右);   }   之前      

上面是计算下划线位置的代码,通过传入在onPageScrolled()中获得的位置和positionOffset,计算下划线是在某一个标签下,或者某两个标签之间的位置。需要注意的是,由于各标签的长度可能不一,所以下划线的长度在滑动中也可能发生变化,所以需分别计算下划线的左和右。

        私人布尔isAnimateRunning=false;   私有静态最终字符串TARGET_LEFT=皌argetLeft”;   私有静态最终字符串TARGET_RIGHT=皌argetRight”;      私人空间startIndicatorAnimate(最后targetLeft浮动,最终浮targetRight) {//在指标超出屏幕范围时,让其从屏幕边界处开始移动   漂浮移动=0;   如果(indicatorCurrentRight & lt;getScrollX ()) {   移动=getScrollX () - indicatorCurrentRight;   }else if (indicatorCurrentLeft比;getScrollX () + DimenUtil.getScreenWidth (getContext ())) {   移动=getScrollX () + DimenUtil.getScreenWidth (getContext ()) - indicatorCurrentLeft;   }   indicatorCurrentLeft +=移动;   indicatorCurrentRight +=移动;      PropertyValuesHolder valuesHolderLeft=PropertyValuesHolder.ofFloat (   TARGET_LEFT、indicatorCurrentLeft targetLeft);   PropertyValuesHolder valuesHolderRight=PropertyValuesHolder.ofFloat (   TARGET_RIGHT、indicatorCurrentRight targetRight);   ValueAnimator动画=ValueAnimator。ofPropertyValuesHolder (valuesHolderLeft valuesHolderRight)   .setDuration (SCROLL_DURATION);   动画师。addUpdateListener(新ValueAnimator.AnimatorUpdateListener () {   @Override   公共空间onAnimationUpdate (ValueAnimator动画){   如果(indicatorCurrentLeft !=targetLeft) {   indicatorCurrentLeft=(浮动)animation.getAnimatedValue (TARGET_LEFT);   }   如果(indicatorCurrentRight !=targetRight) {   indicatorCurrentRight=(浮动)animation.getAnimatedValue (TARGET_RIGHT);   }   如果(indicatorCurrentLeft==targetLeft,,indicatorCurrentRight==targetRight) {   isAnimateRunning=false;   }   无效();   }   });   animator.start ();   isAnimateRunning=true;   }   

Android实现网易严选标签栏滑动效果