首页 > 系统 > Android > 正文

Android 微信6.1 tab栏图标和字体颜色渐变的实现

2019-12-12 04:11:42
字体:
来源:转载
供稿:网友

相信大家都见到了微信图标颜色渐变的过程,是不是感觉很牛逼?不得不说微信团队确实是很厉害的团队,不管是从设计还是开发人员。

今天我带大家来看看,微信 tab 栏图标和字体颜色渐变的过程。先上图吧!今天学了一招制作 gif 动态图的快捷方法。刚好用的上,以前一直想写点什么东西,

苦于一直不知道怎么生成动态图,现在终于学会了,哈哈,让我偷偷的乐一会。额,还是上图吧。。。

好了,效果图也看到了,那么我也就不多嗦了,直接进入主题,看代码

[java] view plain copypackage moon.wechat.view; import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.Rect; import android.util.AttributeSet; import android.util.TypedValue; import android.view.View; /**  * Created by moon.zhong on 2015/2/4.  */ public class TabItem extends View {   /*字体大小*/   private int mTextSize ;   /*字体选中的颜色*/   private int mTextColorSelect ;   /*字体未选择的时候的颜色*/   private int mTextColorNormal;   /*绘制未选中时字体的画笔*/   private Paint mTextPaintNormal;   /*绘制已选中时字体的画笔*/   private Paint mTextPaintSelect;   /*每个 item 的宽和高,包括字体和图标一起*/   private int mViewHeight, mViewWidth;   /*字体的内容*/   private String mTextValue ;   /*已选中时的图标*/   private Bitmap mIconNormal;   /*未选中时的图标*/   private Bitmap mIconSelect;   /*用于记录字体大小*/   private Rect mBoundText;   /*已选中是图标的画笔*/   private Paint mIconPaintSelect;   /*为选中时图标的画笔*/   private Paint mIconPaintNormal;   public TabItem(Context context) {     this(context, null);   }   public TabItem(Context context, AttributeSet attrs) {     this(context, attrs, 0);   }   public TabItem(Context context, AttributeSet attrs, int defStyleAttr) {     super(context, attrs, defStyleAttr);     initView();     initText();   }   /*初始化一些东西*/   private void initView() {     mBoundText = new Rect();   }   /*初始化画笔,并设置出是内容*/   private void initText() {     mTextPaintNormal = new Paint();     mTextPaintNormal.setTextSize(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, mTextSize, getResources().getDisplayMetrics()));     mTextPaintNormal.setColor(mTextColorNormal);     mTextPaintNormal.setAntiAlias(true);     mTextPaintNormal.setAlpha(0xff);     mTextPaintSelect = new Paint();     mTextPaintSelect.setTextSize(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, mTextSize, getResources().getDisplayMetrics()));     mTextPaintSelect.setColor(mTextColorSelect);     mTextPaintSelect.setAntiAlias(true);     mTextPaintSelect.setAlpha(0);     mIconPaintSelect = new Paint(Paint.ANTI_ALIAS_FLAG) ;     mIconPaintSelect.setAlpha(0);     mIconPaintNormal = new Paint(Paint.ANTI_ALIAS_FLAG) ;     mIconPaintNormal.setAlpha(0xff);   }   /*测量字体的大小*/   private void measureText() {     mTextPaintNormal.getTextBounds(mTextValue, 0, mTextValue.length(), mBoundText);   }   /*测量字体和图标的大小,并设置自身的宽和高*/   @Override   protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {     int widthMode = MeasureSpec.getMode(widthMeasureSpec);     int heightMode = MeasureSpec.getMode(heightMeasureSpec);     int widthSize = MeasureSpec.getSize(widthMeasureSpec);     int heightSize = MeasureSpec.getSize(heightMeasureSpec);     int width = 0, height = 0;     measureText();     int contentWidth = Math.max(mBoundText.width(), mIconNormal.getWidth());     int desiredWidth = getPaddingLeft() + getPaddingRight() + contentWidth;     switch (widthMode) {       case MeasureSpec.AT_MOST:         width = Math.min(widthSize, desiredWidth);         break;       case MeasureSpec.EXACTLY:         width = widthSize;         break;       case MeasureSpec.UNSPECIFIED:         width = desiredWidth;         break;     }     int contentHeight = mBoundText.height() + mIconNormal.getHeight();     int desiredHeight = getPaddingTop() + getPaddingBottom() + contentHeight;     switch (heightMode) {       case MeasureSpec.AT_MOST:         height = Math.min(heightSize, desiredHeight);         break;       case MeasureSpec.EXACTLY:         height = heightSize;         break;       case MeasureSpec.UNSPECIFIED:         height = contentHeight;         break;     }     setMeasuredDimension(width, height);     mViewWidth = getMeasuredWidth() ;     mViewHeight = getMeasuredHeight() ;   }   @Override   protected void onDraw(Canvas canvas) {     drawBitmap(canvas) ;     drawText(canvas) ;   }   /*话图标,先画为选中的图标,在画已选中的图标*/   private void drawBitmap(Canvas canvas) {     int left = (mViewWidth - mIconNormal.getWidth())/2 ;     int top = (mViewHeight - mIconNormal.getHeight() - mBoundText.height()) /2 ;     canvas.drawBitmap(mIconNormal, left, top ,mIconPaintNormal);     canvas.drawBitmap(mIconSelect, left, top , mIconPaintSelect);   }   /*画字体*/   private void drawText(Canvas canvas) {     float x = (mViewWidth - mBoundText.width())/2.0f ;     float y = (mViewHeight + mIconNormal.getHeight() + mBoundText.height()) /2.0F ;     canvas.drawText(mTextValue,x,y, mTextPaintNormal);     canvas.drawText(mTextValue,x,y, mTextPaintSelect);   }   public void setTextSize(int textSize) {     this.mTextSize = textSize;     mTextPaintNormal.setTextSize(textSize);     mTextPaintSelect.setTextSize(textSize);   }   public void setTextColorSelect(int mTextColorSelect) {     this.mTextColorSelect = mTextColorSelect;     mTextPaintSelect.setColor(mTextColorSelect);     mTextPaintSelect.setAlpha(0);   }   public void setTextColorNormal(int mTextColorNormal) {     this.mTextColorNormal = mTextColorNormal;     mTextPaintNormal.setColor(mTextColorNormal);     mTextPaintNormal.setAlpha(0xff);   }   public void setTextValue(String TextValue) {     this.mTextValue = TextValue;   }   public void setIconText(int[] iconSelId,String TextValue) {     this.mIconSelect = BitmapFactory.decodeResource(getResources(), iconSelId[0]);     this.mIconNormal = BitmapFactory.decodeResource(getResources(), iconSelId[1]);     this.mTextValue = TextValue;   }   /*通过 alpha 来设置 每个画笔的透明度,从而实现现实的效果*/   public void setTabAlpha(float alpha){     int paintAlpha = (int)(alpha*255) ;     mIconPaintSelect.setAlpha(paintAlpha);     mIconPaintNormal.setAlpha(255-paintAlpha);     mTextPaintSelect.setAlpha(paintAlpha);     mTextPaintNormal.setAlpha(255-paintAlpha);     invalidate();   } } 

分析: 以上代码,功能实现 tab 的每个 item 的内容,在微信的项目中也就是,一个图标加一个字体,

关键代码就在public void setTabAlpha(float alpha) 这个方法,此方法是 viewPager 切换 item 时,不断改变偏移量来调用,从而不断改变

每个画笔的透明度,实现图标和颜色的渐变;是不是很简单?到这里其实我们颜色渐变的代码就已经实现了。接下来的内容可以忽略

这样我们只需要在 MainActivity 的 xml 中定义一个线性布局,然后放如四个我们自定义的 View 进去,就可以了。但是这样你就满足了吗?

我先来给你们看看我的MainActivity的代码;

[java] view plain copypackage moon.wechat; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentManager; import android.support.v4.app.FragmentPagerAdapter; import android.support.v4.view.ViewPager; import android.support.v7.app.ActionBarActivity; import android.os.Bundle; import java.util.HashMap; import java.util.Map; import moon.wechat.view.TabView; public class MainActivity extends ActionBarActivity {   private String[] mTitle = {"微信", "通讯录", "发现", "我"};   private int[] mIconSelect = {R.drawable.al_, R.drawable.al8, R.drawable.alb, R.drawable.ald};   private int[] mIconNormal = {R.drawable.ala, R.drawable.al9, R.drawable.alc, R.drawable.ale};   private ViewPager mViewPager ;   private TabView mTabView ;   private Map<Integer,Fragment> mFragmentMap ;   @Override   protected void onCreate(Bundle savedInstanceState) {     super.onCreate(savedInstanceState);     setContentView(R.layout.activity_main);     mFragmentMap = new HashMap<>() ;     mViewPager = (ViewPager)findViewById(R.id.id_view_pager) ;     mViewPager.setOffscreenPageLimit(4);     mViewPager.setAdapter(new PageAdapter(getSupportFragmentManager()));     mTabView = (TabView)findViewById(R.id.id_tab) ;     mTabView.setViewPager(mViewPager);   }   private Fragment getFragment(int position){     Fragment fragment = mFragmentMap.get(position) ;     if(fragment == null){       switch (position){         case 0:           fragment = new WeChatFragment() ;           break ;         case 1:           fragment = new WeContactFragment();           break ;         case 2:           fragment = new WeDiscoverFragment();           break;         case 3:           fragment = new GameFragment() ; //          fragment = new WeMineFragment();           break;       }       mFragmentMap.put(position,fragment) ;     }     return fragment ;   }   class PageAdapter extends FragmentPagerAdapter implements TabView.OnItemIconTextSelectListener{     public PageAdapter(FragmentManager fm) {       super(fm);     }     @Override     public Fragment getItem(int position) {       return getFragment(position);     }     @Override     public int[] onIconSelect(int position) {       int icon[] = new int[2] ;       icon[0] = mIconSelect[position] ;       icon[1] = mIconNormal[position] ;       return icon;     }     @Override     public String onTextSelect(int position) {       return mTitle[position];     }     @Override     public int getCount() {       return mTitle.length;     }   } } 

是不是很简单,而 xml 更简单

[html] view plain copy<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"   xmlns:zgy="http://schemas.android.com/apk/res-auto"   android:layout_width="match_parent"   android:layout_height="match_parent"   android:background="@android:color/white"   android:orientation="vertical">   <android.support.v4.view.ViewPager     android:id="@+id/id_view_pager"     android:layout_width="match_parent"     android:layout_height="wrap_content"     android:layout_weight="1"     >     </android.support.v4.view.ViewPager>   <moon.wechat.view.TabView     android:id="@+id/id_tab"     android:layout_width="match_parent"     android:layout_height="wrap_content"     android:orientation="horizontal"     android:background="#eeeeee"     zgy:text_size="12sp"     zgy:text_normal_color="#ff777777"     zgy:text_select_color="#ff45c01a"     zgy:item_padding="7dp">    </moon.wechat.view.TabView> </LinearLayout> 

可以看到没有定义我们刚刚自定义的 TabItem,而是使用的 TabView,那 TabView 到底是啥东西?相信大家都想到了,TabView 其实就是我们自定义的线性布局,

[java] view plain copypackage moon.wechat.view; import android.content.Context; import android.content.res.TypedArray; import android.support.v4.view.PagerAdapter; import android.support.v4.view.ViewPager; import android.util.AttributeSet; import android.util.Log; import android.util.TypedValue; import android.view.View; import android.view.ViewGroup; import android.widget.LinearLayout; import java.util.ArrayList; import java.util.List; import moon.wechat.R; /**  * Created by moon.zhong on 2015/2/4.  */ public class TabView extends LinearLayout implements View.OnClickListener {   private ViewPager mViewPager;   private ViewPager.OnPageChangeListener mOnPageChangeListener;   private PagerAdapter mPagerAdapter;   private int mChildSize;   private List<TabItem> mTabItems;   private OnItemIconTextSelectListener mListener;   private int mTextSize = 12;   private int mTextColorSelect = 0xff45c01a;   private int mTextColorNormal = 0xff777777;   private int mPadding = 10;   public TabView(Context context) {     this(context, null);   }   public TabView(Context context, AttributeSet attrs) {     this(context, attrs, 0);   }   public TabView(Context context, AttributeSet attrs, int defStyleAttr) {     super(context, attrs, defStyleAttr);     TypedArray typedArray = getResources().obtainAttributes(attrs, R.styleable.TabView);     int N = typedArray.getIndexCount();     for (int i = 0; i < N; i++) {       switch (typedArray.getIndex(i)) {         case R.styleable.TabView_text_size:           mTextSize = (int) typedArray.getDimension(i, TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP,               mTextSize, getResources().getDisplayMetrics()));           break;         case R.styleable.TabView_text_normal_color:           mTextColorNormal = typedArray.getColor(i, mTextColorNormal);           break;         case R.styleable.TabView_text_select_color:           mTextColorSelect = typedArray.getColor(i, mTextColorSelect);           break;         case R.styleable.TabView_item_padding:           mPadding = (int) typedArray.getDimension(i, TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,               mPadding, getResources().getDisplayMetrics()));           break;       }     }     typedArray.recycle();     mTabItems = new ArrayList<>();   }   public void setViewPager(final ViewPager mViewPager) {     if (mViewPager == null) {       return;     }     this.mViewPager = mViewPager;     this.mPagerAdapter = mViewPager.getAdapter();     if (this.mPagerAdapter == null) {       throw new RuntimeException("亲,在您设置TabView的ViewPager时,请先设置ViewPager的PagerAdapter");     }     this.mChildSize = this.mPagerAdapter.getCount();     this.mViewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {       @Override       public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { //        Log.v("zgy","=============position="+position+",====positionOffset="+positionOffset) ;         View leftView;         View rightView;         if (positionOffset > 0) {           leftView = mViewPager.getChildAt(position);           rightView = mViewPager.getChildAt(position + 1);           leftView.setAlpha(1 - positionOffset);           rightView.setAlpha(positionOffset);           mTabItems.get(position).setTabAlpha(1 - positionOffset);           mTabItems.get(position + 1).setTabAlpha(positionOffset);         } else {           mViewPager.getChildAt(position).setAlpha(1);           mTabItems.get(position).setTabAlpha(1 - positionOffset);         }         if (mOnPageChangeListener != null) { mOnPageChangeListener.onPageScrolled(position, positionOffset, positionOffsetPixels);         }       }       @Override       public void onPageSelected(int position) {         if (mOnPageChangeListener != null) { mOnPageChangeListener.onPageSelected(position);         }       }       @Override       public void onPageScrollStateChanged(int state) {         if (mOnPageChangeListener != null) { mOnPageChangeListener.onPageScrollStateChanged(state);         }       }     });     if (mPagerAdapter instanceof OnItemIconTextSelectListener) {       mListener = (OnItemIconTextSelectListener) mPagerAdapter;     }else {       throw new RuntimeException("请让你的pageAdapter实现OnItemIconTextSelectListener接口");     }     initItem();   }   public void setOnPageChangeListener(ViewPager.OnPageChangeListener mOnPageChangeListener) {     this.mOnPageChangeListener = mOnPageChangeListener;   }   private void initItem() {     for (int i = 0; i < mChildSize; i++) {       TabItem tabItem = new TabItem(getContext());       LayoutParams params = new LayoutParams(0, ViewGroup.LayoutParams.WRAP_CONTENT, 1);       tabItem.setPadding(mPadding, mPadding, mPadding, mPadding);       tabItem.setIconText(mListener.onIconSelect(i), mListener.onTextSelect(i));       tabItem.setTextSize(mTextSize);       tabItem.setTextColorNormal(mTextColorNormal);       tabItem.setTextColorSelect(mTextColorSelect);       tabItem.setLayoutParams(params);       tabItem.setTag(i);       tabItem.setOnClickListener(this);       mTabItems.add(tabItem);       addView(tabItem);     }   }   @Override   protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {     super.onMeasure(widthMeasureSpec, heightMeasureSpec);   }   @Override   public void onClick(View v) {     int position = (Integer) v.getTag();     if (mViewPager.getCurrentItem() == position) {       return;     }     for (TabItem tabItem : mTabItems) {       tabItem.setTabAlpha(0);     }     mTabItems.get(position).setTabAlpha(1);     mViewPager.setCurrentItem(position, false);   }   public interface OnItemIconTextSelectListener {     int[] onIconSelect(int position);     String onTextSelect(int position);   } } 

注释有点少,额,不是少,是压根就没有,其实,这个类的代码不需要注释,我相信大家都能看懂,我就讲下他的作用吧,

  1. 添加 item
  2. 监听 ViewPager 的滚动事件,从而设置相应 item 之间的颜色渐变,
  3. 设置相应 ViewPage 的透明度
  4. 为 TabItem 设置监听事件,

其实上面很多功能本来是在 MainActivity 中实现的,为了减少 Activity 内部的代码量,抽取出来,到达低耦合,高内聚的效果。

Ok,以上就是 微信6.1 tab 栏颜色渐变效果的实现全过程。

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,同时也希望多多支持武林网!

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表