概述:
开发过程中,看到有些界面用到一道光线在屏幕中掠过的效果,觉得挺炫的。所以查找相关资料自己实现了一遍。
先上个预览图:
实现思路:
简单来说就是在一个view中绘制好一道光影,并不断改变光影在view中的位置。
1.首先我们先了解一下光影怎么绘制
在了解如何绘制之前,我们先看一下LinearGradient的构造方法
LinearGradient(float x0, float y0, float x1, float y1, @NonNull @ColorInt int[] colors,
@Nullable float[] positions, @NonNull TileMode tile)
colors[]和positions[]的说明结合下图,这样理解起来应该就比较明朗了
回到正题,如何绘制光影。我们看到的那道光可以参照下图:
根据分析得到我们的着色器是线性着色器(其他着色器请查询相关api):
LinearGradient(a的x坐标, a的y坐标, c的x坐标, c的y坐标, new int[]{Color.parseColor("#00FFFFFF"), Color.parseColor("#FFFFFFFF"), Color.parseColor("#00FFFFFF")}, new float[]{0f, 0.5f, 1f}, Shader.TileMode.CLAMP)
2.给画笔上色。设置着色器mPaint.setShader(mLinearGradient)
3.给定一个数值范围利用数值生成器ValueAnimator产生数值,监听数值变化。每次回调都将该数值传入光影的起点和终点并进行绘制
代码如下:
public class ConfigLoadingView extends View {
private Paint mPaint;
private Path mPath;
private LinearGradient mLinearGradient;
private ValueAnimator mValueAnimator;
public ConfigLoadingView(Context context) {
this(context, null);
}
public ConfigLoadingView(Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}
public ConfigLoadingView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init() {
mPaint = new Paint();
mPath = new Path();
}
private void initPointAndAnimator(int w, int h) {
Point point1 = new Point(0, 0);
Point point2 = new Point(w, 0);
Point point3 = new Point(w, h);
Point point4 = new Point(0, h);
mPath.moveTo(point1.x, point1.y);
mPath.lineTo(point2.x, point2.y);
mPath.lineTo(point3.x, point3.y);
mPath.lineTo(point4.x, point4.y);
mPath.close();
// 斜率k
float k = 1f * h / w;
// 偏移
float offset = 1f * w / 2;
// 0f - offset * 2 为数值左边界(屏幕外左侧), w + offset * 2为数值右边界(屏幕外右侧)
// 目的是使光影走完一遍,加一些时间缓冲,不至于每次光影移动的间隔都那么急促
mValueAnimator = ValueAnimator.ofFloat(0f - offset * 2, w + offset * 2);
mValueAnimator.setRepeatCount(-1);
mValueAnimator.setInterpolator(new LinearInterpolator());
mValueAnimator.setDuration(1500);
mValueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
float value = (float) animation.getAnimatedValue();
mLinearGradient = new LinearGradient(value, k * value, value + offset, k * (value + offset),
new int[]{Color.parseColor("#00FFFFFF"), Color.parseColor("#1AFFFFFF"), Color.parseColor("#00FFFFFF")}, null, Shader.TileMode.CLAMP);
mPaint.setShader(mLinearGradient);
invalidate();
}
});
mValueAnimator.start();
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
initPointAndAnimator(widthSize, heightSize);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawPath(mPath, mPaint);
}
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
mValueAnimator.cancel();
}
}
注意点:
LinearGradient里参数之一:
color[]参数只能是16进制的RGB数值,不能传R.color.xxx。R.color.xxx虽然是int型,但拿到的是资源ID,并不是16进制RGB
到此这篇关于Android实现流光和光影移动效果代码的文章就介绍到这了,更多相关Android 流光和光影移动效果内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!