效果图

原理介绍

1、先绘制一个颜色(例如:粉红)
2、设置Mode=DST_IN
3、绘制我们这个可爱的小机器人
回答我,显示什么,是不是显示交集,交集是什么?交集是我们的小机器人的非透明区域,也就是那张脸,除了两个眼;
好了,那怎么变色呢?
我绘制一个颜色的时候,难道不能设置alpha么

自定义图标控件

自定义属性

<?xml version="1.0" encoding="utf-8"?>
<resources>  <attr name="icon" format="reference" />  <attr name="color" format="color" />  <attr name="text" format="string" />  <attr name="text_size" format="dimension" />  <declare-styleable name="ChangeColorIconView">  <attr name="icon" />  <attr name="color" />  <attr name="text" />  <attr name="text_size" />  </declare-styleable>  </resources>  

绘制图标

绘制图标有很多步骤呀,我来列一列
1、计算alpha(默认为0)
2、绘制原图
3、在绘图区域,绘制一个纯色块(设置了alpha),此步绘制在内存的bitmap上
4、设置mode,针对内存中的bitmap上的paint
5、绘制我们的图标,此步绘制在内存的bitmap上
6、绘制原文本
7、绘制设置alpha和颜色后的文本
8、将内存中的bitmap绘制出来
根据上面的步骤,可以看出来,我们的图标其实绘制了两次,为什么要绘制原图呢,因为我觉得比较好看。
3-5步骤,就是我们上面分析的原理
6-7步,是绘制文本,可以看到,我们的文本就是通过设置alpha实现的

package com.zhy.weixin6.ui;import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.drawable.BitmapDrawable;
import android.os.Bundle;
import android.os.Looper;
import android.os.Parcelable;
import android.util.AttributeSet;
import android.util.Log;
import android.util.TypedValue;
import android.view.View;public class ChangeColorIconWithTextView extends View
{private Bitmap mBitmap;private Canvas mCanvas;private Paint mPaint;/*** 颜色*/private int mColor = 0xFF45C01A;/*** 透明度 0.0-1.0*/private float mAlpha = 0f;/*** 图标*/private Bitmap mIconBitmap;/*** 限制绘制icon的范围*/private Rect mIconRect;/*** icon底部文本*/private String mText = "微信";private int mTextSize = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 10, getResources().getDisplayMetrics());private Paint mTextPaint;private Rect mTextBound = new Rect();public ChangeColorIconWithTextView(Context context){super(context);}/*** 初始化自定义属性值* * @param context* @param attrs*/public ChangeColorIconWithTextView(Context context, AttributeSet attrs){super(context, attrs);// 获取设置的图标TypedArray a = context.obtainStyledAttributes(attrs,R.styleable.ChangeColorIconView);int n = a.getIndexCount();for (int i = 0; i < n; i++){int attr = a.getIndex(i);switch (attr){case R.styleable.ChangeColorIconView_icon:BitmapDrawable drawable = (BitmapDrawable) a.getDrawable(attr);mIconBitmap = drawable.getBitmap();break;case R.styleable.ChangeColorIconView_color:mColor = a.getColor(attr, 0x45C01A);break;case R.styleable.ChangeColorIconView_text:mText = a.getString(attr);break;case R.styleable.ChangeColorIconView_text_size:mTextSize = (int) a.getDimension(attr, TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 10,getResources().getDisplayMetrics()));break;}}a.recycle();mTextPaint = new Paint();mTextPaint.setTextSize(mTextSize);mTextPaint.setColor(0xff555555);// 得到text绘制范围mTextPaint.getTextBounds(mText, 0, mText.length(), mTextBound);}@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec){super.onMeasure(widthMeasureSpec, heightMeasureSpec);// 得到绘制icon的宽int bitmapWidth = Math.min(getMeasuredWidth() - getPaddingLeft()- getPaddingRight(), getMeasuredHeight() - getPaddingTop()- getPaddingBottom() - mTextBound.height());int left = getMeasuredWidth() / 2 - bitmapWidth / 2;int top = (getMeasuredHeight() - mTextBound.height()) / 2 - bitmapWidth/ 2;// 设置icon的绘制范围mIconRect = new Rect(left, top, left + bitmapWidth, top + bitmapWidth);}@Overrideprotected void onDraw(Canvas canvas){int alpha = (int) Math.ceil((255 * mAlpha));canvas.drawBitmap(mIconBitmap, null, mIconRect, null);setupTargetBitmap(alpha);drawSourceText(canvas, alpha);drawTargetText(canvas, alpha);canvas.drawBitmap(mBitmap, 0, 0, null);}private void setupTargetBitmap(int alpha){mBitmap = Bitmap.createBitmap(getMeasuredWidth(), getMeasuredHeight(),Config.ARGB_8888);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);}private void drawSourceText(Canvas canvas, int alpha){mTextPaint.setTextSize(mTextSize);mTextPaint.setColor(0xff333333);mTextPaint.setAlpha(255 - alpha);canvas.drawText(mText, mIconRect.left + mIconRect.width() / 2- mTextBound.width() / 2,mIconRect.bottom + mTextBound.height(), mTextPaint);}private void drawTargetText(Canvas canvas, int alpha){mTextPaint.setColor(mColor);mTextPaint.setAlpha(alpha);canvas.drawText(mText, mIconRect.left + mIconRect.width() / 2- mTextBound.width() / 2,mIconRect.bottom + mTextBound.height(), mTextPaint);}public void setIconAlpha(float alpha){this.mAlpha = alpha;invalidateView();}private void invalidateView(){if (Looper.getMainLooper() == Looper.myLooper()){invalidate();} else{postInvalidate();}}public void setIconColor(int color){mColor = color;}public void setIcon(int resId){this.mIconBitmap = BitmapFactory.decodeResource(getResources(), resId);if (mIconRect != null)invalidateView();}public void setIcon(Bitmap iconBitmap){this.mIconBitmap = iconBitmap;if (mIconRect != null)invalidateView();}private static final String INSTANCE_STATE = "instance_state";private static final String STATE_ALPHA = "state_alpha";@Overrideprotected Parcelable onSaveInstanceState(){Bundle bundle = new Bundle();bundle.putParcelable(INSTANCE_STATE, super.onSaveInstanceState());bundle.putFloat(STATE_ALPHA, mAlpha);return bundle;}@Overrideprotected 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);}}}

MainActivity

package com.zhy.weixin6.ui;import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;import android.annotation.SuppressLint;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.view.ViewPager;
import android.support.v4.view.ViewPager.OnPageChangeListener;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewConfiguration;
import android.view.Window;
import android.widget.SearchView;
import android.widget.Toast;@SuppressLint("NewApi")
public class MainActivity extends FragmentActivity implementsOnPageChangeListener, OnClickListener
{private ViewPager mViewPager;private List<Fragment> mTabs = new ArrayList<Fragment>();private FragmentPagerAdapter mAdapter;private String[] mTitles = new String[] { "First Fragment!","Second Fragment!", "Third Fragment!", "Fourth Fragment!" };private List<ChangeColorIconWithTextView> mTabIndicator = new ArrayList<ChangeColorIconWithTextView>();@Overrideprotected void onCreate(Bundle savedInstanceState){super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);setOverflowShowingAlways();getActionBar().setDisplayShowHomeEnabled(false);mViewPager = (ViewPager) findViewById(R.id.id_viewpager);initDatas();mViewPager.setAdapter(mAdapter);mViewPager.setOnPageChangeListener(this);}private void initDatas(){for (String title : mTitles){TabFragment tabFragment = new TabFragment();Bundle args = new Bundle();args.putString("title", title);tabFragment.setArguments(args);mTabs.add(tabFragment);}mAdapter = new FragmentPagerAdapter(getSupportFragmentManager()){@Overridepublic int getCount(){return mTabs.size();}@Overridepublic Fragment getItem(int arg0){return mTabs.get(arg0);}};initTabIndicator();}SearchView searchView;@Overridepublic boolean onCreateOptionsMenu(Menu menu){getMenuInflater().inflate(R.menu.main, menu);MenuItem searchItem = menu.findItem(R.id.action_search);  searchView = (SearchView) searchItem.getActionView();  return true;}@Overridepublic boolean onSearchRequested() {// TODO Auto-generated method stubToast.makeText(getApplicationContext(), searchView.getQuery(), 0).show();return super.onSearchRequested();}private void initTabIndicator(){ChangeColorIconWithTextView one = (ChangeColorIconWithTextView) findViewById(R.id.id_indicator_one);ChangeColorIconWithTextView two = (ChangeColorIconWithTextView) findViewById(R.id.id_indicator_two);ChangeColorIconWithTextView three = (ChangeColorIconWithTextView) findViewById(R.id.id_indicator_three);ChangeColorIconWithTextView four = (ChangeColorIconWithTextView) findViewById(R.id.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);}@Overridepublic void onPageSelected(int arg0){}@Overridepublic void onPageScrolled(int position, float positionOffset,int positionOffsetPixels){// Log.e("TAG", "position = " + position + " , positionOffset = "// + positionOffset);if (positionOffset > 0){ChangeColorIconWithTextView left = mTabIndicator.get(position);ChangeColorIconWithTextView right = mTabIndicator.get(position + 1);left.setIconAlpha(1 - positionOffset);right.setIconAlpha(positionOffset);}}@Overridepublic void onPageScrollStateChanged(int state){}@Overridepublic void onClick(View v){resetOtherTabs();switch (v.getId()){case R.id.id_indicator_one:mTabIndicator.get(0).setIconAlpha(1.0f);mViewPager.setCurrentItem(0, false);break;case R.id.id_indicator_two:mTabIndicator.get(1).setIconAlpha(1.0f);mViewPager.setCurrentItem(1, false);break;case R.id.id_indicator_three:mTabIndicator.get(2).setIconAlpha(1.0f);mViewPager.setCurrentItem(2, false);break;case R.id.id_indicator_four:mTabIndicator.get(3).setIconAlpha(1.0f);mViewPager.setCurrentItem(3, false);break;}}/*** 重置其他的Tab*/private void resetOtherTabs(){for (int i = 0; i < mTabIndicator.size(); i++){mTabIndicator.get(i).setIconAlpha(0);}}@Overridepublic 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 (Exception e){}}}return super.onMenuOpened(featureId, menu);}private void setOverflowShowingAlways(){try{// true if a permanent menu key is present, false otherwise.ViewConfiguration config = ViewConfiguration.get(this);Field menuKeyField = ViewConfiguration.class.getDeclaredField("sHasPermanentMenuKey");menuKeyField.setAccessible(true);menuKeyField.setBoolean(config, false);} catch (Exception e){e.printStackTrace();}}}

Activity里面代码虽然没什么注释,但是很简单哈,就是初始化Fragment,得到我们的适配器,然后设置给ViewPager;
initTabIndicator我们初始化我们的自定义控件,以及加上了点击事件;
唯一一个需要指出的就是:
我们在onPageScrolled中,动态的获取position以及positionOffset,然后拿到左右两个View,设置positionOffset ;

两个反射的方法,是控制Actionbar的图标的,和点击menu按键显示的

TabFragment

package com.zhy.weixin6.ui;  import android.graphics.Color;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;  public class TabFragment extends Fragment
{  private String mTitle = "Default";  public TabFragment()  {  }  @Override  public View onCreateView(LayoutInflater inflater, ViewGroup container,  Bundle savedInstanceState)  {  if (getArguments() != null)  {  mTitle = getArguments().getString("title");  }  TextView textView = new TextView(getActivity());  textView.setTextSize(20);  textView.setBackgroundColor(Color.parseColor("#ffffffff"));  textView.setGravity(Gravity.CENTER);  textView.setText(mTitle);  return textView;  }
}  

menu.xml文件

<menu xmlns:android="http://schemas.android.com/apk/res/android" ><itemandroid:id="@+id/action_search"android:actionViewClass="android.widget.SearchView"android:icon="@drawable/actionbar_search_icon"android:showAsAction="ifRoom|collapseActionView"android:title="@string/action_search"/><itemandroid:id="@+id/action_group_chat"android:icon="@drawable/ofm_group_chat_icon"android:title="@string/action_group_chat"/><itemandroid:id="@+id/action_add_friend"android:icon="@drawable/ofm_add_icon"android:title="@string/action_add_friend"/><itemandroid:id="@+id/action_scan"android:icon="@drawable/ofm_qrcode_icon"android:title="@string/action_scan"/><itemandroid:id="@+id/action_feed"android:icon="@drawable/ofm_feedback_icon"android:title="@string/action_feed"/></menu>

源码下载

源码下载

参考链接

Android 高仿微信6.0主界面 带你玩转切换图标变色 - Hongyang - 博客频道 - CSDN.NET
http://blog.csdn.net/lmj623565791/article/details/41087219

Android仿微信界面相关推荐

  1. Android仿微信界面--使用Fragment实现(慕课网笔记)

    来自:http://www.imooc.com/video/5903 可参考另一篇博客http://blog.csdn.net/hnyzwtf/article/details/50278377 1 效 ...

  2. 微信界面代码android,仿微信界面代码安卓版

    主页 用的是Fragment 这样的好处是可以独立编辑独立的页 package com.example.weixin_jiemian; import java.util.ArrayList; impo ...

  3. android仿微信界面的实现

     http://download.csdn.net/detail/u014355029/7243433 上面的链接是下载的地址. 效果图如下.

  4. Android 二维码扫描(仿微信界面),根据Google zxing

    Android 二维码扫描(仿微信界面),根据Google zxing Android项目开发中经常会用到二维码扫描,例如登陆.支付等谷歌方面已经有了一个开源库(地址: https://github. ...

  5. android 仿微信聊天界面 以及语音录制功能,Android仿微信录制语音功能

    本文实例为大家分享了Android仿微信录制语音的具体代码,供大家参考,具体内容如下 前言 我把录音分成了两部分 1.UI界面,弹窗读秒 2.一个类(包含开始.停止.创建文件名功能) 第一部分 由于6 ...

  6. android 仿微信demo————微信主界面实现

    android 仿微信demo----微信启动界面实现 android 仿微信demo----注册功能实现(移动端) android 仿微信demo----注册功能实现(服务端) android 仿微 ...

  7. android 仿微信demo————微信发现界面实现

    android 仿微信demo----微信启动界面实现 android 仿微信demo----注册功能实现(移动端) android 仿微信demo----注册功能实现(服务端) android 仿微 ...

  8. android 仿微信demo————微信消息界面实现(移动端)

    android 仿微信demo----微信启动界面实现 android 仿微信demo----注册功能实现(移动端) android 仿微信demo----注册功能实现(服务端) android 仿微 ...

  9. android 仿微信demo————微信通讯录界面功能实现(移动端,服务端)

    android 仿微信demo----微信启动界面实现 android 仿微信demo----注册功能实现(移动端) android 仿微信demo----注册功能实现(服务端) android 仿微 ...

最新文章

  1. Color the ball----HDOJ1556
  2. java log4j mysql_java – 配置log4j属性文件以存储在mysql数据库中
  3. ExtJs Ext.panel.Panel和Ext.container.Viewport布局问题
  4. Xilinx下载方式(具体可以参考配置MCS文件时右下角help调出的doc)
  5. hash值 更改git_Git切换版本
  6. Linux i2c子系统驱动probe
  7. hdu 5139 数据的离线处理
  8. Bootstrap 按钮的外观
  9. 字符编码详解及由来(UNICODE,UTF-8,GBK)
  10. Java基础之Http协议的理解与总结
  11. Qt——消息对话框的设计
  12. 基于OPENCV的图形识别系统
  13. 山东大学研究生计算机学院导师,山东大学计算机科学与技术学院研究生导师简介-杨义军...
  14. Web2.0大潮行将衰退 90%相关公司可能消失
  15. ElasticSearch的常用查询语句
  16. 浅谈大数据平台架构设计
  17. 汪子嵩:论有、存在与是(如是——真如)
  18. python数据结构——无序,有序列表抽象数据类型,链表
  19. Xcon2014 Geekpwn2014
  20. 广告深度学习计算:召回算法和工程协同优化的若干经验

热门文章

  1. 忙累了躺平,躺醒后该干点啥
  2. 巨省显存的重计算技巧在TF、Keras中的正确打开方式
  3. 深度学习在美团配送ETA预估中的探索与实践 1
  4. Java多线程系列(六):深入详解Synchronized同步锁的底层实现
  5. 【TensorFlow】实现、训练并评估简单的回归模型和分类模型
  6. www.sirim-global.com
  7. 洛谷 P1091 合唱队形
  8. 游戏“冰川滑行”设计稿(第一版)
  9. php: eclipse 编辑 php
  10. 哀悼地震遇难者--5月19至21日为全国哀悼日