首先上效果图
大家微信都很熟悉了,这里的效果就是仿照微信,在主界面左右滑动的时候,下面的导航图标会产生渐变的效果,滑动是,之前图标会慢慢变淡,当前的图标会渐渐边成选中的颜色。
这种效果如何实现呢,当然要使用我强大的自定义view。
自定义ChangeColorIconWithText
对于自定view,我们一般需要下面几步:
1.自定义属性
在attrs.xml文件中添加下列代码。
<code class=" hljs xml"> <attr name="icon" format="reference"></attr> <attr name="color" format="color"></attr> <attr name="text" format="string"></attr> <attr name="text_size" format="dimension"></attr> <declare-styleable name="ChangeColorIconWithText"> <attr name="icon"></attr> <attr name="color"></attr> <attr name="text"></attr> <attr name="text_size"></attr> </declare-styleable></code>
2.onMeasure
确定图标位置,对于位置的技术不理解可以自行画图看看。
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int iconWith = Math.min(getMeasuredWidth()-getPaddingLeft()-getPaddingRight(),getMeasuredHeight()-getPaddingTop()-getPaddingBottom()-mTextBound.height());
int left = getMeasuredWidth()/2 - iconWith/2;
int top = (getMeasuredHeight()-mTextBound.height())/2-iconWith/2;
mIconRect = new Rect(left, top, left+iconWith, top+iconWith);
}
3.onDraw
这里现在内存中的Canvas上绘制一个可变色的bitmap,然后再将其绘制到屏幕显示的Canvas上,文字的变色与图标变色没有关系,只是两者都用相同的alpha来控制。
@Override
protected void onDraw(Canvas canvas) {
canvas.drawBitmap(mIconBitmap,null, mIconRect, null);
int alpha = (int) Math.ceil(255*mAlpha);
//在内存中准备mBitmap
setTargetBitmap(alpha);
//绘制原文本
drawSourceText(canvas, alpha);
//绘制变色的文本
drawTargetText(canvas, alpha);
canvas.drawBitmap(mBitmap, 0, 0, null);
}
4.对外公布一个控制透明度的方法
public void setIconAlpha(float alpha)
{
this.mAlpha = alpha;
//重绘
if (Looper.getMainLooper() == Looper.myLooper())//判断是否是主线程
{
invalidate();
}else{
postInvalidate();
}
}
ChangeColorIconWithText类全部代码
public class ChangeColorIconWithText extends View {
private int mColor = 0xFF45c01A;
private Bitmap mIconBitmap;
private String mText = "微信";
private int mTextSize = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP,12, getResources().getDisplayMetrics());
private Canvas mCanvas;
private Bitmap mBitmap;
private Paint mPaint;
private float mAlpha ;
private Rect mIconRect;
private Rect mTextBound;
private Paint mTextPaint;
public ChangeColorIconWithText(Context context) {
this(context, null);
}
public ChangeColorIconWithText(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public ChangeColorIconWithText(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.ChangeColorIconWithText);
for (int i = 0; i < a.getIndexCount(); i++)
{
int attr = a.getIndex(i);
switch (attr)
{
case R.styleable.ChangeColorIconWithText_icon:
BitmapDrawable drawable = (BitmapDrawable) a.getDrawable(attr);
mIconBitmap = drawable.getBitmap();
break;
case R.styleable.ChangeColorIconWithText_color:
mColor = a.getColor(attr,0xff45c01a);
break;
case R.styleable.ChangeColorIconWithText_text:
mText = a.getString(attr);
break;
case R.styleable.ChangeColorIconWithText_text_size:
mTextSize = (int)a.getDimension(attr,TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP,12, getResources().getDisplayMetrics()));
}
}
a.recycle();
mTextBound = new Rect();
mTextPaint = new Paint();
mTextPaint.setTextSize(mTextSize);
mTextPaint.setColor(0xff555555);
mTextPaint.getTextBounds(mText,0, mText.length(), mTextBound);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int iconWith = Math.min(getMeasuredWidth()-getPaddingLeft()-getPaddingRight(),getMeasuredHeight()-getPaddingTop()-getPaddingBottom()-mTextBound.height());
int left = getMeasuredWidth()/2 - iconWith/2;
int top = (getMeasuredHeight()-mTextBound.height())/2-iconWith/2;
mIconRect = new Rect(left, top, left+iconWith, top+iconWith);
}
@Override
protected void onDraw(Canvas canvas) {
canvas.drawBitmap(mIconBitmap,null, mIconRect, null);
int alpha = (int) Math.ceil(255*mAlpha);
//在内存中准备可变色的mBitmap
setTargetBitmap(alpha);
//绘制原文本
drawSourceText(canvas, alpha);
//绘制变色的文本
drawTargetText(canvas, alpha);
canvas.drawBitmap(mBitmap, 0, 0, null);
}
private void drawTargetText(Canvas canvas, int alpha) {
mTextPaint.setColor(mColor);
mTextPaint.setAlpha(alpha);
int x = getMeasuredWidth()/2-mTextBound.width()/2;
int y = mIconRect.bottom+mTextBound.height();
canvas.drawText(mText,x,y,mTextPaint);
}
private void drawSourceText(Canvas canvas, int alpha) {
mTextPaint.setColor(0xff333333);
mTextPaint.setAlpha(255-alpha);
int x = getMeasuredWidth()/2-mTextBound.width()/2;
int y = mIconRect.bottom+mTextBound.height();
canvas.drawText(mText,x,y,mTextPaint);
}
private void setTargetBitmap(int alpha) {
mBitmap = Bitmap.createBitmap(getMeasuredWidth(),getMeasuredHeight(), Bitmap.Config.ARGB_8888);
//以bitmap对象创建一个画布,则将内容都绘制在bitmap上,bitmap不得为null;
mCanvas = new Canvas((mBitmap));
mPaint = new Paint();
mPaint.setColor(mColor);
mPaint.setAntiAlias(true);
mPaint.setDither(true); //设置防抖动,效果更柔和
mPaint.setAlpha(alpha);
mCanvas.drawRect(mIconRect,mPaint);
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
mPaint.setAlpha(255);
mCanvas.drawBitmap(mIconBitmap,null,mIconRect,mPaint);
}
public void setIconAlpha(float alpha)
{
this.mAlpha = alpha;
//重绘
if (Looper.getMainLooper() == Looper.myLooper()) //判断是不是主线程
{
invalidate();
}else{
postInvalidate();
}
}
}
activity代码
public class WeiXinActivity extends FragmentActivity implements View.OnClickListener, ViewPager.OnPageChangeListener {
private ViewPager viewPager;
private List mTabs = new ArrayList();
private String[] mTitles = new String[]{
"first fragemnt", "second fragment",
"third fragment", "forth fragment"
};
private FragmentPagerAdapter mAdapter;
private List mTabIndicator = new ArrayList();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
overflowButtonController();
getActionBar().setDisplayShowHomeEnabled(false);
initViews();
initDatas();
viewPager.setAdapter(mAdapter);
viewPager.setOnPageChangeListener(this);
}
private void initViews() {
viewPager = (ViewPager) findViewById(R.id.viewPager);
ChangeColorIconWithText one = (ChangeColorIconWithText) findViewById(R.id.indicator_one);
ChangeColorIconWithText two = (ChangeColorIconWithText) findViewById(R.id.indicator_two);
ChangeColorIconWithText three = (ChangeColorIconWithText) findViewById(R.id.indicator_three);
ChangeColorIconWithText four = (ChangeColorIconWithText) findViewById(R.id.indicator_four);
mTabIndicator.add(one);
mTabIndicator.add(two);
mTabIndicator.add(three);
mTabIndicator.add(four);
one.setOnClickListener(this);
two.setOnClickListener(this);
three.setOnClickListener(this);
four.setOnClickListener(this);
one.setIconAlpha(1.0f);
}
private void initDatas() {
for (int i = 0; i < mTitles.length; i++)
{
TabFragment fragment = new TabFragment();
Bundle bundle = new Bundle();
bundle.putString(TabFragment.TITLE,mTitles[i]);
fragment.setArguments(bundle);
mTabs.add(fragment);
}
mAdapter = new FragmentPagerAdapter(getSupportFragmentManager()) {
@Override
public Fragment getItem(int i) {
return mTabs.get(i);
}
@Override
public int getCount() {
return mTabs.size();
}
};
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
return super.onCreateOptionsMenu(menu);
}
@Override
public boolean onMenuOpened(int featureId, Menu menu) {
if (featureId == Window.FEATURE_ACTION_BAR && menu != null)
{
if (menu.getClass().getSimpleName().equals("MenuBuilder"))
{
try {
Method m = menu.getClass().getDeclaredMethod("setOptionalIconsVisible",Boolean.TYPE);
m.setAccessible(true);
m.invoke(menu, true);
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
return super.onMenuOpened(featureId, menu);
}
public void overflowButtonController()
{
ViewConfiguration config = ViewConfiguration.get(this);
try {
Field menuKey = ViewConfiguration.class.getDeclaredField("sHasPermanentMenuKey");
menuKey.setAccessible(true);
menuKey.setBoolean(config, false);
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
@Override
public void onClick(View v) {
resetOtherTabs();
switch (v.getId())
{
case R.id.indicator_one:
mTabIndicator.get(0).setIconAlpha(1.0f);
viewPager.setCurrentItem(0,false);
break;
case R.id.indicator_two:
mTabIndicator.get(1).setIconAlpha(1.0f);
viewPager.setCurrentItem(1,false);
break;
case R.id.indicator_three:
mTabIndicator.get(2).setIconAlpha(1.0f);
viewPager.setCurrentItem(2,false);
break;
case R.id.indicator_four:
mTabIndicator.get(3).setIconAlpha(1.0f);
viewPager.setCurrentItem(3,false);
break;
}
}
private void resetOtherTabs() {
for (int i = 0; i < mTabIndicator.size(); i++)
{
mTabIndicator.get(i).setIconAlpha(0);
}
}
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
if (positionOffset > 0)
{
ChangeColorIconWithText left = mTabIndicator.get(position);
ChangeColorIconWithText right = mTabIndicator.get(position+1);
left.setIconAlpha(1-positionOffset);
right.setIconAlpha(positionOffset);
}
}
@Override
public void onPageSelected(int i) {
}
@Override
public void onPageScrollStateChanged(int i) {
}
}
布局文件
<code class=" hljs avrasm"><?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:chm="http://schemas.android.com/apk/res/com.chm.web" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <android.support.v4.view.ViewPager android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1" android:id="@+id/viewPager"> </android.support.v4.view.ViewPager> <LinearLayout android:layout_width="match_parent" android:layout_height="60dp" android:orientation="horizontal" android:background="@drawable/tab_bg"> <com.chm.web.view.ChangeColorIconWithText android:layout_width="0dp" android:layout_height="fill_parent" android:layout_weight="1" chm:color="#ff45c01a" chm:text="@string/tab_weixin" chm:text_size="12sp" android:padding="6dp" chm:icon="@drawable/ic_menu_start_conversation" android:id="@+id/indicator_one"/> <com.chm.web.view.ChangeColorIconWithText android:layout_width="0dp" android:layout_height="fill_parent" android:layout_weight="1" chm:color="#ff45c01a" chm:text="@string/tab_contact" chm:text_size="12sp" android:padding="6dp" chm:icon="@drawable/ic_menu_friendslist" android:id="@+id/indicator_two"/> <com.chm.web.view.ChangeColorIconWithText android:layout_width="0dp" android:layout_height="fill_parent" android:layout_weight="1" chm:color="#ff45c01a" chm:text="@string/tab_discovery" chm:text_size="12sp" android:padding="6dp" chm:icon="@drawable/ic_menu_emoticons" android:id="@+id/indicator_three"/> <com.chm.web.view.ChangeColorIconWithText android:layout_width="0dp" android:layout_height="fill_parent" android:layout_weight="1" chm:color="#ff45c01a" chm:text="@string/tab_me" chm:text_size="12sp" android:padding="6dp" chm:icon="@drawable/ic_menu_allfriends" android:id="@+id/indicator_four"/> </LinearLayout> </LinearLayout></code>