废话不多说,先看效果:
记得微信刚出来时,他的这个渐变效果还是惊艳到我的。现在网上也有很多微信渐变栏的例子,我看过都是利用Paint的Xfermode来实现的。但是我看过微信apk里头,他的两张(选中与非选中)图片都是有的。所以我以前按照自己的思路写了一个,这段时间整理代码时,把他整理出来了。
要说我实现的原理,其实挺简单的,就是两种图都有,一个变淡,一个变深。
每个小块:
/**
* 渐变子模块
* Created by fcp on 2015/9/22.
*/
public class GradualChangeView extends View {
//选中图片
private Bitmap bitmapSelect;
//未选中图片
private Bitmap bitmapUnselect;
//限制绘制icon的范围
private Rect mIconRect = new Rect();
//底部文字
private String mText;
//文字转变色
private int mColor = 0x45C01A;//未选
private int sColor = 0x555555;//选中
//文本大小
private int mTextSize = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 10, getResources().getDisplayMetrics());
//文本区域
private Rect mTextBound = new Rect();
//画笔
private Paint mTextPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
private Paint bitmapPaint = new Paint();
/**
* 透明度 0.0-1.0
*/
private float mAlpha = 0f;
public GradualChangeView(Context context) {
super(context);
}
public GradualChangeView(Context context, AttributeSet attrs) {
super(context, attrs);
initView(context, attrs);
}
public GradualChangeView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initView(context, attrs);
}
/**
* 初始化布局
* @param context Context
* @param attrs AttributeSet
*/
private void initView(Context context, AttributeSet attrs) {
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.GradualChangeBar);
for (int i = 0; i < typedArray.getIndexCount(); i++) {
int attr = typedArray.getIndex(i);
switch (attr) {
case R.styleable.GradualChangeBar_grad_icon_top_selected:
BitmapDrawable bitmapDrawable = (BitmapDrawable) typedArray.getDrawable(attr);
if(bitmapDrawable != null) bitmapSelect = bitmapDrawable.getBitmap();
break;
case R.styleable.GradualChangeBar_grad_icon_top_unselect:
BitmapDrawable bitmapDrawable1 = (BitmapDrawable) typedArray.getDrawable(attr);
if(bitmapDrawable1 != null) bitmapUnselect = bitmapDrawable1.getBitmap();
break;
case R.styleable.GradualChangeBar_grad_text_bottom:
mText = typedArray.getString(attr);
break;
case R.styleable.GradualChangeBar_grad_text_size:
mTextSize = (int) typedArray.getDimension(attr, TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP,
10, getResources().getDisplayMetrics()));
break;
case R.styleable.GradualChangeBar_grad_text_color:
mColor = typedArray.getColor(attr , 0x45C01A);
break;
}
}
typedArray.recycle();
mTextPaint.setTextSize(mTextSize);
mTextPaint.setColor(sColor);//初始颜色
// 得到text绘制范围
mTextPaint.getTextBounds(mText, 0, mText.length(), mTextBound);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
// 得到绘制icon的宽
//int bitmapWidth = getMeasuredWidth() - getPaddingLeft() - getPaddingRight();
int bitmapHeight = (int)((getMeasuredHeight() - getPaddingTop() - getPaddingBottom() - mTextBound.height()) *0.8);//乘0.8只是让图片更小,整体更居中
int bitmapWidth = bitmapHeight * bitmapSelect.getWidth() / bitmapSelect.getHeight() ;
int left = ( getMeasuredWidth() - bitmapWidth ) / 2;
int top =( getMeasuredHeight() - mTextBound.height() - bitmapHeight) / 2;
// 设置icon的绘制范围
mIconRect.set(left, top, left + bitmapWidth, top + bitmapHeight);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
int alpha = (int) Math.ceil((255 * mAlpha));
//if(alpha!=255){
//绘制未选中图标
bitmapPaint.setAlpha(255 - alpha);
canvas.drawBitmap(bitmapUnselect, null, mIconRect, bitmapPaint);
//绘制未选中文本
mTextPaint.setColor(sColor);
mTextPaint.setAlpha(255 - alpha);
canvas.drawText(mText, mIconRect.left + (mIconRect.width() - mTextBound.width()) / 2,
mIconRect.bottom + mTextBound.height() , mTextPaint);
//}
//if(alpha!=0){
//绘制选中图标
bitmapPaint.setAlpha(alpha);
canvas.drawBitmap(bitmapSelect, null, mIconRect, bitmapPaint);
//绘制选中文本
mTextPaint.setColor(mColor);
mTextPaint.setAlpha( alpha);
canvas.drawText(mText, mIconRect.left + (mIconRect.width() - mTextBound.width()) / 2,
mIconRect.bottom + mTextBound.height() , mTextPaint);
//}
}
public void setIconAlpha(float alpha) {
this.mAlpha = alpha;
if (Looper.getMainLooper() == Looper.myLooper()) {
invalidate();
} else {
postInvalidate();
}
}
private static final String INSTANCE_STATE = "instance_state";
private static final String STATE_ALPHA = "state_alpha";
@Override
protected Parcelable onSaveInstanceState() {
Bundle bundle = new Bundle();
bundle.putParcelable(INSTANCE_STATE, super.onSaveInstanceState());
bundle.putFloat(STATE_ALPHA, mAlpha);
return bundle;
}
@Override
protected void onRestoreInstanceState(Parcelable state) {
if (state instanceof Bundle) {
Bundle bundle = (Bundle) state;
mAlpha = bundle.getFloat(STATE_ALPHA);
super.onRestoreInstanceState(bundle.getParcelable(INSTANCE_STATE));
} else {
super.onRestoreInstanceState(state);
}
}
}
整个bar类:
/**
* 渐变导航栏
* Created by fcp on 2015/9/22.
*/
public class GradualChangeBar extends LinearLayout implements View.OnClickListener,ViewPager.OnPageChangeListener{
private GradualChangeView one;
private GradualChangeView two;
private GradualChangeView three;
private GradualChangeView four;
private ArrayList<GradualChangeView> mGradualChangeViews =new ArrayList<>();
private ViewPager viewPager;
private OnSelectIdChanged mOnSelectIdChanged;
private int selectId;
public GradualChangeBar(Context context) {
super(context);
init(context);
}
public GradualChangeBar(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
public GradualChangeBar(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context);
}
private void init(Context context){
setOrientation(LinearLayout.HORIZONTAL);
setBackgroundResource(R.drawable.layer_list_graduallchangebar);
LayoutInflater inflater = LayoutInflater.from(context);
inflater.inflate(R.layout.activity_app_main_graduallbar, this);
}
@Override
protected void onFinishInflate() {
super.onFinishInflate();
one = (GradualChangeView) findViewById(R.id.activity_app_main_gradual_bar_one);
two = (GradualChangeView) findViewById(R.id.activity_app_main_gradual_bar_two);
three = (GradualChangeView) findViewById(R.id.activity_app_main_gradual_bar_three);
four = (GradualChangeView) findViewById(R.id.activity_app_main_gradual_bar_four);
mGradualChangeViews.add(one);
mGradualChangeViews.add(two);
mGradualChangeViews.add(three);
mGradualChangeViews.add(four);
one.setOnClickListener(this);
two.setOnClickListener(this);
three.setOnClickListener(this);
four.setOnClickListener(this);
}
/**
* 设置ViewPager
* @param viewPager ViewPager
*/
public void setViewPager(ViewPager viewPager, OnSelectIdChanged onSelectIdChanged) {
this.viewPager = viewPager;
this.mOnSelectIdChanged = onSelectIdChanged;
//初始化第一项
viewPager.setCurrentItem(0,false);
one.setIconAlpha(1);
two.setIconAlpha(0);
three.setIconAlpha(0);
four.setIconAlpha(0);
selectId = one.getId();
//监听
viewPager.addOnPageChangeListener(this);
}
@Override
public void onClick(View v) {
int id = v.getId();
if(id == selectId){
return ;
}
selectId = id;
switch (id){
case R.id.activity_app_main_gradual_bar_one:
one.setIconAlpha(1);
two.setIconAlpha(0);
three.setIconAlpha(0);
four.setIconAlpha(0);
viewPager.setCurrentItem(0,false);
if(mOnSelectIdChanged !=null) mOnSelectIdChanged.selectOne();
break;
case R.id.activity_app_main_gradual_bar_two:
one.setIconAlpha(0);
two.setIconAlpha(1);
three.setIconAlpha(0);
four.setIconAlpha(0);
viewPager.setCurrentItem(1, false);
if(mOnSelectIdChanged !=null) mOnSelectIdChanged.selectTwo();
break;
case R.id.activity_app_main_gradual_bar_three:
one.setIconAlpha(0);
two.setIconAlpha(0);
three.setIconAlpha(1);
four.setIconAlpha(0);
viewPager.setCurrentItem(2, false);
if(mOnSelectIdChanged !=null) mOnSelectIdChanged.selectThree();
break;
case R.id.activity_app_main_gradual_bar_four:
one.setIconAlpha(0);
two.setIconAlpha(0);
three.setIconAlpha(0);
four.setIconAlpha(1);
viewPager.setCurrentItem(3, false);
if(mOnSelectIdChanged !=null) mOnSelectIdChanged.selectFour();
break;
}
}
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
if (positionOffset > 0) {
GradualChangeView left = mGradualChangeViews.get(position);
GradualChangeView right = mGradualChangeViews.get(position + 1);
left.setIconAlpha(1 - positionOffset);
right.setIconAlpha(positionOffset);
}
}
@Override
public void onPageSelected(int position) {
selectId = mGradualChangeViews.get(position).getId();
switch (position){
case 0:
if(mOnSelectIdChanged !=null) mOnSelectIdChanged.selectOne();
break;
case 1:
if(mOnSelectIdChanged !=null) mOnSelectIdChanged.selectTwo();
break;
case 2:
if(mOnSelectIdChanged !=null) mOnSelectIdChanged.selectThree();
break;
case 3:
if(mOnSelectIdChanged !=null) mOnSelectIdChanged.selectFour();
break;
}
}
@Override
public void onPageScrollStateChanged(int state) {
}
public interface OnSelectIdChanged {
void selectOne();
void selectTwo();
void selectThree();
void selectFour();
}
}
布局:
<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:bar="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.fcp.gradual.view.GradualChangeView
android:id="@+id/activity_app_main_gradual_bar_one"
android:layout_weight="1"
android:layout_width="0dp"
android:layout_height="match_parent"
android:padding="@dimen/grad_view_padding"
bar:grad_icon_top_selected="@mipmap/ic_grad_store_selected"
bar:grad_icon_top_unselect= "@mipmap/ic_grad_store_unselect"
bar:grad_text_bottom="@string/fragment_store_text"
bar:grad_text_size="@dimen/grad_view_text_size"
bar:grad_text_color="@color/grad_view_text_color"/>
<com.fcp.gradual.view.GradualChangeView
android:id="@+id/activity_app_main_gradual_bar_two"
android:layout_weight="1"
android:layout_width="0dp"
android:layout_height="match_parent"
android:padding="@dimen/grad_view_padding"
bar:grad_icon_top_selected="@mipmap/ic_grad_activity_selected"
bar:grad_icon_top_unselect= "@mipmap/ic_grad_activity_unselect"
bar:grad_text_bottom="@string/fragment_activity_text"
bar:grad_text_size="@dimen/grad_view_text_size"
bar:grad_text_color="@color/grad_view_text_color" />
<com.fcp.gradual.view.GradualChangeView
android:id="@+id/activity_app_main_gradual_bar_three"
android:layout_weight="1"
android:layout_width="0dp"
android:layout_height="match_parent"
android:padding="@dimen/grad_view_padding"
bar:grad_icon_top_selected="@mipmap/ic_grad_message_selected"
bar:grad_icon_top_unselect= "@mipmap/ic_grad_message_unselect"
bar:grad_text_bottom="@string/fragment_message_text"
bar:grad_text_size="@dimen/grad_view_text_size"
bar:grad_text_color="@color/grad_view_text_color"/>
<com.fcp.gradual.view.GradualChangeView
android:id="@+id/activity_app_main_gradual_bar_four"
android:layout_weight="1"
android:layout_width="0dp"
android:layout_height="match_parent"
android:padding="@dimen/grad_view_padding"
bar:grad_icon_top_selected="@mipmap/ic_grad_mine_selected"
bar:grad_icon_top_unselect= "@mipmap/ic_grad_mine_unselect"
bar:grad_text_bottom="@string/fragment_mine_text"
bar:grad_text_size="@dimen/grad_view_text_size"
bar:grad_text_color="@color/grad_view_text_color"/>
</merge>