美文网首页
使用PorterDuffXfermode实现刮刮卡效果

使用PorterDuffXfermode实现刮刮卡效果

作者: duoduo7628 | 来源:发表于2021-02-05 20:34 被阅读0次
    PorterDuff其实来自两个人名:Tomas Porter和Tom Duff。利用PorterDuff.Mode,我们可以实现图片的任意叠加混合。

    先画圆,在画矩形,代码中间设置Xfermode。圆在下,矩形在上。SrcOver是默认状态

    全重叠
    部分重叠

    因为准备画“部分重叠”状态,所以用ClearDstOut都可以,因为矩形即使不重叠的部分也会消失,因为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使用中的一些坑

    相关文章

      网友评论

          本文标题:使用PorterDuffXfermode实现刮刮卡效果

          本文链接:https://www.haomeiwen.com/subject/lpsqzktx.html