Android-导航栏特效-新闻类APP(仿iOS版网易新闻今日头条的文字渐变缩放特效)

转载自:http://blog.csdn.net/ta893115871/article/details/44724953


最近工作中要实现类似 今日头条等新闻类APP顶部导航条的效果 ,不过我们这效果切换时要加上文字颜色的渐变和缩放。
git图片比较大,耐心等待哦,小宝贝~~







一:分析

今天我们要实现这种特效。

用到的开源项目有:master-nineoldandroids-library.jar这个jar包,这个是向下兼容的jar包,包括Android一系列的动画。

首先我们说一下这种 日头条等新闻类APP 的基本实现是ViewPage+Fragment+HorizontalScrollView

我们今天说的就是这个HorizontalScrollView的特效。

实现原理图:



相信大家已经明白了大概

就是:最初时我们 初始化textview  并把选中的和正常的textview 初始化。就是上图中的framelayout中的2个textview 放到集合 HashMap<String, View>()中。用于保持所有textview的状态。

至于代码怎么写呢?!

android系统给我们提供了一个叫PagerSlidingTabStrip的类,在v4包中。我们把Java中考出来放到我们的项目中,修改其中的代码就可以。

我们通过viewpage来控制导航条。把viewpage传到PagerSlidingTabStrip中,并设置监听器,代码如下:

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. public void setViewPager(ViewPager pager) {  
  2.         this.pager = pager;  
  3.   
  4.         if (pager.getAdapter() == null) {  
  5.             throw new IllegalStateException(  
  6.                     "ViewPager does not have adapter instance.");  
  7.         }  
  8.   
  9.         pager.setOnPageChangeListener(pageListener);  
  10.   
  11.         notifyDataSetChanged();  
  12.     }  

二、获取用户切换时当前View和切换至的目的View。

ViewPager也需要监听用户的手势,所以肯定提供了某个方法。于是纵观ViewPager的方法,发现了一个叫做 onPageScrolled(int position, float positionOffset, int positionOffsetPixels)的方法~~

没错就是这个方法:在页面滚动时调用~

下面仔细研究下这几个参数:

直接说测试结果:

在非第一页与最后一页时,滑动到下一页,position为当前页位置;滑动到上一页:position为当前页-1

positionOffset 滑动到下一页,[0,1)区间上变化;滑动到上一页:(1,0]区间上变化

positionOffsetPixels这个和positionOffset很像:滑动到下一页,[0,宽度)区间上变化;滑动到上一页:(宽度,0]区间上变化

第一页时:滑动到上一页position=0 ,其他基本为0 ;最后一页滑动到下一页 position为当前页位置,其他两个参数为0


豁然发现,我们需要的步骤的第二步解决了,positionOffset很适合作为,渐变,缩放的控制参数;positionOffsetPixels则可以作为平移等的控制参数。

那么如何获得当前View和目的View呢:

分享几个我的歧途:

1、【错误】我通过getChildAt(position),getChildAt(position+1),getChildAt(position-1)获得滑动时,左右的两个View;乍一看,还真觉得不错~~~在代码写出来,再乍效果也出不来~~错误原因:我们忽略一个特别大的东西,ViewPager的机制,滑动时动态加载和删除View,ViewPager其实只会维持2到3个View,而position的范围基本属于无限~~

2、【错误】我通过getCurrentItem获得当前的位置,然后+1,-1获得后一个或者前一个~~正在窃喜,赶快代码改过来,效果怎么也不对,乱七八糟的~~仔细观察日志,这个getCurrentItem当用户手指离开的屏幕,Page还在动画执行时,就改变了~~难怪~整个滑动过程并不是固定的~~唉,心都碎了~

3、【错误】position在整个滑动的过程中是不变化的,而且ViewPager会保存2个或3个View;那么我考虑,如果是第一页、或者最后一页那么我取getChildAt(0)和getChildAt(1),如果在其他页面则为getChildAt(0),getChildAt(2),然后经过一系列的变化~我想这会总该对了吧,于是我遇到第一问题,第一页的时候,不管左右position都为0,尼玛,这哪个为左View,哪个为右View~~

说了这么多错误,大家可以绕过这些弯路,也能从这些弯路里面看出点什么~

下面说正确的,其实ViewPager在添加一个View或者销毁一个View时,是我们自己的PageAdapter中控制的,于是我们可以在ViewPager里面维系一个HashMap<Position,View>,然后滑动的时候,通过get(position)取出,比如上述效果,始终是右边的View变化,要么从小到大,要么从大到小

那么滑倒下一页:左边的View:map.get(position) ,右边的View : map.get(position+1) . 

那么滑倒上一页:左边的View : map.get(position) , 右边的View : map.get(position+1) , 一样的,因为滑到上一页,position为当前页-1


关键代码:

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. <pre name="code" class="java">    private class PageListener implements OnPageChangeListener {  
  2.         private int oldPosition = 0;  
  3.   
  4.         @Override  
  5.         public void onPageScrolled(int position, float positionOffset,  
  6.                 int positionOffsetPixels) {  
  7.             currentPosition = position;  
  8.             currentPositionOffset = positionOffset;  
  9.   
  10.             scrollToChild(position, (int) (positionOffset * tabsContainer  
  11.                     .getChildAt(position).getWidth()));  
  12.   
  13.             invalidate();  
  14.   
  15.             if (delegatePageListener != null) {  
  16.                 delegatePageListener.onPageScrolled(position, positionOffset,  
  17.                         positionOffsetPixels);  
  18.             }  
  19.   
  20.             if (mState == State.IDLE && positionOffset > 0) {  
  21.                 oldPage = pager.getCurrentItem();  
  22.                 mState = position == oldPage ? State.GOING_RIGHT  
  23.                         : State.GOING_LEFT;  
  24.             }  
  25.             boolean goingRight = position == oldPage;  
  26.             if (mState == State.GOING_RIGHT && !goingRight)  
  27.                 mState = State.GOING_LEFT;  
  28.             else if (mState == State.GOING_LEFT && goingRight)  
  29.                 mState = State.GOING_RIGHT;  
  30.   
  31.             float effectOffset = isSmall(positionOffset) ? 0 : positionOffset;  
  32.   
  33.             View mLeft = tabsContainer.getChildAt(position);  
  34.             View mRight = tabsContainer.getChildAt(position + 1);  
  35.   
  36.             if (effectOffset == 0) {  
  37.                 mState = State.IDLE;  
  38.             }  
  39.   
  40.             if (mFadeEnabled)  
  41.                 animateFadeScale(mLeft, mRight, effectOffset, position);  
  42.   
  43.         }  
  44.   
  45.         @Override  
  46.         public void onPageScrollStateChanged(int state) {  
  47.             if (state == ViewPager.SCROLL_STATE_IDLE) {  
  48.                 scrollToChild(pager.getCurrentItem(), 0);  
  49.                 mFadeEnabled = true;  
  50.             }  
  51.   
  52.             if (delegatePageListener != null) {  
  53.                 delegatePageListener.onPageScrollStateChanged(state);  
  54.             }  
  55.         }  
  56.   
  57.         @Override  
  58.         public void onPageSelected(int position) {  
  59.             // selectedPosition = position;  
  60.             // updateTabStyles();  
  61.             currentPosition = position;  
  62.   
  63.             // set old view statue  
  64.             ViewHelper.setAlpha(tabViews.get(oldPosition).get("normal"), 1);  
  65.             ViewHelper.setAlpha(tabViews.get(oldPosition).get("selected"), 0);  
  66.             View v_old = tabsContainer.getChildAt(oldPosition);  
  67.             ViewHelper.setPivotX(v_old, v_old.getMeasuredWidth() * 0.5f);  
  68.             ViewHelper.setPivotY(v_old, v_old.getMeasuredHeight() * 0.5f);  
  69.             ViewHelper.setScaleX(v_old, 1f);  
  70.             ViewHelper.setScaleY(v_old, 1f);  
  71.   
  72.             // set new view statue  
  73.             ViewHelper.setAlpha(tabViews.get(position).get("normal"), 0);  
  74.             ViewHelper.setAlpha(tabViews.get(position).get("selected"), 1);  
  75.             View v_new = tabsContainer.getChildAt(position);  
  76.             ViewHelper.setPivotX(v_new, v_new.getMeasuredWidth() * 0.5f);  
  77.             ViewHelper.setPivotY(v_new, v_new.getMeasuredHeight() * 0.5f);  
  78.             ViewHelper.setScaleX(v_new, 1 + ZOOM_MAX);  
  79.             ViewHelper.setScaleY(v_new, 1 + ZOOM_MAX);  
  80.   
  81.             if (delegatePageListener != null) {  
  82.                 delegatePageListener.onPageSelected(position);  
  83.             }  
  84.             // oldPosition = selectedPosition;  
  85.             oldPosition = currentPosition;  
  86.   
  87.         }  
  88.   
  89.     }  


 

可以看到代码:缩放view很关键:

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. View v_old = tabsContainer.getChildAt(oldPosition);  
  2.             ViewHelper.setPivotX(v_old, v_old.getMeasuredWidth() * 0.5f);  
  3.             ViewHelper.setPivotY(v_old, v_old.getMeasuredHeight() * 0.5f);  
  4.             ViewHelper.setScaleX(v_old, 1f);  
  5.             ViewHelper.setScaleY(v_old, 1f);  
找到view的中心点即:setPivotX setPivotY 然后对X轴Y轴缩放。1为原始大小。>1放大,<1  且>0 缩小。

关键代码是:onPageScrolled 方法的底2个参数positionOffset 滑动的百分比。

渐变通过animateFadeScale这个方法控制:

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. protected void animateFadeScale(View left, View right,  
  2.         float positionOffset, int position) {  
  3.   
  4.     if (mState != State.IDLE) {  
  5.         if (left != null) {  
  6.             ViewHelper.setAlpha(tabViews.get(position).get("normal"),  
  7.                     positionOffset);  
  8.             ViewHelper.setAlpha(tabViews.get(position).get("selected"),  
  9.                     1 - positionOffset);  
  10.   
  11.             float mScale = 1 + ZOOM_MAX - ZOOM_MAX * positionOffset;  
  12.   
  13.             ViewHelper.setPivotX(left, left.getMeasuredWidth() * 0.5f);  
  14.             ViewHelper.setPivotY(left, left.getMeasuredHeight() * 0.5f);  
  15.             ViewHelper.setScaleX(left, mScale);  
  16.             ViewHelper.setScaleY(left, mScale);  
  17.   
  18.         }  
  19.         if (right != null) {  
  20.             ViewHelper.setAlpha(tabViews.get(position + 1).get("normal"),  
  21.                     1 - positionOffset);  
  22.             ViewHelper.setAlpha(tabViews.get(position + 1).get("selected"),  
  23.                     positionOffset);  
  24.   
  25.             float mScale = 1 + ZOOM_MAX * positionOffset;  
  26.   
  27.             ViewHelper.setPivotX(right, right.getMeasuredWidth() * 0.5f);  
  28.             ViewHelper.setPivotY(right, right.getMeasuredHeight() * 0.5f);  
  29.             ViewHelper.setScaleX(right, mScale);  
  30.             ViewHelper.setScaleY(right, mScale);  
  31.   
  32.         }  
  33.     }  
  34. }  



在你activity/引用的地方 中你可以直接设置TAB的颜色大小,正常色,选中色等。EG:

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. /** 
  2.      * 对PagerSlidingTabStrip的各项属性进行赋值。 
  3.      */  
  4.     private void setTabsValue() {  
  5.         // 设置Tab是自动填充满屏幕的  
  6.         tabs.setShouldExpand(true);  
  7.         // 设置Tab的分割线是透明的  
  8.         tabs.setDividerColor(Color.TRANSPARENT);  
  9.         // 设置Tab底部线的高度  
  10.         tabs.setUnderlineHeight((int) TypedValue.applyDimension(  
  11.                 TypedValue.COMPLEX_UNIT_DIP, 1, dm));  
  12.         // 设置Tab Indicator的高度  
  13.         tabs.setIndicatorHeight((int) TypedValue.applyDimension(  
  14.                 TypedValue.COMPLEX_UNIT_DIP, 4, dm));  
  15.         // 设置Tab标题文字的大小  
  16.         tabs.setTextSize((int) TypedValue.applyDimension(  
  17.                 TypedValue.COMPLEX_UNIT_SP, 16, dm));  
  18.         // 设置Tab Indicator的颜色  
  19.         tabs.setIndicatorColor(Color.parseColor("#45c01a"));  
  20.         // 设置选中Tab文字的颜色 (这是我自定义的一个方法)  
  21.         tabs.setSelectedTextColor(Color.parseColor("#45c01a"));  
  22.         //设置正常Tab文字的颜色 (这是我自定义的一个方法)  
  23.         tabs.setTextColor(Color.parseColor("#C231C7"));  
  24.         // 取消点击Tab时的背景色  
  25.         tabs.setTabBackground(0);  
  26.     }  


源码:

github地址:

https://github.com/ta893115871/PagerSlidingTabStrip 

注意:偷偷的告诉你最好去github地址哦,免费的,不要资源积

分。代码已经没有多余的类了。也可以直接食用依赖库,github上都有说明哦!

不要忘记start哦!!

csdn资源-源代码

源代码



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值