昨天写了一篇关于支付宝咻一咻的功能,但是一直想通过使用Canvas来实现它,之前有的地方没想通,今天突然想通了,今天就自定义继承view而不是继承ViewGroup或者容器view来实现,但是也有个缺点,就是点击区域问题,先一步步来实现它,
第一步:画图片
上面画的是drawBitmap的时候离左边和上边的值,思路通过图应该实现起来不难,代码如下:
package com.alipay_xiuyixiu.view;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.View;
import com.alipay_xiuyixiu.R;
/**
* 仿支付宝咻一咻功能
* Created by admin on 2016/12/30.
*/
public class AlipayView extends View {
private int bpWidth;//图片的宽度
private int bpHeight;//图片的高度
private int width;//view的宽度
private int height;//view的高度
private Paint paint;
private Bitmap bitmap;
public AlipayView(Context context) {
this(context,null);
}
public AlipayView(Context context, AttributeSet attrs) {
this(context, attrs,0);
}
public AlipayView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initPaint();
initBitmap();
}
private void initBitmap() {
bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.icon);
bpWidth = bitmap.getWidth();
bpHeight = bitmap.getHeight();
}
private void initPaint() {
paint = new Paint();
paint.setAntiAlias(true);
paint.setStrokeWidth(2);
paint.setStyle(Paint.Style.FILL);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
width = getMeasuredWidth();
height = getMeasuredHeight();
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawBitmap(bitmap,width/2-bpWidth/2,height/2-bpHeight/2,null);
}
}
效果图:
第一步实现出来了,那么第二步就是画圆,先绘制一个圆,要想达到水波纹的效果,哪就要让圆的半径是不断变化的过程,
第二步:绘制单个半径不断变化的圆,使用handler间隔多少时间去更新UI即可
package com.alipay_xiuyixiu.view;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.os.Handler;
import android.util.AttributeSet;
import android.view.View;
import com.alipay_xiuyixiu.R;
/**
* 仿支付宝咻一咻功能
* Created by admin on 2016/12/30.
*/
public class AlipayView extends View {
private int bpWidth;//图片的宽度
private int bpHeight;//图片的高度
private int width;//view的宽度
private int height;//view的高度
private Paint paint;
private Bitmap bitmap;
private int raduis;//圆的半径
private Handler mHandler = new Handler();
public AlipayView(Context context) {
this(context,null);
}
public AlipayView(Context context, AttributeSet attrs) {
this(context, attrs,0);
}
public AlipayView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initPaint();
initBitmap();
}
private void initBitmap() {
bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.icon);
bpWidth = bitmap.getWidth();
bpHeight = bitmap.getHeight();
}
private void initPaint() {
paint = new Paint();
paint.setAntiAlias(true);
paint.setStyle(Paint.Style.FILL);
paint.setColor(Color.parseColor("#0099CC"));
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
width = getMeasuredWidth();
height = getMeasuredHeight();
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawCircle(width/2,height/2,raduis,paint);
canvas.drawBitmap(bitmap,width/2-bpWidth/2,height/2-bpHeight/2,null);//千万要注意这个bitmap要绘制在圆的后面 不然会被圆盖住
}
/**
* 开始水波纹效果
*/
public void startRipper(){
mHandler.post(runnable);
}
private Runnable runnable = new Runnable() {
@Override
public void run() {
if(raduis>=width/2-20){
raduis=Math.min(bpWidth,bpHeight)/2;
}else{
raduis+=3;
}
postInvalidate();
mHandler.postDelayed(runnable,20);
}
};
}
效果:
这是第二步实现的效果,离我们想要的目标就是要同时是多个圆的半径不断的发生变化,
第三步:绘制多个半径不断变化的圆
思路:
a:记录当前的时间然后每隔多少毫秒添加一个半径到集合中,然后重新记录当前的时间
b:加入半径后就对半径进行不断的变化
c:判断集合中存储的半径的值是否大于我们预先规定的值,大于了就移除
根据上面三点进行编码:
package com.alipay_xiuyixiu.view;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.os.Handler;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import com.alipay_xiuyixiu.R;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
/**
* 仿支付宝咻一咻功能
* Created by admin on 2016/12/30.
*/
public class AlipayView extends View {
private int bpWidth;//图片的宽度
private int bpHeight;//图片的高度
private int width;//view的宽度
private int height;//view的高度
private Paint paint;
private Bitmap bitmap;
private int raduis;//圆的半径
private Handler mHandler = new Handler();
private List<Integer> raduisList = Collections.synchronizedList(new ArrayList<Integer>());//存储半径的集合
private long intervalTime = 300;//间隔的时间
private long currentTime = System.currentTimeMillis();//系统当前的时间
public AlipayView(Context context) {
this(context,null);
}
public AlipayView(Context context, AttributeSet attrs) {
this(context, attrs,0);
}
public AlipayView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initPaint();
initBitmap();
}
private void initBitmap() {
bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.icon);
bpWidth = bitmap.getWidth();
bpHeight = bitmap.getHeight();
raduis = Math.min(bpWidth,bpHeight)/2;
raduisList.add(raduis);
}
private void initPaint() {
paint = new Paint();
paint.setAntiAlias(true);
paint.setStyle(Paint.Style.STROKE);
paint.setColor(Color.parseColor("#0099CC"));
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
width = getMeasuredWidth();
height = getMeasuredHeight();
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
for(int i=0;i<raduisList.size();i++){
canvas.drawCircle(width/2,height/2,raduisList.get(i),paint);
}
canvas.drawBitmap(bitmap,width/2-bpWidth/2,height/2-bpHeight/2,null);//千万要注意这个bitmap要绘制在圆的后面 不然会被圆盖住
}
/**
* 开始水波纹效果
*/
public void startRipper(){
mHandler.post(runnable);
}
private Runnable runnable = new Runnable() {
@Override
public void run() {
postInvalidate();
if(System.currentTimeMillis()-currentTime>intervalTime){
raduisList.add(Math.min(bpWidth,bpHeight)/2);
currentTime = System.currentTimeMillis();
}
for(int i=0;i<raduisList.size();i++){//改变每个半径的值
raduisList.set(i,raduisList.get(i)+3);
}
//判断半径是否超过预先设定的值
Iterator<Integer> iterator = raduisList.iterator();//使用这个迭代防止出现并发修改的异常
while (iterator.hasNext()) {
Integer r = iterator.next();
if(r>=(width/2-20)){
iterator.remove();
}
}
mHandler.postDelayed(runnable,20);
}
};
}
我把paint的设置成了paint.setStyle(Paint.Style.STROKE);这样能更好的观察是否有个半径不断的在变化,效果:
生成了4个圆,这生成多少个圆,在于你每隔多少时间加入半径决定的,现在改变下画笔的style:
paint.setStyle(Paint.Style.FILL);
效果:
总感觉有bug,先把第四步实现,有bug再改,
第四步:就是圆的半径大到一定程度会有个颜色的变化,其实就是设置paint的setColor()而已
颜色变化分析图:
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
for(int i=0;i<raduisList.size();i++){
int r = raduisList.get(i);
int alpha = 255-255*(r-bpWidth/2)/(width/2-bpWidth/2);
paint.setAlpha(alpha);
canvas.drawCircle(width/2,height/2,r,paint);
}
canvas.drawBitmap(bitmap,width/2-bpWidth/2,height/2-bpHeight/2,null);//千万要注意这个bitmap要绘制在圆的后面 不然会被圆盖住
}
上面是根据半径的变化设置paint的颜色不断的进行变化,
效果:
ok,基本实现了