博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Android 开源SlideSwitch源码分析
阅读量:6582 次
发布时间:2019-06-24

本文共 4507 字,大约阅读时间需要 15 分钟。


大家都知道android的最大好处就是开源,其实很多项目能全部用开源就能搞定。但是当我们在用开源项目的时候,不懂得它们的原理,就相当于过眼云烟,行尸走肉,只有空壳没有宝贵的思想。当我们的项目一旦要维护于优化的时候,适应需求时,我们对那些只会拿来用的开源项目只能目瞪口呆。这样不仅没有加快我们的开发速度而且还会让我们全盘皆输。好了其它的也不多说,正式进入主题,分享一下自己最近对SlideSwitch开源代码的理解。


说明

首先还是要说明下SlideSwitch是什么开源项目,其实它就是一个我们几乎每个项目中都会遇到的滑动开关,还不懂请看下图:

图片描述

对于大神来说我想早就已经会了,所用这图也请大神早点回家吃饭的

分析要点

  • TypedArray 的使用
  • onMeasure 各个参数的初始化
  • onDraw 绘制图形
  • onTouchEvent 监听触摸点击
  • ValueAnimator 动画实现
  • SlideSwitchListener 接口

TypedArray

一般自定义控件都要用到TypedArray,所以SlideSwitch自然少不了。它就继承了Android原生的View。而*TypedArray是获取自定义属性的参数值。

首先我们会在styles&或者attrs中定义属性参数

format属性类型,然后在XML中引用,引用之前一定要加入下面的声明

xmlns:slideswitch="http://schemas.android.com/apk/res/xxx"

xxx:代表包名。直接引用就行

slideswitch:themeColor="#ffaaff"

最后在构造方法中通过下面代码获取设置的参数值:

TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.slideswitchview);        theme_color =     ta.getColor(R.styleable.slideswitchview_themeColor, DEFAULT_THEME_COLOR);        ta.recycle();
使用完后务必recycle否则会对下次的使用造成影响

onMeasure

每次视图的创建都要先获取视图的宽高,次方法就会被调用。该方法参数widthMeasureSpecheightMeasuerSpec不是一般的尺寸,而是包括了sizemode。所以为了获取实际的宽高,要使用如下方法分别获取sizemode

int size = MeasureSpec.getSize(measureSpec);    int mode = MeasureSpec.getMode(measureSpec);

通过mode来获取sizemode有三种:

  • EXACTLY 精确尺寸,就是我们指定的尺寸
  • UNSPECIFIED 为指定的
  • AT_MOST 最大尺寸 形如指定WRAP_CONTENT在父控件允许的范围内
if (mode == MeasureSpec.EXACTLY) {            result = size;        } else {            result = DefaultSize; //UNSPECIFIED            if (mode == MeasureSpec.AT_MOST) {                result = Math.min(size, result);            }        }
其它简单的参数值设置就不多说了,请移步最后的源码

onDraw

尺度获取到了后,下面自然就是绘制,我们都知道选择开关形状有矩形的也有圆角矩形所以根据shpe的值来绘制相应的形状,这里以矩形为例

if (shape == 1) {            mPaint.setColor(Color.GRAY);            //绘制close时的灰色背景            canvas.drawRect(backRect, mPaint);            mPaint.setColor(theme_color);            mPaint.setAlpha(alpha);            //绘制open时的彩色渐变背景            canvas.drawRect(backRect, mPaint);            mPaint.setColor(Color.WHITE);            frontRect.set(front_left, pandding, front_left + getMeasuredWidth() / 2 - pandding                    , getMeasuredHeight() - pandding);            //绘制滑动器            canvas.drawRect(frontRect, mPaint);        }

其中padding代表内边距,就是滑动器距边框的距离

onTouchEvent

这里就是实现动态的触摸滑动,根据ACTION_DOWNACTION_MOVEACTION_UP来实现动态效果,至于点坐标的处理,源码很清楚。这里主要提下alpha参数的变化,该参数是实现颜色的透明效果,在这里通过触摸滑动的间距,动态的改变alpha

alpha = (int) (255 * (float) front_left / (float) max_left);

ValueAnimator

这个类是动画效果的核心,通过简单的几步就能迅速的实现一些简单的动画

首先实例化这里使用的是ofInt(),当然也有ofFloat()等静态实例化方法

ValueAnimator valueAnimator = ValueAnimator.ofInt(front_left, toRight ? max_left : min_left);

两个参数初值与结束值

//设置插值器      valueAnimator.setInterpolator(new  AccelerateDecelerateInterpolator());    valueAnimator.setDuration(500);    valueAnimator.start();

Interpolator是定义动画的变化过程下面是一些常用参数

  • AccelerateDecelerateInterpolator 开始结束慢 中间过程快
  • AccelerateInterpolator 加速状态
  • AnticipateInterpolator 先后移一点,再快速移动
  • BounceInterpolator 在最后有弹球效果

当然你也可以自定义效果,只要继承TimeInterpolator类,重写getInterpolation方法自定义计算值

@Override      public float getInterpolation(float input) {          // 编写相关的逻辑计算          return input;      }

既然是动画自然有监听设置addUpdateListener实时改变滑动初始值雨alpha

valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {            @Override            public void onAnimationUpdate(ValueAnimator animation) {                front_left = (int) animation.getAnimatedValue();                alpha = (int) (255 * (float) front_left / (float) max_left);                initloop();            }        });

最后增加addListener调用下面的接口SlideSwitchListener中的方法

valueAnimator.addListener(new AnimatorListenerAdapter() {            @Override            public void onAnimationEnd(Animator animation) {                if (toRight) {                    isOpen = true;                    if (mSlideSwitchListener != null)                        mSlideSwitchListener.onOpen();                    front_start_left = max_left;                } else {                    isOpen = false;                    if (mSlideSwitchListener != null)                        mSlideSwitchListener.onClose();                    front_start_left = min_left;                }            }        });

SlideSwitchListener

接口的定义使得在操作类中能更好的实现状态改变后的相关操作

public void setSlideSwitchListener(SlideSwitchListener sideSwitchListener) {        mSlideSwitchListener = sideSwitchListener;    }    public interface SlideSwitchListener {        public void onOpen();        public void onClose();    }

只要稍微复杂的在这里都讲到了,还有不明白的可以点击查看下面我注释的源码,或者留言,谢谢浏览。

注释源码链接:

更多:

关注

clipboard.png

转载地址:http://zxino.baihongyu.com/

你可能感兴趣的文章
1163: 零起点学算法70——Yes,I can!
查看>>
关于图片或者文件在数据库的存储方式归纳
查看>>
ADO.NET笔记——使用DataSet返回数据
查看>>
Python脚本日志系统
查看>>
RowSet的使用
查看>>
每日一记--cookie
查看>>
IOS 7 Study - UISegmentedControl
查看>>
八、通用类型系统
查看>>
JQuery的ajaxFileUpload的使用
查看>>
关于Integer类中parseInt()和valueOf()方法的区别以及int和String类性的转换.以及String类valueOf()方法...
查看>>
ios 控制器的生命周期
查看>>
JavaScript 特殊效果代码
查看>>
【?】codeforces721E Road to Home(DP+单调队列)
查看>>
MySQL 仅保留7天、一个月数据
查看>>
Diff Two Arrays
查看>>
下拉菜单
查看>>
[清华集训2014]玛里苟斯
查看>>
【MVC+EasyUI实例】对数据网格的增删改查(上)
查看>>
Project Euler 345: Matrix Sum
查看>>
你可能不知道的技术细节:存储过程参数传递的影响
查看>>