在我们的生活和学习中一定遇到过很多类似的效果,比如当我们购物时,商家为了促销,有时会采用刮奖的方式来求得大家的关注,随着移动互联网的高速发展,越来越多的电商走进了我们的视线,那么传统的刮刮卡效果如何在手机上实现呢?本篇我将为大家介绍一下这个实现的方式和方案。
对于这个效果的实现需要用到绘图的知识,大家如果对这部分知识存在困难,建议大家首先去准备一下这方面的知识,这样可以更好的方便你对本效果的认识。ok,开始我们本篇的内容介绍:
对于刮刮卡效果的实现,我们需要使用paint.setXfermode()来控制我们的图层显示,对于setXfermode()的16中效果,请结合下图进行掌握。
在进行具体操作之前先为大家介绍一下关于圆角图片的设计方式:1、我们绘制我们的矩形(正方形)图片;2、setXferMode(srcIn);;3、绘制我们的圆形。三步就可以完成我们的效果了。我们的刮刮卡效果就是这个原理,下面我们一起来学习一下吧。
第一步我们先实现一个画板的效果,为我们接下来的设计打一下基础,这里我们在布局文件中需要使用自定义View,所以我们的自定义View代码:
public class guagua extends View{ //定义变量 private Paint mOutterPath;//画笔对象 private Path mPath;//记录用户手指的绘制过程 private Canvas mCanvas;//画布 private Bitmap mBitmap;//图片 //记录用户绘制时的坐标值 private int mLastX = 0; private int mLastY = 0; public guagua(Context context) { this(context, null); } public guagua(Context context, AttributeSet attrs) { this(context, null, 0); } public guagua(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); //初始化变量 init(); } /** * 进行初始化操作 */ private void init() { mOutterPath = new Paint();//画笔对象 mPath = new Path();//绘制过程 } /** * 得到控件的宽和高 */ @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); int width = getMeasuredWidth(); int height = getMeasuredHeight(); //初始化我们的Bitmap(画布)对象 mBitmap = Bitmap.createBitmap(width, height, Config.ARGB_8888); mCanvas = new Canvas(mBitmap); //初始化我们的画笔属性 this.myOutterPath(); } /** * 初始化我们的画笔属性 */ protected void myOutterPath() { mOutterPath.setColor(Color.BLUE);//设置画笔的颜色 mOutterPath.setAntiAlias(true);//设置锯齿 mOutterPath.setDither(true); mOutterPath.setStrokeJoin(Paint.Join.ROUND);//圆角 mOutterPath.setStrokeCap(Paint.Cap.ROUND); mOutterPath.setStyle(Style.STROKE); mOutterPath.setStrokeWidth(10);//线条的宽带 } /** * 用户操作事件的监控 */ @Override public boolean onTouchEvent(MotionEvent event) { int action = event.getAction(); int x = (int) event.getX(); int y = (int) event.getY(); switch (action) { case MotionEvent.ACTION_DOWN://按下事件 mLastX = x; mLastY = y; mPath.moveTo(mLastX, mLastY); break; case MotionEvent.ACTION_MOVE://离开事件 //判断用户绘制的是否达到一定的值 int dx = Math.abs(x - mLastX); int dy = Math.abs(y - mLastY); if(dx>3||dy>3){ mPath.lineTo(x, y); } mLastX = x; mLastY = y; break; case MotionEvent.ACTION_UP://抬起事件 break; default: break; } invalidate(); return true; } @Override protected void onDraw(Canvas canvas) { drawPath(); canvas.drawBitmap(mBitmap, 0, 0, null); } private void drawPath() { mCanvas.drawPath(mPath, mOutterPath); } }
第二步我们需要在Layout文件中进行引用:
<cn.edu.hpu.guaguaka.guagua android:layout_below="@id/text" android:layout_width="fill_parent" android:layout_height="fill_parent" />
到这里我们的画板效果就实现的了,下面我们来进一步改进我们的自定义View来向我们的最终效果靠近,接下来我们实现一个类似于之前很火的小游戏:脱美女的效果。我们需要准备一张图片作为我们的美女。代码如下:
public class guagua extends View{ //定义变量 private Paint mOutterPath;//画笔对象 private Path mPath;//记录用户手指的绘制过程 private Canvas mCanvas;//画布 private Bitmap mBitmap;//图片 //记录用户绘制时的坐标值 private int mLastX = 0; private int mLastY = 0; //----------------------------------- private Bitmap bitmap; public guagua(Context context) { this(context, null); } public guagua(Context context, AttributeSet attrs) { this(context, null, 0); } public guagua(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); //初始化变量 init(); } /** * 进行初始化操作 */ private void init() { mOutterPath = new Paint(); mPath = new Path(); //加载底层图片 bitmap = BitmapFactory.decodeResource(getResources(), com.example.guaguaka.R.drawable.girl); } /** * 得到控件的宽和高 */ @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); int width = getMeasuredWidth(); int height = getMeasuredHeight(); //初始化我们的Bitmap(画布)对象 mBitmap = Bitmap.createBitmap(width, height, Config.ARGB_8888); mCanvas = new Canvas(mBitmap); //初始化我们的画笔属性 this.myOutterPath(); //设置覆盖色 mCanvas.drawColor(Color.parseColor("#C0C0C0")); //mCanvas.drawColor(Color.BLACK); } /** * 初始化我们的画笔属性 */ protected void myOutterPath() { mOutterPath.setColor(Color.RED);//设置画笔的颜色 mOutterPath.setAntiAlias(true);//设置锯齿 mOutterPath.setDither(true); mOutterPath.setStrokeJoin(Paint.Join.ROUND);//圆角 mOutterPath.setStrokeCap(Paint.Cap.ROUND); mOutterPath.setStyle(Style.STROKE); mOutterPath.setStrokeWidth(20);//线条的宽带 } /** * 用户操作事件的监控 */ @Override public boolean onTouchEvent(MotionEvent event) { int action = event.getAction(); int x = (int) event.getX(); int y = (int) event.getY(); switch (action) { case MotionEvent.ACTION_DOWN://按下事件 mLastX = x; mLastY = y; mPath.moveTo(mLastX, mLastY); break; case MotionEvent.ACTION_MOVE://离开事件 //判断用户绘制的是否达到一定的值 int dx = Math.abs(x - mLastX); int dy = Math.abs(y - mLastY); if(dx>3||dy>3){ mPath.lineTo(x, y); } mLastX = x; mLastY = y; break; case MotionEvent.ACTION_UP://抬起事件 break; default: break; } invalidate(); return true; } @Override protected void onDraw(Canvas canvas) { canvas.drawBitmap(bitmap, 0, 0, null); drawPath(); canvas.drawBitmap(mBitmap, 0, 0, null); } private void drawPath() { mOutterPath.setXfermode(new PorterDuffXfermode(android.graphics.PorterDuff.Mode.DST_OUT)); mCanvas.drawPath(mPath, mOutterPath); } }
需要修改的地方已经为大家进行标注,很清晰,相信大家都可以理解。对于刮刮卡的具体实现,我将在随后的介绍中带领大家一点一点的实现。