android高仿微信底部导航栏
2017-05-08 19:29
477 查看
这几天在公司没什么工作,闲来没事写了一下关于微信底部渐变的导航,textview 是利用 ArgbEvaluator 实现颜色渐变的效果,图片渐变是自定义imageview 来设置透明度进行渐变的
本代码与其他实现的优越性:
代码简单容易看懂,对新手来说不是问题
直接可以copy到自己的项目中使用
首先看一下效果图
先了解一下ArgbEvaluator的使用,ArgbEvaluator俗称颜色计算器,举个栗子
float percentage = (float)i/100; //这个就是根据百分比来计算出颜色 ArgbEvaluator argb = new ArgbEvaluator(); int color = (int)argb.evaluate(percentage, Color.parseColor("#ffffff"),Color.parseColor("#000000")); findViewById(R.id.tv_simple).setBackgroundColor(color);
此栗子:当percentage为0的时候:color为纯白色,当percentage为1的时候:color为纯黑色, 当percentage从0-1变化的时候,颜色会从白色到黑色逐渐的变化
先看一自定义控件自定义imageView 不用再xml中设置src或者backgroud
在setImages的时候 就会传入两张图片, 一个是正常的,一个是选中状态下的图片. 实际上就是在此imageview上面画图片在 transformPage的时候,就会根据offset(偏移量)的大小来设置透明度,从而效果为渐变.
public class MyImageView extends ImageView { private Paint mPaint; private Bitmap mSelectedIcon; private Bitmap mNormalIcon; private Rect mSelectedRect; private Rect mNormalRect; private int mSelectedAlpha = 0; public MyImageView(Context context) { super(context); } public MyImageView(Context context, AttributeSet attrs) { super(context, attrs); } public MyImageView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } public final void setImages(int normal, int selected) { this.mNormalIcon = createBitmap(normal); // 拿到原图 this.mSelectedIcon = createBitmap(selected); int width = (int)getResources().getDimension(R.dimen.tab_image_weith); int heigh = (int)getResources().getDimension(R.dimen.tab_image_heigh); this.mNormalRect = new Rect(0, 0, width, heigh); //拿到画板的大小 也就是此控件的大小 this.mSelectedRect = new Rect(0, 0, width, heigh); this.mPaint = new Paint(); // 拿到画笔 } private Bitmap createBitmap(int resId) { return BitmapFactory.decodeResource(getResources(), resId); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); if (this.mPaint == null) { return; } this.mPaint.setAlpha(255 - this.mSelectedAlpha); canvas.drawBitmap(this.mNormalIcon, null, this.mNormalRect, this.mPaint); //开始在画板上画原图 // 也就是在这个控件上画bitmap this.mPaint.setAlpha(this.mSelectedAlpha); canvas.drawBitmap(this.mSelectedIcon, null, this.mSelectedRect, this.mPaint); } public final void changeSelectedAlpha(int alpha) { } /** * 当viewpager滑动的时候,也就是onPageScrolled调用的时候,再来调用此方法 * @param offset 偏移量 */ public final void transformPage(float offset) { this.mSelectedAlpha = (int) (255 * (1 - offset)); invalidate(); // 此方法调用就会从新走 onDraw方法 } }
之后我们看一下xml中,其实xml布局挺简单的,一看就懂,没错,就是上面一个ViewPgaer 下面一个LinearLayout 里面包裹着
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="kitrobot.com.wechat_bottom_navigation.MainActivity" android:orientation="vertical"> <android.support.v4.view.ViewPager android:layout_weight="1" android:id="@+id/vp" android:layout_width="match_parent" android:layout_height="0dp"></android.support.v4.view.ViewPager> <LinearLayout android:paddingTop="10dp" android:background="#ffffff" android:orientation="horizontal" android:id="@+id/rg" android:layout_width="match_parent" android:layout_height="60dp"> <LinearLayout android:id="@+id/ll_home" android:layout_weight="1" android:layout_width="0dp" android:layout_height="match_parent" android:orientation="vertical"> <kitrobot.com.wechat_bottom_navigation.view.MyImageView android:layout_gravity="center" android:id="@+id/iv1" android:layout_width="30dp" android:layout_height="30dp"/> <TextView android:gravity="center" android:text="微信" android:button="@null" android:id="@+id/rb1" android:layout_width="match_parent" android:layout_height="match_parent"/> </LinearLayout> <LinearLayout android:id="@+id/ll_categroy" android:layout_weight="1" android:layout_width="0dp" android:layout_height="match_parent" android:orientation="vertical"> <kitrobot.com.wechat_bottom_navigation.view.MyImageView android:layout_gravity="center" android:id="@+id/iv2" android:layout_width="30dp" android:layout_height="30dp"/> <TextView android:gravity="center" android:text="通信录" android:button="@null" android:id="@+id/rb2" android:layout_width="match_parent" android:layout_height="match_parent"/> </LinearLayout> <LinearLayout android:id="@+id/ll_find" android:layout_weight="1" android:layout_width="0dp" android:layout_height="match_parent" android:orientation="vertical"> <kitrobot.com.wechat_bottom_navigation.view.MyImageView android:layout_gravity="center" android:id="@+id/iv3" android:layout_width="30dp" android:layout_height="30dp"/> <TextView androi 4000 d:gravity="center" android:text="发现" android:button="@null" android:id="@+id/rb3" android:layout_width="match_parent" android:layout_height="match_parent"/> </LinearLayout> <LinearLayout android:id="@+id/ll_mine" android:layout_weight="1" android:layout_width="0dp" android:layout_height="match_parent" android:orientation="vertical"> <kitrobot.com.wechat_bottom_navigation.view.MyImageView android:layout_gravity="center" android:id="@+id/iv4" android:layout_width="@dimen/tab_image_weith" android:layout_height="@dimen/tab_image_heigh"/> <TextView android:gravity="center" android:text="我" android:button="@null" android:id="@+id/rb4" android:layout_width="match_parent" android:layout_height="match_parent"/> </LinearLayout> </LinearLayout> </LinearLayout>
最后看一下代码的逻辑 你会发现so简单 注释什么的都很全自己看一下绝对ok
public class MainActivity extends AppCompatActivity implements View.OnClickListener { private ViewPager mViewPager; private MyImageView mIvHome; // tab 消息的imageview private TextView mTvHome; // tab 消息的imageview private MyImageView mIvCategory; // tab 通讯录的imageview private TextView mTvCategory; private MyImageView mIvFind; // tab 发现的imageview private TextView mTvFind; private MyImageView mIvMine; // tab 我的imageview private TextView mTvMine; private ArrayList<Fragment> mFragments; private ArgbEvaluator mColorEvaluator; private int mTextNormalColor;// 未选中的字体颜色 private int mTextSelectedColor;// 选中的字体颜色 private LinearLayout mLinearLayoutHome; private LinearLayout mLinearLayoutCategory; private LinearLayout mLinearLayoutFind; private LinearLayout mLinearLayoutMine; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initColor();//也就是选中未选中的textview的color initView();// 初始化控件 initData(); // 初始化数据(也就是fragments) initSelectImage();// 初始化渐变的图片 aboutViewpager(); // 关于viewpager setListener(); // viewpager设置滑动监听 } private void initSelectImage() { mIvHome.setImages(R.drawable.home_normal, R.drawable.home_selected); mIvCategory.setImages(R.drawable.category_normal, R.drawable.category_selected); mIvFind.setImages(R.drawable.find_normal, R.drawable.find_selected); mIvMine.setImages(R.drawable.mine_normal, R.drawable.mine_selected); } private void initColor() { mTextNormalColor = getResources().getColor(R.color.main_bottom_tab_textcolor_normal); mTextSelectedColor = getResources().getColor(R.color.main_bottom_tab_textcolor_selected); } private void setListener() { //下面的tab设置点击监听 mLinearLayoutHome.setOnClickListener(this); mLinearLayoutCategory.setOnClickListener(this); mLinearLayoutFind.setOnClickListener(this); mLinearLayoutMine.setOnClickListener(this); mViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() { @Override public void onPageScrolled(int position, float positionOffset, int positionOffsetPs) { setTabTextColorAndImageView(position,positionOffset);// 更改text的颜色还有图片 } @Override public void onPageSelected(int position) { } @Override public void onPageScrollStateChanged(int state) { } }); } private void setTabTextColorAndImageView(int position, float positionOffset) { mColorEvaluator = new ArgbEvaluator(); // 根据偏移量 来得到 int evaluateCurrent =(int) mColorEvaluator.evaluate(positionOffset,mTextSelectedColor , mTextNormalColor);//当前tab的颜色值 int evaluateThe =(int) mColorEvaluator.evaluate(positionOffset, mTextNormalColor, mTextSelectedColor);// 将要到tab的颜色值 switch (position) { case 0: mTvHome.setTextColor(evaluateCurrent); //设置消息的字体颜色 mTvCategory.setTextColor(evaluateThe); //设置通讯录的字体颜色 mIvHome.transformPage(positionOffset); //设置消息的图片 mIvCategory.transformPage(1-positionOffset); //设置通讯录的图片 break; case 1: mTvCategory.setTextColor(evaluateCurrent); mTvFind.setTextColor(evaluateThe); mIvCategory.transformPage(positionOffset); mIvFind.transformPage(1-positionOffset); break; case 2: mTvFind.setTextColor(evaluateCurrent); mTvMine.setTextColor(evaluateThe); mIvFind.transformPage(positionOffset); mIvMine.transformPage(1-positionOffset); break; } } private void initData() { mFragments = new ArrayList<>(); mFragments.add(new HomeFragment()); mFragments.add(new CategoryFragment()); mFragments.add(new FindFragment()); mFragments.add(new MineFragment()); } private void aboutViewpager() { MyAdapter myAdapter = new MyAdapter(getSupportFragmentManager(), mFragments);// 初始化adapter mViewPager.setAdapter(myAdapter); // 设置adapter } private void initView() { mLinearLayoutHome = (LinearLayout) findViewById(R.id.ll_home); mLinearLayoutCategory = (LinearLayout) findViewById(R.id.ll_categroy); mLinearLayoutFind = (LinearLayout) findViewById(R.id.ll_find); mLinearLayoutMine = (LinearLayout) findViewById(R.id.ll_mine); mViewPager = (ViewPager) findViewById(R.id.vp); mIvHome = (MyImageView) findViewById(R.id.iv1); // tab 微信 imageview mTvHome = (TextView) findViewById(R.id.rb1); // tab 微信 字 mIvCategory = (MyImageView) findViewById(R.id.iv2); // tab 通信录 imageview mTvCategory = (TextView) findViewById(R.id.rb2); // tab 通信录 字 mIvFind = (MyImageView) findViewById(R.id.iv3); // tab 发现 imageview mTvFind = (TextView) findViewById(R.id.rb3); // tab 发现 字 mIvMine = (MyImageView) findViewById(R.id.iv4); // tab 我 imageview mTvMine = (TextView) findViewById(R.id.rb4); // tab 我 字 } @Override public void onClick(View view) { switch (view.getId()) { case R.id.ll_home: mViewPager.setCurrentItem(0); break; case R.id.ll_categroy: mViewPager.setCurrentItem(1); break; case R.id.ll_find: mViewPager.setCurrentItem(2); break; case R.id.ll_mine: mViewPager.setCurrentItem(3); break; } } }
有的同学会问:为什么不用初始化tab字体的颜色和imageview的图片的,其实这个我也是最近才发现的,当界面完成的时候,viewpager会自动加载第一页而此时的ViewPager.OnPageChangeListener中的 onPageScrolled 会自动的执行一次,其他的方法不会去执行
最后献上源码位置
github:wechat-Bottom-navigation欢迎star
相关文章推荐
- android高仿微信底部渐变导航栏
- Android UI-仿微信底部导航栏布局
- [置顶] JFTabBar android强大的底部导航栏框架 (微信底部导航栏效果)
- Android UI-仿微信底部导航栏布局
- Android 高仿微信图片浏览,点击图片,头部和底部隐藏
- Android实现简单底部导航栏 Android仿微信滑动切换效果
- Android高仿QQ及微信底部菜单的多种实现方式【附源码地址】
- [置顶] Android项目导航栏之仿微信底部导航栏TabLayout+ViewPager+Fragment
- Android UI-仿微信底部导航栏布局
- Android Fragment + ViewPager 实现类微信 底部导航栏 和 显示消息提醒
- 微信小程序实战之仿android fragment可滑动底部导航栏(4)
- Android高仿qq及微信底部菜单的几种实现方式
- Android使用Fragment仿微信底部导航栏
- 微信小程序之仿android fragment之可滑动的底部导航栏实例 —— 微信小程序实战系列(4)
- Android高仿qq及微信底部菜单的几种实现方式
- android仿微信底部导航栏图标渐变效果
- Android UI-仿微信底部导航栏布局
- 【附源码地址】Android高仿QQ及微信底部菜单的多种实现方式
- Android RadioGroup+ViewPager+ActionBar实现仿微信6.0界面(底部滑动菜单栏+导航栏)
- 高仿微信app实战(二)- 自定义View实现底部导航栏