前言
在Android绘图操作中,我贴出很多和绘图有关的博客,包括了绘制基本图形,以及绘制模式、Matrix、Shader。不能吸收了前人的经验而不实践,所以下面一段时间,我会使用里面的方法写几个自定义的demo。本篇博客将会在TextView的基础上实现一个刮刮卡的效果。
具体实现
首先我们先看看效果图。
可以看到,类似于平常我们抽奖的那种效果,具体实现方法是,在TextView的基础上绘制了一个覆盖层,然后处理TextView的onTouchEvent方法,当手指落下的时候记录起点,然后在手指移动的时候将移动的点加入到路径中,然后调用invalidate()方法使视图重绘,在onDraw方法中,先使用默认的super.onDraw(canvas);方法去绘制正常的TextView,然后在下面使用如下代码区绘制覆盖层。具体代码的作用注释已经标出了。
@Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); //如果没有覆盖层则不绘制覆盖层 if(!mIsCover) return; //存储当前画布图层 canvas.saveLayer(0, 0, this.getMeasuredWidth(), getMeasuredHeight(),null, Canvas.ALL_SAVE_FLAG); //绘制覆盖色 canvas.drawColor(mCoverColor); //使用绘制模式为Mode.DST_OUT mPaint.setXfermode(Xmode); //绘制路径,由于绘制模式,路径会擦除覆盖层的一部分 canvas.drawPath(mPath, mPaint); canvas.restore(); }
由于本例子很简单,就不在详细说明了,下面贴出全部代码,其实重点代码就是上面的一点,也只是基本绘图操作而已。
package comjay.guaguaka; import android.content.Context; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.Path; import android.graphics.PorterDuff.Mode; import android.graphics.PorterDuffXfermode; import android.util.AttributeSet; import android.view.MotionEvent; import android.widget.TextView; public class GuaGuaKa extends TextView { /** * 绘制覆盖层的画笔 */ private Paint mPaint; /** * 覆盖层被涂抹的路径 */ private Path mPath; /** * 合成模式 */ private PorterDuffXfermode Xmode; /** * 覆盖层的颜色 */ private int mCoverColor = 0xffcbcbcb; /** * 是否覆盖,默认有覆盖层 */ private boolean mIsCover = true; public GuaGuaKa(Context context) { this(context, null); } public GuaGuaKa(Context context, AttributeSet attrs) { this(context, attrs, 0); } public GuaGuaKa(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); mPaint = new Paint(); mPath = new Path(); Xmode = new PorterDuffXfermode(Mode.DST_OUT); mPaint.setAntiAlias(true); mPaint.setDither(true); mPaint.setStrokeWidth(25); mPaint.setStyle(Paint.Style.STROKE); mPaint.setStrokeCap(Paint.Cap.ROUND); mPaint.setStrokeJoin(Paint.Join.ROUND); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); // 如果没有覆盖层则不绘制覆盖层 if (!mIsCover) return; // 存储当前画布图层 canvas.saveLayer(0, 0, this.getMeasuredWidth(), getMeasuredHeight(), null, Canvas.ALL_SAVE_FLAG); // 绘制覆盖色 canvas.drawColor(mCoverColor); // 使用绘制模式为Mode.DST_OUT mPaint.setXfermode(Xmode); // 绘制路径,由于绘制模式,路径会擦除覆盖层的一部分 canvas.drawPath(mPath, mPaint); canvas.restore(); } @Override public boolean onTouchEvent(MotionEvent event) { float x = event.getX(); float y = event.getY(); switch (event.getAction()) { case MotionEvent.ACTION_DOWN: mPath.moveTo(x, y); break; case MotionEvent.ACTION_MOVE: mPath.lineTo(x, y); break; case MotionEvent.ACTION_UP: break; } this.invalidate(); return true; } /** * 设置覆盖层颜色 * * @param newColor */ public void setCoverColor(int newColor) { mCoverColor = newColor; invalidate(); } /** * 设置是否显示覆盖层 * * @param show */ public void showCover(boolean show) { mIsCover = show; invalidate(); } }
可以看到代码并不长,只是用到了一点绘图而已,可以看到,效果还是和不错的。