Android项目中用到Tab作为导航条切换页面的效果,我相信大家都用到过吧,但是在切换的时候,Tab下划线跟着手指滑动的比例而滑动,相关的两个Tab的文字的颜色根据手指的滑动,而发生颜色渐变的改变。

下面说一下原理:

整个实现的过程需要用到,viewpager+fragment+tab,另外tab下划线的滑动以及tab中文本的颜色的渐变,是根据viewpager的页面的滑动比例计算出来相对应的值,然后进行设置,下划线是设置margin—left来完成的,颜色的渐变是通过设置画笔的透明度来实现。

一、自定义TextView,根据页面滑动的比例,计算出文本的透明度,如果对自定义流程不太清楚,请向这里看过来:

Android自定义View流程:

package com.example.tab;import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.os.Looper;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.View;/*** 自定义textview,可以根据透明度改变其颜色* Created by xiaoyunfei on 16/4/7.*/
public class MyTextView extends View {/*** 文本,默认:微信*/private String mText = "微信";/*** 文本大小*/private int mTextSize = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 10f, getResources().getDisplayMetrics());/*** 文本颜色*/private int mColor = 0xff45C01A;/*** 透明度*/private float mAlpha = 0f;/*** 显示文本区域的矩形*/private Rect mTextRect;private Paint mPaint;public MyTextView(Context context) {this(context, null);}public MyTextView(Context context, AttributeSet attrs) {this(context, attrs, 0);}public MyTextView(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.change_color_icon_view, defStyleAttr, 0);int count = array.getIndexCount();for (int i = 0; i < count; i++) {int attr = array.getIndex(i);switch (attr) {case R.styleable.change_color_icon_view_color_://文本颜色mColor = array.getColor(attr, 0xff45C01A);break;case R.styleable.change_color_icon_view_text_://文本mText = array.getString(attr);break;case R.styleable.change_color_icon_view_textSize_://文本字号mTextSize = array.getDimensionPixelSize(attr, (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 10f, getResources().getDisplayMetrics()));break;}}array.recycle();mPaint = new Paint();mTextRect = new Rect();mPaint.setTextSize(mTextSize);mPaint.setColor(mColor);mPaint.getTextBounds(mText, 0, mText.length(), mTextRect);}/*** 设置透明度** @param alpha*/public void setmAlpha(float alpha) {this.mAlpha = alpha;invalidateView();}private void invalidateView() {if (Looper.getMainLooper() == Looper.myLooper()) {//因为Android UI操作是非线程安全的,所以invalidate()不能再子线程中执行,需要配合handler使用invalidate();} else {//可以在子线程中使用,因为其封装了handlerpostInvalidate();}}@Overrideprotected void onDraw(Canvas canvas) {//alpha:255--->0:完全不透明--->完全透明int alpha = (int) Math.ceil(255 * mAlpha);drawDefaultText(canvas, alpha);drawTargetText(canvas, alpha);}/*** 写入目标文本** @param canvas* @param alpha*/private void drawTargetText(Canvas canvas, int alpha) {mPaint.setColor(mColor);mPaint.setAlpha(alpha);int width = getMeasuredWidth();int height = getMeasuredHeight();int x = width / 2 - mTextRect.width() / 2;int y = height / 2 + mTextRect.height() / 2;canvas.drawText(mText, x, y, mPaint);}/*** 写入默认文本** @param canvas* @param alpha*/private void drawDefaultText(Canvas canvas, int alpha) {mPaint.setColor(0xff555555);mPaint.setAlpha(255 - alpha);int width = getMeasuredWidth();int height = getMeasuredHeight();int x = width / 2 - mTextRect.width() / 2;int y = height / 2 + mTextRect.height() / 2;canvas.drawText(mText, x, y, mPaint);}
}

下面我们来看一下,在activity中,如何实现根据viewpager的滑动,来实现tab的下划线的滑动、以及颜色透明度的设置:

package com.example.tab;import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.view.ViewPager;
import android.util.DisplayMetrics;
import android.view.View;
import android.widget.LinearLayout;import java.util.ArrayList;
import java.util.List;public class MainActivity extends FragmentActivity implements View.OnClickListener, ViewPager.OnPageChangeListener {private ViewPager mViewPager;private List<Fragment> mList = new ArrayList<Fragment>();private String[] tag = {"微信", "通讯录", "发现", "我"};private int currentIndex = 0;//上部tabprivate int[] mTextId = {R.id.text_1, R.id.text_2, R.id.text_3, R.id.text_4};private MyTextView[] mTextViews = new MyTextView[4];private View tabView;private LinearLayout.LayoutParams params;/*** tab下划线的宽度*/private int width;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);initViews();initTabLine();initData();}/*** 初始化tab下划线*/private void initTabLine() {params = (LinearLayout.LayoutParams) tabView.getLayoutParams();DisplayMetrics metrics = new DisplayMetrics();getWindowManager().getDefaultDisplay().getMetrics(metrics);width = metrics.widthPixels / 4;params.width = width;tabView.setLayoutParams(params);}/*** 初始化数据*/private void initData() {for (int i = 0; i < 4; i++) {TabFragment fragment = new TabFragment();Bundle bundle = new Bundle();bundle.putString("content", tag[i]);fragment.setArguments(bundle);mList.add(fragment);}MyPageAdapter adapter = new MyPageAdapter(getSupportFragmentManager(), mList);mViewPager.setAdapter(adapter);}/*** 初始化控件*/private void initViews() {mViewPager = (ViewPager) findViewById(R.id.viewpager);for (int i = 0; i < mTextId.length; i++) {mTextViews[i] = (MyTextView) findViewById(mTextId[i]);mTextViews[i].setOnClickListener(this);}tabView = findViewById(R.id.tab_view);mViewPager.addOnPageChangeListener(this);mTextViews[0].setmAlpha(1.0f);}@Overridepublic void onClick(View v) {resetOtherTab();setClickTab(v.getId());
//        switch (v.getId()) {
//            case R.id.tab_1:
//                setClickTab(0);
//                break;
//            case R.id.tab_2:
//                setClickTab(1);
//                break;
//            case R.id.tab_3:
//                setClickTab(2);
//                break;
//            case R.id.tab_4:
//                setClickTab(3);
//                break;
//        }}/*** 设置当前的tab** @param id*/private void setClickTab(int id) {int i = -1;//根据id获取到指定的tab的下下标for (int j = 0; j < mTextId.length; j++) {if (mTextId[j] == id) {i = j;break;}}if (i == -1)return;params.leftMargin = width * i;tabView.setLayoutParams(params);setTab(i);}/*** 设置当前的tab** @param i*/private void setTab(int i) {mViewPager.setCurrentItem(i, false);mTextViews[i].setmAlpha(1.0f);currentIndex = i;}/*** 重新设置tab值默认值*/private void resetOtherTab() {for (int i = 0; i < mTextId.length; i++) {mTextViews[i].setmAlpha(0f);}}@Overridepublic void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {//注:position大部分时间和左边的页面的下标一致;positionOffset以及positionOffsetPixels大部分时间和右边的页面占比保持一致
//        if (position == 0 && currentIndex == 0) {//0-->1
//            mTextViews[0].setmAlpha(1 - positionOffset);
//            mTextViews[1].setmAlpha(positionOffset);
//            params.leftMargin = (int) (width * positionOffset);
//        } else if (position == 0 && currentIndex == 1) {//1-->0
//            mTextViews[0].setmAlpha(1 - positionOffset);
//            mTextViews[1].setmAlpha(positionOffset);
//            params.leftMargin = (int) (-width * (1 - positionOffset) + width * currentIndex);
//        } else if (position == 1 && currentIndex == 1) {//1-->2
//            mTextViews[1].setmAlpha(1 - positionOffset);
//            mTextViews[2].setmAlpha(positionOffset);
//            params.leftMargin = (int) (width * positionOffset + width * currentIndex);
//        } else if (position == 1 && currentIndex == 2) {//2-->1
//            mTextViews[1].setmAlpha(1 - positionOffset);
//            mTextViews[2].setmAlpha(positionOffset);
//            params.leftMargin = (int) (-width * (1 - positionOffset) + width * currentIndex);
//        } else if (position == 2 && currentIndex == 2) {//2-->3
//            mTextViews[2].setmAlpha(1 - positionOffset);
//            mTextViews[3].setmAlpha(positionOffset);
//            params.leftMargin = (int) (width * positionOffset + width * currentIndex);
//        } else if (position == 2 && currentIndex == 3) {//3-->2
//            mTextViews[2].setmAlpha(1 - positionOffset);
//            mTextViews[3].setmAlpha(positionOffset);
//            params.leftMargin = (int) (-width * (1 - positionOffset) + width * currentIndex);
//        }//上面的代码可以抽成下面的一个方法pageScroll(position, positionOffset);}/*** viewpager滑动的时候设置顶部和底部tab的透明度以及顶部tab下划线的位置** @param position* @param positionOffset*/private void pageScroll(int position, float positionOffset) {if (position + 1 == mTextViews.length)//因为2-->3滑动的时候,在最后滚动结束的时候,position会突变成3(position大部分时候和左边的页面的下标一直),这样会造成下标越界return;mTextViews[position].setmAlpha(1 - positionOffset);mTextViews[position + 1].setmAlpha(positionOffset);if (position == currentIndex) {params.leftMargin = (int) (width * positionOffset + width * currentIndex);} else {params.leftMargin = (int) (-width * (1 - positionOffset) + width * currentIndex);}tabView.setLayoutParams(params);}@Overridepublic void onPageSelected(int position) {currentIndex = position;setTab(position);}@Overridepublic void onPageScrollStateChanged(int state) {}
}

其中,实现的核心代码,在viewpager添加的监听的回调方法

onPageScrolled(int position, float positionOffset, int positionOffsetPixels)中,如果对
viewpager添加的这个监听,需要做一点解释:

有什么不理解的地方,可以参考我的另外一篇博客:
ViewPager的setOnPageChangeListener方法详解,这里对viewpager滑动的监听做了详细的说明。
例如:从1-->2滑动:
params.leftMargin = (int) (width * positionOffset + width * currentIndex);
从这个可以看出来,leftMargin的值等于当前的距左的值(width*currentIndex)加上滑动比例对应的宽度
(width*positionOffset)。
mTextViews[position].setmAlpha(1 - positionOffset);
设置透明度。
mTextViews[position + 1].setmAlpha(positionOffset);

项目下载

Android滑动切换页面Tab文字颜色发生渐变效果相关推荐

  1. fragment+viewpager+tablayou实现滑动切换页面

    本文目标:实现滑动切换页面 首先,Tablayout控件就需要添加design library,在android studio中添加依赖  compile 'com.android.support:d ...

  2. Android 滑动切换(首页展示,图片、新闻自动切换,循环切换,自动和手动)

    最近做的项目,要用到滑动切换的效果,就是类似新闻客户端的图片一张一张的自动切换或者手动滑动切换,于是就搜集了一下资料,使用两种方式实现这样的效果,分别是ViewFlipper和ViewPager.这两 ...

  3. iOS开发------仿知乎上下滑动切换页面

    放松的时候看看知乎,生活不解的时候问问知乎,这貌似已经成为了生活中的一种习惯,它独特翻页方式也是本人喜欢的一个原因,通过上划与下滑进行页面的翻页,不必返回再进入下一个页面,显得非常的简介并且人性化,这 ...

  4. 基于 vue +better scroll滑动切换页面 并支持下拉刷新案例

    也是公司项目 ,内部app的资讯模块整改,改是不可能改的,之前还是用jquery.感觉越改越混乱,还是重做.就仿着今日头条.等资讯页面做了一个dome,话不多说,先看效果! 微信扫码预览 效果看完,感 ...

  5. 手机版html页面左右滑动切换页面,移动端手指左右滑动切换内容demo

    说在开头 最近移动端做了一个手指左右滑动切换内容的效果demo; 为了表示我的无私,决定分享给诸位:(详细代码见附件) 正文 先上html代码html> 穿衣助理 完成 整个页面ul部分是需要切 ...

  6. android滑动切换卡片,一步步实现Viewpager卡片翻页效果

    这个CardStackViewpager的灵感来自Github上面的 FlippableStackView开源项目,而我想实现的效果方向上刚好与FlippableStackView相反,而且细节上也有 ...

  7. Android——Fragment实例精讲——底部导航栏+ViewPager滑动切换页面

    说明: 实现效果: 1- 用ViewPager实现Fragmen之间的切换 2- 底部用RadioGroup实现,更方便的实现图片和字体颜色的改变,更方便的通过RadioButton的点击事件来控制页 ...

  8. android横向滑动换页,[转载]Android 左右滑动切换页面或Activity的效果实现

    3.重载onFling函数 Java代码   publicbooleanonFling(MotionEvent e1, MotionEvent e2,floatvelocityX, floatvelo ...

  9. 微信小程序 左右滑动切换页面(炫酷效果)以及点赞特效

    #效果图 gif放不上来..我就直接口述了..需要看具体效果戳GitHub>>>>>demo地址 首先左右滑动的时候整个页面会以动画效果切换(demo里是反转和水平淡出) ...

最新文章

  1. 1562. [NOI2009]变换序列【二分图】
  2. 第 3 章 镜像 - 014 - 镜像的缓存特性
  3. Python入门100题 | 第005题
  4. vsc系统是什么意思_电脑蓝屏是什么意思?蓝屏就一定要重装系统吗?你可不要弄错了...
  5. XCode 4.2(4.1)真机调试及生成IPA全攻略
  6. Java异常处理和常用类
  7. JaveWeb中实现分页的总结
  8. 简单的脚本控制面试题
  9. 简单工厂模式(Simple Factory Pattern)
  10. php 越权 漏洞,PHPYUN最新版多处SQL注入及越权操作二
  11. delphi连接sql server的字符串2011-10-11 16:07
  12. 【生活相关】三(米新江老师语录)
  13. h5 右下角浮动按钮_基于javascript实现右下角浮动广告效果
  14. 阿里矢量图库 当前页全选
  15. 上古卷轴5json文件修改_改进名称的新Tempering名称定制SSE
  16. pycharm配置连接服务器+python环境设置
  17. Python开发指南[1]之程序员计时小时钟(附源码)
  18. ddrk(ddrk)
  19. 怎样区分细菌性和病毒性感冒
  20. 交换内存SWAP使用率90%

热门文章

  1. android 启动视频,android 启动页面全屏播放视频
  2. CWnd和HWND的区别
  3. DB2表空间状态代码解释
  4. P3842 [TJOI2007]线段(线性dp,分类讨论)
  5. 基于JAVA广西科技大学第一附属医院陪护椅管理计算机毕业设计源码+数据库+lw文档+系统+部署
  6. 在Deepin 15.11系统中遇到微信版本过低不能登录的解决方法
  7. linux hd4000显卡驱动,AMD Radeon HD 2000/HD 3000/HD 4000系列显卡驱动怎么样
  8. 互联网金融牌照有哪些 金融牌照一览表
  9. 安卓玩机搞机技巧综合资源-----修改rom 制作rom 解包rom的一些问题解析【二十一】
  10. R6-1 Python人民币美元双向兑换 (10 分)习题解答