我的编程空间,编程开发者的网络收藏夹
学习永远不晚

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

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

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

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

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

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

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


[java] view plain copy
package 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; 
 
public class TabItem extends View { 
   
  private int mTextSize ; 
   
  private int mTextColorSelect ; 
   
  private int mTextColorNormal; 
   
  private Paint mTextPaintNormal; 
   
  private Paint mTextPaintSelect; 
   
  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; 
  } 
   
  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 copy
package 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 copy
package 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; 
 
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); 
  } 
} 

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

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

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

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

您可能感兴趣的文章:Android 图片的颜色处理实例代码Android编程之图片颜色处理方法Android开发中使用颜色矩阵改变图片颜色,透明度及亮度的方法android中实现背景图片颜色渐变方法android开发修改状态栏背景色和图标颜色的示例Android实现修改状态栏背景、字体和图标颜色的方法Android 改变图标原有颜色和搜索框的实例代码Android编程实现图片的颜色处理功能示例


免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

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

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

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

相信大家都见到了微信图标颜色渐变的过程,是不是感觉很牛逼?不得不说微信团队确实是很厉害的团队,不管是从设计还是开发人员。 今天我带大家来看看,微信 tab 栏图标和字体颜色渐变的过程。先上图吧!今天学了一招制作 gif 动态图的快捷方法。刚
2022-06-06

Android实现修改状态栏背景、字体和图标颜色的方法

前言:Android开发,对于状态栏的修改,实在是不友好,没什么api可以用,不像ios那么方便.但是ui又喜欢只搞ios一套.没办法.各种翻源码,写反射.真的蛋疼.需求场景:当toolbar及状态栏需要为白色或浅色时(如简书),状态栏由于
2023-05-30

编程热搜

  • Android:VolumeShaper
    VolumeShaper(支持版本改一下,minsdkversion:26,android8.0(api26)进一步学习对声音的编辑,可以让音频的声音有变化的播放 VolumeShaper.Configuration的三个参数 durati
    Android:VolumeShaper
  • Android崩溃异常捕获方法
    开发中最让人头疼的是应用突然爆炸,然后跳回到桌面。而且我们常常不知道这种状况会何时出现,在应用调试阶段还好,还可以通过调试工具的日志查看错误出现在哪里。但平时使用的时候给你闹崩溃,那你就欲哭无泪了。 那么今天主要讲一下如何去捕捉系统出现的U
    Android崩溃异常捕获方法
  • android开发教程之获取power_profile.xml文件的方法(android运行时能耗值)
    系统的设置–>电池–>使用情况中,统计的能耗的使用情况也是以power_profile.xml的value作为基础参数的1、我的手机中power_profile.xml的内容: HTC t328w代码如下:
    android开发教程之获取power_profile.xml文件的方法(android运行时能耗值)
  • Android SQLite数据库基本操作方法
    程序的最主要的功能在于对数据进行操作,通过对数据进行操作来实现某个功能。而数据库就是很重要的一个方面的,Android中内置了小巧轻便,功能却很强的一个数据库–SQLite数据库。那么就来看一下在Android程序中怎么去操作SQLite数
    Android SQLite数据库基本操作方法
  • ubuntu21.04怎么创建桌面快捷图标?ubuntu软件放到桌面的技巧
    工作的时候为了方便直接打开编辑文件,一些常用的软件或者文件我们会放在桌面,但是在ubuntu20.04下直接直接拖拽文件到桌面根本没有效果,在进入桌面后发现软件列表中的软件只能收藏到面板,无法复制到桌面使用,不知道为什么会这样,似乎并不是很
    ubuntu21.04怎么创建桌面快捷图标?ubuntu软件放到桌面的技巧
  • android获取当前手机号示例程序
    代码如下: public String getLocalNumber() { TelephonyManager tManager =
    android获取当前手机号示例程序
  • Android音视频开发(三)TextureView
    简介 TextureView与SurfaceView类似,可用于显示视频或OpenGL场景。 与SurfaceView的区别 SurfaceView不能使用变换和缩放等操作,不能叠加(Overlay)两个SurfaceView。 Textu
    Android音视频开发(三)TextureView
  • android获取屏幕高度和宽度的实现方法
    本文实例讲述了android获取屏幕高度和宽度的实现方法。分享给大家供大家参考。具体分析如下: 我们需要获取Android手机或Pad的屏幕的物理尺寸,以便于界面的设计或是其他功能的实现。下面就介绍讲一讲如何获取屏幕的物理尺寸 下面的代码即
    android获取屏幕高度和宽度的实现方法
  • Android自定义popupwindow实例代码
    先来看看效果图:一、布局
  • Android第一次实验
    一、实验原理 1.1实验目标 编程实现用户名与密码的存储与调用。 1.2实验要求 设计用户登录界面、登录成功界面、用户注册界面,用户注册时,将其用户名、密码保存到SharedPreference中,登录时输入用户名、密码,读取SharedP
    Android第一次实验

目录