PorterDuff其实来自两个人名:Tomas Porter和Tom Duff。利用PorterDuff.Mode,我们可以实现图片的任意叠加混合。
先画圆,在画矩形,代码中间设置Xfermode。圆在下,矩形在上。SrcOver
是默认状态
部分重叠
因为准备画“部分重叠”状态,所以用Clear
和DstOut
都可以,因为矩形即使不重叠的部分也会消失,因为Clean
全重叠时会全部消失,所以选择DstOut。
刮刮卡代码
package com.noahedu.currentactivity;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
public class GuaGuaCard extends View implements View.OnTouchListener {
private Paint mPaint;
private Rect mRect;
//把画的所有点都存起来
private Path mPath;
private PorterDuffXfermode mPorterDuffXfermode;
public GuaGuaCard(Context context) {
this(context, null);
}
public GuaGuaCard(Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}
public GuaGuaCard(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init() {
setOnTouchListener(this);
//关闭硬件加速(遇到显示异常,比如全黑全白时设置)
setLayerType(LAYER_TYPE_SOFTWARE, null);
mPorterDuffXfermode = new PorterDuffXfermode(PorterDuff.Mode.DST_OUT);
mRect = new Rect();
mPath = new Path();
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeWidth(dp2px(20));
mPaint.setColor(Color.RED);
}
private float dp2px(int dp) {
float density = getContext().getResources().getDisplayMetrics().density;
int px = (int) (dp * density + 0.5f);
return px;
}
private static final String TAG = "GuaGuaCard";
private float startX;
private float startY;
private float endX;
private float endY;
@Override
public boolean onTouch(View v, MotionEvent event) {
int action = event.getAction();
if (action == MotionEvent.ACTION_DOWN) {
Log.e(TAG, "onTouch: action = MotionEvent.ACTION_DOWN");
startX = event.getX();
startY = event.getY();
mPath.moveTo(startX, startY);
} else if (action == MotionEvent.ACTION_MOVE) {
Log.e(TAG, "onTouch: action = MotionEvent.ACTION_MOVE");
endX = event.getX();
endY = event.getY();
mPath.lineTo(endX, endY);
invalidate();
} else if (action == MotionEvent.ACTION_UP) {
Log.e(TAG, "onTouch: action = MotionEvent.ACTION_UP");
}
return true;
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Log.e(TAG, "onDraw: -------------------startX = " + startX + " endX = " + endX);
mPaint.setXfermode(null);
mRect.set(0, 0, canvas.getWidth(), canvas.getHeight());
mPaint.setColor(Color.parseColor("#FFCEE0E0"));
mPaint.setStyle(Paint.Style.FILL);
canvas.drawRect(mRect, mPaint);
mPaint.setColor(Color.RED);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setXfermode(mPorterDuffXfermode);
canvas.drawPath(mPath, mPaint);
}
}
Activity代码
package com.noahedu.currentactivity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
public class MainActivity extends AppCompatActivity {
private TextView textview;
private Button test_button;
private Thread thread;
private GuaGuaCard guaguacard;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textview = findViewById(R.id.textview);
test_button = findViewById(R.id.test_button);
guaguacard = findViewById(R.id.guaguacard);
textview.setText("世有伯乐,然后有千里马。千里马常有,而伯乐不常有。故虽有名马,祗辱于奴隶人之手,骈死于槽枥之间,不以千里称也。\n" +
"\n" +
"马之千里者,一食或尽粟一石。食马者不知其能千里而食也。是马也,虽有千里之能,食不饱,力不足,才美不外见,且欲与常马等不可得,安求其能千里也?\n" +
"\n" +
"策之不以其道,食之不能尽其材,鸣之而不能通其意,执策而临之,曰:“天下无马!”呜呼!其真无马邪?其真不知马也!");
}
}
activity_main.xml代码
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:id="@+id/textview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"
android:textSize="16sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/test_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/app_name"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
/>
<com.noahedu.currentactivity.GuaGuaCard
android:id="@+id/guaguacard"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="visible"
/>
</android.support.constraint.ConstraintLayout>
实现效果
参考:
Android Paint Xfermode 学习小结
Android PorterDuffXfermode使用中的一些坑
网友评论