Android仿微信底部按钮滑动变色

Android仿微信底部按钮滑动变色,这里只针对使用Fragment为Tab页的滑动操作,进行简单的变色讲解。

首先说下OnPageChangeListener这个监听

//这个监听有三个方法
public abstract void onPageScrollStateChanged (int state) 

public abstract void onPageScrolled (int position, float positionOffset, int positionOffsetPixels) 

public abstract void onPageSelected (int position) 

//第一个方法onPageScrollStateChanged 中的参数state,有三个可取的值

public static final int SCROLL_STATE_DRAGGING
Constant Value: 1 (0x00000001) //手指按在ViewPager上滑动时

public static final int SCROLL_STATE_IDLE
Constant Value: 0 (0x00000000) //手指松开后,ViewPager自动滑动期间

public static final int SCROLL_STATE_SETTLING
Constant Value: 2 (0x00000002) //ViewPager进入了某个Page

//如果在onPageScrollStateChanged 中输出state的值,你会发现每次都是按顺序打印出“1---2---0”

//第二个方法onPageScrolled的三个参数

position://滑动时,屏幕左侧显示的第一个page

positionOffset://滑动比例,值的范围为[0, 1),手指往左滑动,该值递增,反之递减

positionOffsetPixels://滑动距离,和屏幕有关,手指往左滑动,该值递增,反之递减

//我们经常需要检查viewpager的滑动方向并作出一些操作,这时你只需要通过position和positionOffset两个值即可实现该功能。

//比如实现微信底部图标颜色渐变 向左滑动时

ChangeColorIconWithTextView left = mTabIndicator.get(position); //左侧显示的第一个page页面上底部图标和文字的初始化
ChangeColorIconWithTextView right = mTabIndicator.get(position + 1); //右侧显示的Page底部图标和文字的初始化

left.setIconAlpha(1 - positionOffset); //设置图标的透明度 此时positionOffset值递增 左侧图标的颜色变浅
right.setIconAlpha(positionOffset); //右侧图标的颜色逐渐变深

//第三个方法onPageSelected的三个参数

position://当前选择的page序号

//该方法被调用的时间比较特别,在上面的第一个方法中的“1---2----0”中的2执行之后,onPageSelected就执行,然后执行“1---2----0”中的0。就是手指松开屏幕之后,onPageSelected被执行。

上面提到了ChangeColorIconWithTextView 主要类

package com.mhealth.nursestation.app.pda.business.login.base.ui.fragmentutil;

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.TypedValue;
import android.view.View;

import com.mhealth.nursestation.app.pda.R;

/**
 * 此类用于修改颜色渐变
 */
public class ChangeColorIconWithTextView extends View {

  private Bitmap mBitmap;
  private Canvas mCanvas;
  private Paint mPaint;
  /**
   * 颜色
   */
  private int mColor = 0XFF07B7C4;
  /**
   * 透明度 0.0-1.0 初始化必须是0 不是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, 0x07B7C4);
        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(0xff07B7C4);
    mTextPaint.setAntiAlias(true);
    // 得到text绘制范围
    mTextPaint.getTextBounds(mText, 0, mText.length(), mTextBound);

  }

  @Override
  protected 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);

  }

  @Override
  protected 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);
  }

  /**
   * 透明度 255
   *
   * @param canvas
   * @param alpha
   */
  private void drawSourceText(Canvas canvas, int alpha) {
    mTextPaint.setTextSize(mTextSize);
    mTextPaint.setColor(0x00333333);
    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";

  @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);
    }
  }
}

在Activity里面实现监听操作

@Override
  public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {

    if (positionOffset > 0) {
      ChangeColorIconWithTextView left = mTabIndicator.get(position);
      ChangeColorIconWithTextView right = mTabIndicator.get(position + 1);

      left.setIconAlpha(1 - positionOffset);
      right.setIconAlpha(positionOffset);
    }
  }

定义一个集合,将所有变色控件装载进去

private List<ChangeColorIconWithTextView> mTabIndicator = new ArrayList<ChangeColorIconWithTextView>();

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);
  }

点击监听

@Override
  public 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);
      mAppContext.has_new_talk = false;

      break;
    case R.id.id_indicator_four:
      mTabIndicator.get(3).setIconAlpha(1.0f);
      mViewPager.setCurrentItem(3, false);
      break;

    }
  }

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

时间: 2017-03-27

Android开发之微信底部菜单栏实现的几种方法汇总

 实现方式 实现的方式有很多种 这里总结最常见的几种方式,以后再添加其他的. viewPager + RadioGroup viewPager + FragmentTabHost viewpager +TabLayout viewPager+RadioGroup 感觉这是最简单的一个了,我也就不贴代码 说说我理解的思路吧 通过给pager 和RadioGroup 添加监听,监听两个控件的变化 实现联动 当viewPager的显示pager改变就会触发监听 ,在监听中选中对应的RadioButto

android 中viewpager+fragment仿微信底部TAG完美渐变

viewpager+fragment仿微信底部TAG完美渐变,在图片渐变的同时字的颜色也在变,注意,是渐变哦! 效果图: activity_main.xml <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:zhy="http://schemas.android.com/apk/res/com.Sing.weixin" xmlns:tools="

Android仿微信底部实现Tab选项卡切换效果

在网上看了比较多的关于Tab的教程,发现都很杂乱.比较多的用法是用TitlePagerTabStrip和ViewPaper.不过TitlePagerTabStrip有个很大的缺陷,Tab里面的内容刚进去是没有的,要滑一次才能加载出来.而且滑动的时候,Tab里面的内容位置不是固定的,滑倒最后会出现一片空白,非常不美观.虽然有其他的补救方法,但是非常的麻烦,所以我就按照自己的方法实现了一个,功能不错而且非常简单. 直接点击或者是滑动界面,都可以转到相应的页面. 效果图: 原理是用了三个按钮和View

Android仿微信底部菜单栏功能显示未读消息数量

底部菜单栏很重要,我看了一下很多应用软件都是用了底部菜单栏,这里使用了tabhost做了一种通用的(就是可以像微信那样显示未读消息数量的,虽然之前也做过但是layout下的xml写的太臃肿,这里去掉了很多不必要的层,个人看起来还是不错的,所以贴出来方便以后使用). 先看一下做出来之后的效果: 以后使用的时候就可以换成自己项目的图片和字体了,主框架不用变哈哈, 首先是要布局layout下xml文件 main.xml: <?xml version="1.0" encoding=&qu

Android仿微信底部菜单栏效果

前言 在市面上,大多数的APP都需要通过底部菜单栏来将程序的功能进行分类整理,通常都是分为3-5个大模块,从而正确有效地引导用户去使用我们的APP.实现底部菜单栏的方法也有很多种. 1.仿微信底部菜单栏(ViewPager+ImagerView+TextView) ......(其他方式后续会补充) 效果预览 首先来个开胃菜,看看实现效果: 先贴出项目所需的资源文件,这些可随个人自由更改颜色和文字 colors.xml <color name="bg_line_light_gray&quo

Flutter实现仿微信底部菜单栏功能

import 'package:flutter/material.dart'; void main() => runApp(MyApp()); class MyApp extends StatelessWidget{ @override Widget build(BuildContext context) { return MaterialApp( home: Scaffold( body: MyHomePage(), ), ); } } class MyHomePage extends Sta

Android 仿微信底部渐变Tab效果

先来看一下效果图 除了第三个的发现Tab有所差别外,其他的基本还原了微信的底部Tab渐变效果 每个Tab都是一个自定义View,根据ImageView的tint属性来实现颜色渐变效果,tint属性的使用可以看我的上一篇文章 我将自定义View命名为ShadeView,包含四个自定义属性 意思分别为图标.背景色.底部文本.底部文本大小 <declare-styleable name="ShadeView"> <attr name="icon" for

Android仿微信语音聊天功能

本文实例讲述了Android仿微信语音聊天功能代码.分享给大家供大家参考.具体如下: 项目效果如下: 具体代码如下: AudioManager.java package com.xuliugen.weichat; import java.io.File; import java.io.IOException; import java.util.UUID; import android.media.MediaRecorder; public class AudioManager { private

Android 桌面图标右上角显示未读消息数字

背景: 在Android原生系统中,众所周知不支持桌面图标显示未读消息提醒的数字,虽然第三方控件BadgeView可以实现应用内的数字提醒.但对于系统的图标,特别是app的logo图标很难实现数字标志,即使是绘图的方式不断修改,但这种方式天生弊端,实用性很差.但幸运的是,一些强大的手机厂商(小米,三星,索尼)提供了私有的API,但也带来了难度,API的不同就意味着代码量的增加和兼容性问题更加突出. 现在我们来看看他们是如何实现的: 实现原理: 首先我们要明白 并不是应用本身处理对启动图标进行修改

Android 给应用程序的icon添加未读消息个数提示(红圈内数字)

最近在做一个可以查看未读消息的功能,需要在界面中的Tab页的标签icon的右上角添加一个未读消息提示的功能. 先上个效果图出来,比较直观明白需求: 思路上似乎有两种:  1. 直接把底图和红圆圈的图片用相对布局进行排列,在代码中动态更改红圆中的TextView的数字,并且识别一下各种情况下红圆的显示或者隐藏.这种方法比较直观.  2. 采用canvas画出圆和数字. 由于项目采用的是Tab页的形式,其中的RadioButton不适合采用相对布局.故我采用了第二种方式.将绘制的过程写成了工具方法.

android仿微信好友列表功能

android studio实现微信好友列表功能,注意有一个jar包我没有放上来,请大家到MainActivity中的那个网址里面下载即可,然后把pinyin4j-2.5.0.jar复制粘贴到项目的app/libs文件夹里面,然后clean项目就可以使用了 实现效果图: (1)在build.gradle中引用第三方的类库 compile 'com.android.support:recyclerview-v7:26.0.0-alpha1' compile files('libs/pinyin4j

Android仿微信录制语音功能

本文实例为大家分享了Android仿微信录制语音的具体代码,供大家参考,具体内容如下 前言 我把录音分成了两部分 1.UI界面,弹窗读秒 2.一个类(包含开始.停止.创建文件名功能) 第一部分 由于6.0权限问题,点击按钮申请权限通过则弹窗,如何申请权限 弹窗布局popw_record.xml <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http: