Android Shimmer学习
2017-02-05 17:09
267 查看
Android Shimmer学习
Facebook在Android上实现了Shimmer的效果,如上图,可以针对所有的View,地址:http://facebook.github.io/shimmer-android/
我就学习一下该如何制作出类似的简易效果,现实的核心部分是使用线性渐变LinearGradient,然后在绘图的时候不断将渐变平移来达到效果。
LinearGradient
根据开发者文档,有两种构造方法:Public constructors
LinearGradient(float x0, float y0, float x1, float y1, int[] colors, float[] positions, Shader.TileMode tile)
LinearGradient(float x0, float y0, float x1, float y1, int color0, int color1, Shader.TileMode tile)
首先来看看几个共同的属性:
x0, y0 渐变线起点的x,y坐标
x1, y1 渐变线终点的x,y坐标
tile Shader.TileMode 平铺模式
前两个都很好理解,平铺模式又是什么呢?根据开发者文档,有三种平铺模式:
CLAMP 如果着色器渲染越过了原始的边界,复制边缘的颜色渲染
MIRROR 垂直和水平地重复着色器图片,交替复制的镜像图片以保证相邻的图片总是能够接上
REPEAT 垂直和水平地重复着色器图片
从上面的三行话中已经透露出了一个很关键的东西,渐变也是一个着色器,在来看开发者文档,也标明了这一点,这也是之后的平移过程的基础。
更多关于Shader着色器的知识可以参考博文:http://blog.csdn.net/iispring/article/details/50500106
再来看看两个构造函数不同的地方主要是颜色的决定,第一个函数使用的是一个数组并配上位置来决定颜色所在的位置,第二个函数则简单粗暴地多,设置起点和终点的位置即可。这里需要注意一点,对于第一个函数中的位置参数可以为null,如果设置为null的话,颜色会均匀分布在渐变线上。
现在一切准备就绪,所以根据效果,我们可以构造出一个LinearGradient
mLinearGradient = new LinearGradient(-mViewWidth, 0, 0, 0, new int[] { 0x33ffffff, 0xffffffff, 0x33ffffff }, new float[] { 0, 0.5f, 1 }, Shader.TileMode.CLAMP);
可以看出我们构建了一个和View一样长的渐变,而位置就在View的左侧紧贴着,我们接下来需要做的就是将这个渐变从左侧慢慢平移到右侧,这样就能达到闪动的效果。(需要自定义颜色的在此处修改)
那该如何平移这个渐变呢?需要使用到属性动画了
平移
可能很多人都已经学过了安卓中的动画,但这里着色器的平移有一些不同,它是使用矩阵来进行移动,通过查阅开发者文档,我们可以知道有这么一个函数 setLocalMatrix 可以用来设置着色器的矩阵。所以我们还需要一个矩阵来控制着色器的位置。(注意是使用android.graphics.Matrix)mGradientMatrix = new Matrix();
在本例中我是每次移动宽度的1/10,如果平移完了再回到左侧重新平移
mTranslate += mViewWidth / 10; if (mTranslate > 2 * mViewWidth) { mTranslate = 0; }
然后给矩形赋值然后将着色器平移
mGradientMatrix.setTranslate(mTranslate, 0); mLinearGradient.setLocalMatrix(mGradientMatrix); postInvalidateDelayed(50);
由于是个安卓新手,本着凡是不懂得就去查查文档,我在这里卡了很久,setTranslate 到底是怎样的运作方式,是控制平移量还是直接控制位置,经过实验后我发现该函数所做的操作都是在原位置上进行平移,左负右正,它做完平移后,不会改变原位置,虽然在视觉上现位置已经有了改变,所以我们需要在每一次都递增mTranslate变量。postInvalidateDelay里设置每一帧绘制的时间,也就是控制闪动的快慢。
综上
有了着色器应该如何使用上呢?这里就需要提到一个Paint类,它来决定如何绘制,习惯称为“画笔”,这个就很生动了,我们换了画笔,那画出来的东西就是我们想要的。mPaint.setShader(mLinearGradient);
因为我们是继承一个TextView来进行操作,之前也一直在用到View的宽度,这个我们应该在哪里获取?答案就是 onSizeChanged这个回调函数,我们在这里完成大部分的初始化功能。所以这个自定View代码如下:
public class MyTextView extends TextView {
private LinearGradient mLinearGradient;
private Matrix mGradientMatrix;
private Paint mPaint;
private int mViewWidth = 0;
private int mTranslate = 0;
private boolean mAnimating = true;
public MyTextView(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
if (mViewWidth == 0) {
mViewWidth = getMeasuredWidth();
if (mViewWidth > 0) {
mPaint = getPaint();
mLinearGradient = new LinearGradient(-mViewWidth, 0, 0, 0, new int[] { 0x33ffffff, 0xffffffff, 0x33ffffff }, new float[] { 0, 0.5f, 1 }, Shader.TileMode.CLAMP);mPaint.setShader(mLinearGradient);mGradientMatrix = new Matrix();}
}
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (mAnimating && mGradientMatrix != null) {
mTranslate += mViewWidth / 10;
if (mTranslate > 2 * mViewWidth) {
mTranslate = 0;
}
mGradientMatrix.setTranslate(mTranslate, 0);
mLinearGradient.setLocalMatrix(mGradientMatrix);
postInvalidateDelayed(80);
}
}
}
相关文章推荐
- 使用C++实现JNI接口需要注意的事项
- Android IPC进程间通讯机制
- Android Manifest 用法
- [转载]Activity中ConfigChanges属性的用法
- Android之获取手机上的图片和视频缩略图thumbnails
- Android之使用Http协议实现文件上传功能
- Android学习笔记(二九):嵌入浏览器
- android string.xml文件中的整型和string型代替
- i-jetty环境搭配与编译
- android之定时器AlarmManager
- android wifi 无线调试
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- android 代码实现控件之间的间距
- android FragmentPagerAdapter的“标准”配置
- Android"解决"onTouch和onClick的冲突问题
- android:installLocation简析
- android searchView的关闭事件