昨天写了一篇关于支付宝咻一咻的功能,但是一直想通过使用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,基本实现了