Android PorterDuff.Mode.DST_OUT 刮彩票
我在学习 PorterDuff.Mode
实现图片混排模式的时候发现有一个很好玩,那就是 PorterDuff.Mode.DST_OUT
它会把两者相交的地方擦去,这这不就有点像刮彩票一样么?
Android 提供的 18 种图片混排模式
Android PorterDuff.Mode.DST_OUT 刮彩票 实现步骤
先说说原理,就是两个 Bitmap,一前一后,前面的是一层涂层,后面的是中奖信息
然后通过一个 Path 来记录用户绘制出来的图形,然后为我们的画笔设置 DST_OUT 的模式,那么 与 Path 重叠部分的 DST(目标图),也就是涂层,会变成透明
-
首先我们需要两个 Bitmap,用来存储涂层和中奖信息
-
接着设置下画笔,圆角,笔宽,抗锯齿等
-
定义一个 Path,即用户绘制区域的方法,设置 Xfermode 后画区域
-
重写
onTouchEvent()
-
重写
onDraw()
方法,先绘制背景图片,调用用户绘制区域的方法,再绘制前景图片
范例
-
创建一个 空的 Android 项目
cn.twle.android.Lottery
-
定义一个自定义 View LotteryView.java
package cn.twle.android.lottery; import android.annotation.SuppressLint; import android.content.Context; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.Path; import android.graphics.PorterDuff; import android.graphics.PorterDuffXfermode; import android.graphics.Xfermode; import android.util.AttributeSet; import android.util.DisplayMetrics; import android.view.MotionEvent; import android.view.View; import android.view.WindowManager; public class LotteryView extends View { private Paint mPaint = new Paint(); private Path mPath = new Path(); private Canvas mCanvas; private Bitmap mBeforeBitmap; private Bitmap mBackBitmap; private int mLastX,mLastY; private int width,height=200,top = 0; private Xfermode mXfermode = new PorterDuffXfermode(PorterDuff.Mode.DST_OUT); public LotteryView(Context context) { this(context, null); } public LotteryView(Context context, AttributeSet attrs) { super(context, attrs); WindowManager wm = (WindowManager) context. getSystemService(Context.WINDOW_SERVICE); DisplayMetrics dm = new DisplayMetrics(); wm.getDefaultDisplay().getMetrics(dm); width = dm.widthPixels; top = (dm.heightPixels-280) / 2; init(); } public LotteryView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } private void init() { mBackBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); Canvas c = new Canvas(mBackBitmap); Paint p = new Paint(Paint.ANTI_ALIAS_FLAG); c.drawColor(0xFFDDDDDD); p.setColor(0xFF000000); p.setTextSize(48.0f); p.setTextAlign(Paint.Align.CENTER); Paint.FontMetrics fontMetrics = p.getFontMetrics(); float tp = fontMetrics.top; // 为基线到字体上边框的距离 float tb = fontMetrics.bottom; // 为基线到字体下边框的距离 int cY = (int) (height/2 - tp/2 - tb/2);//基线中间点的y轴计算公式 c.drawText("简单教程,简单编程",width/2,cY,p); mBeforeBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); mCanvas = new Canvas(mBeforeBitmap); p.setColor(0xFF666666); mCanvas.drawRect(0,0,width,height,p); //画笔相关的设置 mPaint.setAntiAlias(true); mPaint.setDither(true); mPaint.setStyle(Paint.Style.STROKE); mPaint.setStrokeJoin(Paint.Join.ROUND); // 圆角 mPaint.setStrokeCap(Paint.Cap.ROUND); // 圆角 mPaint.setStrokeWidth(80); // 设置画笔宽 } private void drawPath() { mPaint.setXfermode(mXfermode); mCanvas.drawPath(mPath, mPaint); } @Override protected void onDraw(Canvas canvas) { canvas.drawBitmap(mBackBitmap, 0, top, null); drawPath(); canvas.drawBitmap(mBeforeBitmap, 0, top, null); } @SuppressLint("ClickableViewAccessibility") @Override public boolean onTouchEvent(MotionEvent event) { int action = event.getAction(); int x = (int) event.getX(); int y = (int) event.getY() - top; 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; } invalidate(); return true; } }
-
修改 activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <cn.twle.android.lottery.LotteryView android:layout_width="match_parent" android:layout_height="match_parent"/> </RelativeLayout>