前两天在csdn手机端上看到貌似是有个app具有这个闪电的loading标志,非常感兴趣,正好目前正在学习自定义view,所以就想自己来实现一下,还好自己完成了,不是很难~
效果图:
由于是手机上截的图,所以没有弄成动态的,大家体谅一下哈。
下面是代码:
首先自定义view的属性,我先以属性的形式实现了,大家如果想做成loading的效果的话,可以自己去实现。。
```
<resources>
<declare-styleable name="LightView">
<attr name="light_color" format="color"></attr>
<attr name="bg_color" format="color"></attr>
<attr name="speed" format="integer"></attr>
<attr name="lightSize" format="dimension"></attr>
</declare-styleable>
</resources>
这里面我定义了light_color 首次闪电的绘制颜色,bg_color 第二次绘制闪电的颜色,后面如果绘制的话,其实就不分首次和下一次了,因为需要来回的转换,speed 绘制的速度,lightSize 闪电的高度
下面看具体实现代码:
public class LightView extends View {
private int mLightColor, mBgColor, mspeed, addSpeed = 1, mLightSize;
private Paint paint;
private int mWidth, mHeight, measureHeight;
private Path path;
private boolean flag = false;
private RectF rect;
public LightView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public LightView(Context context) {
this(context, null);
}
public LightView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.LightView, defStyleAttr, 0);
mLightColor = a.getColor(R.styleable.LightView_light_color, Color.YELLOW);
mBgColor = a.getColor(R.styleable.LightView_bg_color, Color.RED);
mspeed = a.getInt(R.styleable.LightView_speed, 1);
mLightSize = a.getDimensionPixelSize(R.styleable.LightView_lightSize, (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 17,
getResources().getDisplayMetrics()));
a.recycle();
paint = new Paint();
paint.setStyle(Paint.Style.FILL);
paint.setAntiAlias(true);
paint.setStrokeWidth(1);
paint.setColor(mLightColor);
rect = new RectF();
new Thread(new Runnable() {
@Override
public void run() {
while (true) {
//高度的增量
addSpeed += 10;
postInvalidate();
try {
Thread.sleep(mspeed);//绘制的速度
} catch (Exception e) {
e.printStackTrace();
}
}
}
}).start();
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
measureHeight = MeasureSpec.getSize(heightMeasureSpec);
if (heightMode == MeasureSpec.EXACTLY) {
mHeight = Math.min(measureHeight, mLightSize);
} else {
mHeight = mLightSize;
}
mWidth = 2 * mHeight / 3;//以高度来决定view的宽度,设置宽度永远为高度的三分之二。。我是觉得这样好看。。=。=
//使用path绘制闪电形状
path = new Path();
path.moveTo(mWidth * 2 / 3, 0);
path.lineTo(mWidth / 2, 4 * mHeight / 9);
path.lineTo(mWidth * 2 / 3, 4 * mHeight / 9);
path.lineTo(mWidth / 3, mHeight);
path.lineTo(mWidth / 2, 5 * mHeight / 9);
path.lineTo(mWidth / 3, 5 * mHeight / 9);
path.close();
setMeasuredDimension(mWidth, mHeight);
}
@Override
protected void onDraw(Canvas canvas) {
rect.top = 0;
rect.left = 0;
rect.right = mWidth;
rect.bottom = mHeight;
paint.setColor(Color.GREEN);
canvas.drawRoundRect(rect, mWidth / 2, mHeight / 2, paint);
//通过对切割画布的高度的判断,判断是否第二次的绘制已经完成,然后改变初次绘制的闪电的颜色
if (addSpeed >= mHeight) {
addSpeed = 0;
if (!flag) {
flag = true;
} else {
flag = false;
}
}
if (!flag) {
paint.setColor(mLightColor);
canvas.drawPath(path, paint);//绘制完全的闪电
paint.setColor(mBgColor);
canvas.clipRect(0, 0, mWidth, addSpeed);//通过切割画布,在重新绘制闪电,并不会对已经绘制过的图形产生影响
canvas.drawPath(path, paint);
} else {
paint.setColor(mBgColor);
canvas.drawPath(path, paint);
paint.setColor(mLightColor);
canvas.clipRect(0, 0, mWidth, addSpeed);
canvas.drawPath(path, paint);
}
}
}
其实这里面主要是对基础的path和clipRect的理解
找到一个介绍clipRect的不错的文章,摘过来
android的clip有以下两点疑问:
Clip(剪切)的时机
Clip中的Op的参数的意思。
通常咱们理解的clip(剪切),是对已经存在的图形进行clip的。但是,在android上是对canvas(画布)上进行clip的,要在画图之前对canvas进行clip,如果画图之后再对canvas进行clip不会影响到已经画好的图形。一定要记住clip是针对canvas而非图形。
接下来通过android自带的APIdemo Clipping例子详细讲述Clip中的Op的参数的意思。Android提供clipRect、clipPath和clipRegion剪切区域的API。
Op一共有 DIFFERENCE,INTERSECT,UNION,XOR, REVERSE_DIFFERENCE, REPLACE六种选择。
例子:
在canvas上剪切从(0,0)到(60,60)的方块。下图蓝色区域加紫色区域。
在canvas上剪切从(40,40)到(100,100)的方块。下图橄榄色区域加紫色区域。
在canvas上剪切从(0,0)到(100,100)的方块。
先在第二方块上加上Op参数例如:canvas.clipRect(40, 40, 100, 100, Region.Op. DIFFERENCE);
首先,需要搞清楚Op参数针对的对象。接着了解其含义。
Op参数针对的对象是之前剪切的区域以及当前要剪切的区域。
在本例中涉及到区域是从(0,0)到(60,60)的方块和从(40,40)到(100,100)的方块。
那有哪些含义呢?就是表示当前要剪切的区域与之前剪切过的之间的关系。
DIFFERENCE:之前剪切过除去当前要剪切的区域(蓝色区域)。
INTERSECT:当前要剪切的区域在之前剪切过内部的部分(紫色区域)。
UNION:当前要剪切的区域加上之前剪切过内部的部分(蓝色区域+紫色区域+橄榄色区域)。
XOR:异或,当前要剪切的区域与之前剪切过的进行异或。(蓝色区域+橄榄色区域)。
REVERSE_DIFFERENCE:与DIFFERENCE相反,以当前要剪切的区域为参照物,当前要剪切的区域除去之前剪切过的区域(橄榄色区域);
REPLACE:用当前要剪切的区域代替之前剪切过的区域。(橄榄色区域+紫色区域);
没带Op参数效果与INTERSECT的效果一样,两个区域的交集。
版权声明:本文为博主原创文章,未经博主允许不得转载。
原文地址:http://blog.csdn.net/u011625768/article/details/47342205