运维开发网

通过Android自定义视图实现抓取效果的详细介绍

运维开发网 https://www.qedev.com 2022-04-26 14:52 出处:网络
这篇文章主要介绍了如何在Android中利用自定义的view实现刮刮乐的效果,文中的示例代码讲解详细,感兴趣的小伙伴可以跟上小编一起动手试一试

这篇文章主要介绍了如何在Android中利用自定义的view实现刮刮乐的效果,文中的示例代码讲解详细,感兴趣的小伙伴可以跟上小编一起动手试一试


前言

我已经两个月没更新博客了。其实这篇文章我早在两个月前就写好了,一直放在草稿箱里没有发表。原因是有些原理还没搞清楚。最近花时间研究混音模式,终于明白scratch music是怎么实现的了,所以想继续分享一些自己的经验,先把效果图放上去。

效果图:



实现原理

其实scratch music的实现原理并不是很复杂,最重要的是要知道Paint的混合模式。因为scratch music由两个位图组成,一个是源图像,一个是目标图像,我们需要将目标图像的颜色改为灰色,并用一个灰色的目标图像覆盖源图像。当手指滑动屏幕时,Paint将在新画布上绘制一条路径。由于新的画布将容纳新的位图,当两个位图的像素重叠时,将显示源图像的部分,从而达到刮音乐的效果。波特达夫。这里用的是混合模式的DST_IN。


关键代码:

pathPaint.setXfermode(new PorterDuffXfermode((PorterDuff.Mode.DST_IN)));


关键步骤


创建bitmap @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); mBitmapBackground = getBitmap(mBitmapBackground, w, h); mBitmapFront = Bitmap.createBitmap(mBitmapBackground.getWidth(), mBitmapBackground.getHeight(), Bitmap.Config.ARGB_8888); mCanvas.setBitmap(mBitmapFront); drawText(mCanvas, w, h); }

在onSizeChanged方法中创建了两个位图,一个是背景图像,另一个是覆盖在背景图像上的位图。然后在上面的位图上画出文字。


绘制文字 private void drawText(Canvas canvas, int mWidth, int mHeight) { String text = "赶紧刮开吧"; canvas.drawColor(Color.GRAY); Paint.FontMetrics fm = mPaintText.getFontMetrics(); int mTxtWidth = (int) mPaintText.measureText(text, 0, text.length()); int mTxtHeight = (int) Math.ceil(fm.descent - fm.ascent); int x = mWidth / 2 - mTxtWidth / 2; //文字在画布中的x坐标 int y = mHeight / 2 + mTxtHeight / 4; //文字在画布中的y坐标 canvas.drawText(text, x, y, mPaintText); }


调用canvas的drawText方法绘制文本,其中x和y是文本中心的坐标。测量单词的宽度和高度有两种方法。这里使用了更精确的getFontMetrics方法。


画路径 @Override public boolean onTouchEvent(MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: path.reset(); path.moveTo(event.getX(), event.getY());//原点移动至手指的触摸点 break; case MotionEvent.ACTION_MOVE: path.lineTo(event.getX(), event.getY()); break; } mCanvas.drawPath(path, pathPaint); invalidate(); return true; }

最终效果图



完整代码import android.content.Context;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Matrix;import android.graphics.Paint;import android.graphics.Path;import android.graphics.PorterDuff;import android.graphics.PorterDuffXfermode;import android.util.AttributeSet;import android.view.MotionEvent;import android.view.View; import androidx.annotation.Nullable; import com.example.androidprogressbar.R; public class ScratchCard extends View { private Bitmap mBitmapBackground; private Bitmap mBitmapFront; private Canvas mCanvas; private Paint pathPaint; private Path path; private Paint mPaintText; public ScratchCard(Context context) { super(context); init(); } public ScratchCard(Context context, @Nullable AttributeSet attrs) { super(context, attrs); init(); } public ScratchCard(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(); } private void init() { pathPaint = new Paint(); pathPaint.setAlpha(0); pathPaint.setStyle(Paint.Style.STROKE); pathPaint.setStrokeWidth(70); pathPaint.setXfermode(new PorterDuffXfermode((PorterDuff.Mode.DST_IN)));//混合模式 pathPaint.setStrokeJoin(Paint.Join.ROUND);//线段之间连接处的样式 pathPaint.setStrokeCap(Paint.Cap.ROUND);//设置画笔的线冒样式 path = new Path(); mBitmapBackground = BitmapFactory.decodeResource(getResources(), R.drawable.card); mCanvas = new Canvas(); mPaintText = new Paint(); mPaintText.setColor(Color.WHITE); mPaintText.setTextSize(100); mPaintText.setStrokeWidth(20); } @Override protected void onDraw(Canvas canvas) { canvas.drawBitmap(mBitmapBackground, 0, 0, null); canvas.drawBitmap(mBitmapFront, 0, 0, null); } @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); mBitmapBackground = getBitmap(mBitmapBackground, w, h); mBitmapFront = Bitmap.createBitmap(mBitmapBackground.getWidth(), mBitmapBackground.getHeight(), Bitmap.Config.ARGB_8888); mCanvas.setBitmap(mBitmapFront); drawText(mCanvas, w, h); } @Override public boolean onTouchEvent(MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: path.reset(); path.moveTo(event.getX(), event.getY());//原点移动至手指的触摸点 break; case MotionEvent.ACTION_MOVE: path.lineTo(event.getX(), event.getY()); break; } mCanvas.drawPath(path, pathPaint); invalidate(); return true; } private void drawText(Canvas canvas, int mWidth, int mHeight) { String text = "赶紧刮开吧"; canvas.drawColor(Color.GRAY); Paint.FontMetrics fm = mPaintText.getFontMetrics(); int mTxtWidth = (int) mPaintText.measureText(text, 0, text.length()); int mTxtHeight = (int) Math.ceil(fm.descent - fm.ascent); int x = mWidth / 2 - mTxtWidth / 2; //文字在画布中的x坐标 int y = mHeight / 2 + mTxtHeight / 4; //文字在画布中的y坐标 canvas.drawText(text, x, y, mPaintText); } public Bitmap getBitmap(Bitmap bm, int newWidth, int newHeight) { // 获得图片的宽高 int width = bm.getWidth(); int height = bm.getHeight(); // 计算缩放比例 float scaleWidth = ((float) newWidth) / width; float scaleHeight = ((float) newHeight) / height; // 取得想要缩放的matrix参数 Matrix matrix = new Matrix(); matrix.postScale(scaleWidth, scaleHeight); // 得到新的图片 Bitmap newbm = Bitmap.createBitmap(bm, 0, 0, width, height, matrix, true); return newbm; } }

以上是Android通过自定义视图实现抓取效果的详细内容。

0

精彩评论

暂无评论...
验证码 换一张
取 消