原創(chuàng)作者:AchillesL
若轉(zhuǎn)載文章,請(qǐng)?jiān)诿黠@的位置標(biāo)明文章出處
1. 前言
??使用微信時(shí)被济,我們會(huì)發(fā)現(xiàn):進(jìn)行頁面切換時(shí)蛋勺,底部標(biāo)題欄的圖片會(huì)發(fā)生顏色深淺的變化羡宙。
??本文將介紹這種效果是如何實(shí)現(xiàn)的孵坚,最終效果如圖1所示。
2. 知識(shí)點(diǎn)
ArgbEvaluator.evaluate方法:
該方法用于根據(jù)一個(gè)起始顏色值和一個(gè)結(jié)束顏色值以及一個(gè)偏移量生成一個(gè)新的顏色滞时。
DrawableCompat.setTintList方法:
通過該方法叁幢,可以動(dòng)態(tài)地給圖片進(jìn)行著色處理。對(duì)于具體的用法坪稽,可以參考一下文章:http://www.reibang.com/p/6bd7dd1cd491 本文不再講述曼玩。
3. 準(zhǔn)備工作
??我們創(chuàng)建一個(gè)Demo。Activity中包含一個(gè)ViewPager控件窒百,并利用LinearLayout實(shí)現(xiàn)底部標(biāo)題欄黍判。
??布局代碼:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="com.achillesl.bottombar.MainActivity">
<android.support.v4.view.ViewPager
android:id="@+id/viewPager"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"/>
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="#eeeeee"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:paddingBottom="10dp"
android:paddingTop="10dp"
>
<ImageView
android:id="@+id/ivOne"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
tools:src="@drawable/ic_action_alarm"/>
<ImageView
android:id="@+id/ivTwo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
tools:src="@drawable/ic_action_amazon"/>
<ImageView
android:id="@+id/ivThree"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
tools:src="@drawable/ic_action_anchor"/>
<ImageView
android:id="@+id/ivFour"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
tools:src="@drawable/ic_action_android"/>
</LinearLayout>
</LinearLayout>
??主界面代碼:
package com.achillesl.bottombar;
import android.content.res.ColorStateList;
import android.graphics.drawable.Drawable;
import android.support.v4.content.ContextCompat;
import android.support.v4.graphics.drawable.DrawableCompat;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends AppCompatActivity {
private ViewPager mViewPager;
private List<TextView> mTipList = new ArrayList<>();
//使用List存放ImageView對(duì)象
private List<ImageView> mBottomImageViews = new ArrayList<>();
//使用List存放ImageView對(duì)應(yīng)的圖片資源
private List<Drawable> mBottomImageDrawables = new ArrayList<>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initTipList();
initImageViewDrawable();
// TODO: 2016/11/13 設(shè)置ViewPager的頁面數(shù)
mViewPager = (ViewPager) findViewById(R.id.viewPager);
mViewPager.setAdapter(new PagerAdapter() {
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView(mTipList.get(position));
}
@Override
public Object instantiateItem(ViewGroup container, int position) {
TextView textView = mTipList.get(position);
container.addView(textView);
return textView;
}
@Override
public int getCount() {
return 4;
}
@Override
public boolean isViewFromObject(View view, Object object) {
return view == object;
}
});
}
private void initImageViewDrawable() {
mBottomImageViews.add((ImageView) findViewById(R.id.ivOne));
mBottomImageViews.add((ImageView) findViewById(R.id.ivTwo));
mBottomImageViews.add((ImageView) findViewById(R.id.ivThree));
mBottomImageViews.add((ImageView) findViewById(R.id.ivFour));
mBottomImageDrawables.add(ContextCompat.getDrawable(this,R.drawable.ic_action_alarm).mutate());
mBottomImageDrawables.add(ContextCompat.getDrawable(this,R.drawable.ic_action_amazon).mutate());
mBottomImageDrawables.add(ContextCompat.getDrawable(this,R.drawable.ic_action_anchor).mutate());
mBottomImageDrawables.add(ContextCompat.getDrawable(this,R.drawable.ic_action_android).mutate());
}
private void initTipList() {
ViewGroup.LayoutParams layoutParams = new ViewGroup.LayoutParams(ViewGroup.LayoutParams
.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
for (int i = 0; i < 4; i++) {
TextView textView = new TextView(this);
textView.setText("第" + (i + 1) + "個(gè)頁面");
textView.setLayoutParams(layoutParams);
textView.setGravity(Gravity.CENTER);
mTipList.add(textView);
}
}
}
??上面代碼中,我們使用List統(tǒng)一管理圖片資源篙梢、ImageView實(shí)例顷帖。
4. 顏色漸變
4.1 設(shè)置圖標(biāo)初始顏色
??這一步,我們將設(shè)置底部標(biāo)題欄圖標(biāo)的顏色渤滞。選擇的顏色為藍(lán)色贬墩,未選中的藍(lán)色為灰色。
4.1.1 定義并初始化顏色
在color.xml文件中定義顏色
<color name="buttonSelect">#3F51B5</color>
<color name="buttonUnSelect">#a4a3a3</color>
4.1.2 在Activity中添加變量
private int mBottomColorSelect;
private int mBottomColorUnSelect;
4.1.3 設(shè)置不同圖標(biāo)的顏色
??添加setImageViewSelect方法妄呕,代碼如下:
private void setImageViewSelect(int selectIndex) {
for (int index = 0; index < mBottomImageViews.size(); index++) {
ImageView imageView = mBottomImageViews.get(index);
Drawable drawable = mBottomImageDrawables.get(index);
if (index == selectIndex) {
imageView.setImageDrawable(tintDrawable(drawable, ColorStateList.valueOf
(mBottomColorSelect)));
} else {
imageView.setImageDrawable(tintDrawable(drawable, ColorStateList.valueOf
(mBottomColorUnSelect)));
}
}
}
4.1.4 修改initImageViewDrawable方法
private void initImageViewDrawable() {
/*Add begin*/
mBottomColorSelect = ContextCompat.getColor(this, R.color.buttonSelect);
mBottomColorUnSelect = ContextCompat.getColor(this, R.color.buttonUnSelect);
/*Add end*/
mBottomImageViews.add((ImageView) findViewById(R.id.ivOne));
...
mBottomImageDrawables.add(ContextCompat.getDrawable(this,R.drawable.ic_action_android).mutate());
/*Add begin*/
setImageViewSelect(0);
/*Add end*/
}
??此時(shí)陶舞,完成了底部欄圖標(biāo)的初始化,如圖2所示绪励。
4.2 設(shè)置ViewPager滑動(dòng)監(jiān)聽
??這時(shí)肿孵,我們需要給ViewPager添加滑動(dòng)監(jiān)聽事件,并且可以聯(lián)想到:顏色的漸變疏魏,應(yīng)該與ViewPager的滑動(dòng)距離有關(guān)停做。
??因此,在監(jiān)聽器的onPageScrolled方法中添加changeImageViewDrawable方法蠢护,根據(jù)ViewPager的滑動(dòng)偏移量雅宾,動(dòng)態(tài)改變圖標(biāo)的顏色养涮。
mViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
changeImageViewDrawable(position,positionOffset);
}
@Override
public void onPageSelected(int position) {
}
@Override
public void onPageScrollStateChanged(int state) {
}
});
4.2.1 編寫changeImageViewDrawable方法
??這一步主要用到ArgbEvaluator類的evaluate方法葵硕,該方法的用法很簡(jiǎn)單:
public Object evaluate(float fraction, Object startValue, Object endValue)
??參數(shù)fraction:
指起始顏色到目標(biāo)顏色的偏移值眉抬。該值我們用ViewPager的頁面偏移值positionOffset傳入。
??參數(shù)startValue:起始顏色
??參數(shù)endValue:目標(biāo)顏色
??changeImageViewDrawable方法的代碼:
private void changeImageViewDrawable(int position, float positionOffset) {
ImageView ivFrom = null;
ImageView ivTo = null;
Drawable drawableFrom = null;
Drawable drawableTo = null;
ivFrom = mBottomImageViews.get(position);
drawableFrom = mBottomImageDrawables.get(position);
if (position != mBottomImageDrawables.size() - 1) {
ivTo = mBottomImageViews.get(position + 1);
drawableTo = mBottomImageDrawables.get(position + 1);
} else {
ivTo = null;
drawableTo = null;
}
if (ivFrom != null) {
int colorStart = (int) mArgbEvaluator.evaluate(positionOffset, mBottomColorSelect,
mBottomColorUnSelect);
Drawable drawableColorStart = tintDrawable(drawableFrom, ColorStateList.valueOf
(colorStart));
ivFrom.setImageDrawable(drawableColorStart);
}
if (ivTo != null) {
int colorStart = (int) mArgbEvaluator.evaluate(positionOffset, mBottomColorUnSelect,
mBottomColorSelect);
Drawable drawableColorEnd = tintDrawable(drawableTo, ColorStateList.valueOf
(colorStart));
ivTo.setImageDrawable(drawableColorEnd);
}
}
3 小問題優(yōu)化
??實(shí)現(xiàn)具體業(yè)務(wù)時(shí)懈凹,往往點(diǎn)擊底部標(biāo)題欄的圖片時(shí)蜀变,需要切換到具體的頁面。細(xì)心的同學(xué)可能會(huì)發(fā)現(xiàn)介评,若起始按鈕與目標(biāo)按鈕相隔較遠(yuǎn)時(shí)库北,其他按鈕圖片上可能遺留“殘影”。
??解決這個(gè)問題很簡(jiǎn)單们陆,只要在ViewPager頁面切換完成時(shí)寒瓦,再一次延時(shí)設(shè)置底部圖標(biāo)的顏色就可以了。
@Override
public void onPageSelected(final int position) {
handler.postDelayed(new Runnable() {
@Override
public void run() {
setImageViewSelect(position);
}
},DELAY_TIME);
}
全部代碼
package com.achillesl.bottombar;
import android.animation.ArgbEvaluator;
import android.content.res.ColorStateList;
import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.support.v4.content.ContextCompat;
import android.support.v4.graphics.drawable.DrawableCompat;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends AppCompatActivity {
private ViewPager mViewPager;
private List<TextView> mTipList = new ArrayList<>();
//使用List存放ImageView對(duì)象
private List<ImageView> mBottomImageViews = new ArrayList<>();
//使用List存放ImageView對(duì)應(yīng)的圖片資源
private List<Drawable> mBottomImageDrawables = new ArrayList<>();
private ArgbEvaluator mArgbEvaluator = new ArgbEvaluator();
private int mBottomColorSelect;
private int mBottomColorUnSelect;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initTipList();
initImageViewDrawable();
// TODO: 2016/11/13 設(shè)置ViewPager的頁面數(shù)
mViewPager = (ViewPager) findViewById(R.id.viewPager);
mViewPager.setAdapter(new PagerAdapter() {
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView(mTipList.get(position));
}
@Override
public Object instantiateItem(ViewGroup container, int position) {
TextView textView = mTipList.get(position);
container.addView(textView);
return textView;
}
@Override
public int getCount() {
return 4;
}
@Override
public boolean isViewFromObject(View view, Object object) {
return view == object;
}
});
mViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
private final int DELAY_TIME = 100;
private Handler handler = new Handler();
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
changeImageViewDrawable(position,positionOffset);
}
@Override
public void onPageSelected(final int position) {
handler.postDelayed(new Runnable() {
@Override
public void run() {
setImageViewSelect(position);
}
},DELAY_TIME);
}
@Override
public void onPageScrollStateChanged(int state) {
}
});
}
private void changeImageViewDrawable(int position, float positionOffset) {
ImageView ivFrom = null;
ImageView ivTo = null;
Drawable drawableFrom = null;
Drawable drawableTo = null;
ivFrom = mBottomImageViews.get(position);
drawableFrom = mBottomImageDrawables.get(position);
if (position != mBottomImageDrawables.size() - 1) {
ivTo = mBottomImageViews.get(position + 1);
drawableTo = mBottomImageDrawables.get(position + 1);
} else {
ivTo = null;
drawableTo = null;
}
if (ivFrom != null) {
int colorStart = (int) mArgbEvaluator.evaluate(positionOffset, mBottomColorSelect,
mBottomColorUnSelect);
Drawable drawableColorStart = tintDrawable(drawableFrom, ColorStateList.valueOf
(colorStart));
ivFrom.setImageDrawable(drawableColorStart);
}
if (ivTo != null) {
int colorStart = (int) mArgbEvaluator.evaluate(positionOffset, mBottomColorUnSelect,
mBottomColorSelect);
Drawable drawableColorEnd = tintDrawable(drawableTo, ColorStateList.valueOf
(colorStart));
ivTo.setImageDrawable(drawableColorEnd);
}
}
private void initImageViewDrawable() {
/*Add begin*/
mBottomColorSelect = ContextCompat.getColor(this, R.color.buttonSelect);
mBottomColorUnSelect = ContextCompat.getColor(this, R.color.buttonUnSelect);
/*Add end*/
mBottomImageViews.add((ImageView) findViewById(R.id.ivOne));
mBottomImageViews.add((ImageView) findViewById(R.id.ivTwo));
mBottomImageViews.add((ImageView) findViewById(R.id.ivThree));
mBottomImageViews.add((ImageView) findViewById(R.id.ivFour));
mBottomImageDrawables.add(ContextCompat.getDrawable(this,R.drawable.ic_action_alarm).mutate());
mBottomImageDrawables.add(ContextCompat.getDrawable(this,R.drawable.ic_action_amazon).mutate());
mBottomImageDrawables.add(ContextCompat.getDrawable(this,R.drawable.ic_action_anchor).mutate());
mBottomImageDrawables.add(ContextCompat.getDrawable(this,R.drawable.ic_action_android).mutate());
for (int i = 0; i < mBottomImageViews.size(); i++) {
ImageView imageView = mBottomImageViews.get(i);
final int index = i;
imageView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
mViewPager.setCurrentItem(index);
}
});
}
/*Add begin*/
setImageViewSelect(0);
/*Add end*/
}
private void setImageViewSelect(int selectIndex) {
for (int index = 0; index < mBottomImageViews.size(); index++) {
ImageView imageView = mBottomImageViews.get(index);
Drawable drawable = mBottomImageDrawables.get(index);
if (index == selectIndex) {
imageView.setImageDrawable(tintDrawable(drawable, ColorStateList.valueOf
(mBottomColorSelect)));
} else {
imageView.setImageDrawable(tintDrawable(drawable, ColorStateList.valueOf
(mBottomColorUnSelect)));
}
}
}
public Drawable tintDrawable(Drawable drawable, ColorStateList colors) {
final Drawable wrappedDrawable = DrawableCompat.wrap(drawable);
DrawableCompat.setTintList(wrappedDrawable, colors);
return wrappedDrawable;
}
private void initTipList() {
ViewGroup.LayoutParams layoutParams = new ViewGroup.LayoutParams(ViewGroup.LayoutParams
.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
for (int i = 0; i < 4; i++) {
TextView textView = new TextView(this);
textView.setText("第" + (i + 1) + "個(gè)頁面");
textView.setLayoutParams(layoutParams);
textView.setGravity(Gravity.CENTER);
mTipList.add(textView);
}
}
}