原本faceBook早就有类似强大效果。文中也是参考faceBook和网上资料,改编的轻量级工具。
效果如下:
使用及其简单:
EditText et = (EditText) findViewById(R.id.et);
ShimmerHelper helper2 = new ShimmerHelper(et, et.getPaint());
helper2.setDuration(3000);
helper2.setMode(Shader.TileMode.REPEAT);
helper2.setColors(Color.parseColor("#ff00ff"), Color.parseColor("#00ffff"));
helper2.start();
原理和实现:
在绘制view的时候,我们为了使其有渐变效果,一般就加一个shader。Shader的官方解释如下:
* Shader is the based class for objects that return horizontal spans of colors
* during drawing. A subclass of Shader is installed in a Paint calling
* paint.setShader(shader). After that any object (other than a bitmap) that is
* drawn with that paint will get its color(s) from the shader.
可以看到效果图中本就是一个水平方向上的颜色渐变,因此可以通过实时改变shader的覆盖区域来实现。
用代码实现非常简单,核心方法就一个:
public void start() {
mView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
init(mView);
ObjectAnimator animator = ObjectAnimator.ofFloat(mView, "n", 0f, 0.5f, 1f);
animator.setDuration(mDuration);
animator.setRepeatCount(mRepeatCount);
animator.addListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {
start();
}
@Override
public void onAnimationEnd(Animator animation) {
}
@Override
public void onAnimationCancel(Animator animation) {
}
@Override
public void onAnimationRepeat(Animator animation) {
start();
}
private void start() {
if (mAnimating && mGradientMatrix != null) {
//每次shader的变化长度为10个单位长度
mTranslate += mViewWidth / 10;
if (mTranslate > 2 * mViewWidth) {
// 移动了整个View的距离后 回到原位
mTranslate = -mViewWidth;
}
//shader的移动其实是其对应的矩阵的变化
mGradientMatrix.setTranslate(mTranslate, 0);
//将实时变化的矩阵作用到shader上
mLinearGradient.setLocalMatrix(mGradientMatrix);
}
mView.postInvalidate();
}
});
animator.start();
}
});
}
private void init(View v) {
if (mViewWidth == 0) {
mViewWidth = v.getMeasuredWidth();
if (mViewWidth > 0) {
//LinearGradient继承至Shader
mLinearGradient = new LinearGradient(-mViewWidth, 0, 0, 0,
mColors,
new float[]{0, 0.5f, 1}, mMode);
//将shader作用到目标view的画笔上
mPaint.setShader(mLinearGradient);
mGradientMatrix = new Matrix();
}
}
}
这里有几点需要注意:
1、 闪动过程需要获取目标view的宽度,而一般 我们会在onCreate或者onResume里面去进行方法start()的调用。为了能正常获取到view的真实宽度,需要在onGlobalLayout里面进行获取,这也是为什么一开始需要getViewTreeObserver().addOnGlobalLayoutListener的原因
2 、在onGlobalLayout里面有一个属性动画 ObjectAnimator animator = ObjectAnimator.ofFloat(mView, “n”, 0f, 0.5f, 1f);
这里的属性“n”是一个虚属性(就是不存在的意思)。我们设置这个属性动画的目的并不是为了真正改变view的某个属性,我们只是想在动画的周期函数里面自行改变shader的覆盖长度而已。
局限性:
只能使用在能获取画笔的目标view上(view.getPaint()),例如TextView,Button,EditText等。
代码下载:
https://github.com/killer8000/ShimmerHelper/