关于使用PorterDuff.Mode.CLEAR实现丧心病狂的高亮效果

最近项目里面要做引导页,然后美工出图了,看到效果图的第一眼我觉得还是很容易的关于使用PorterDuff.Mode.CLEAR实现丧心病狂的高亮效果_第1张图片

我的第一个思路是用WindowManger 往里面丢View就行了,第2个思路是使用Dialog 来实现。然后问了下Lite群里面,有大神Aite
推荐了2个库:
https://github.com/hongyangAndroid/Highlight
https://github.com/fredericojssilva/ShowTipsView

抱着试一试的态度,我去看了2个库;然后发现ShowTipsView不就有我的想要的效果的么。

好吧,扯了那么久,终于要进入主题了(你他么真是啰嗦的啊)。
要实现这种相交区域高亮的效果,说实话以我作孽的智商是没有想出来的,不过还有大神的代码可以参考,让我们共同去了解其中的原理吧!!

  // ShowTipsView
        ShowTipsView showtips = new ShowTipsBuilder(this)
                .setTarget(btn_two).setTitle("A magnific button")
                .setDescription("This button do nothing very well")
                .setDelay(1000)
                .setBackgroundAlpha(128)
                .setCloseButtonColor(Color.RED)
                .setCloseButtonTextColor(Color.GREEN)
                .build();

        showtips.show(this);

这里看到构建ShowTipsView使用的是Builder模式,进去看下ShowTipsBuilder的构造方法,里面调用了

public ShowTipsBuilder(Activity activity) {
        this.showtipsView = new ShowTipsView(activity);
    }

那么进去看ShowTipsView

public ShowTipsView(Context context) {
        super(context);
        init();
    }

    private void init() {
        this.setVisibility(View.GONE);
        this.setBackgroundColor(Color.TRANSPARENT);

        this.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                // DO NOTHING
                // HACK TO BLOCK CLICKS

            }
        });

        showTipsStore = new StoreUtils(getContext());

        paint = new Paint();
        bitmapPaint = new Paint();
        circleline = new Paint();
        transparentPaint = new Paint();
        // it's very important,so highlight cool
        porterDuffXfermode = new PorterDuffXfermode(PorterDuff.Mode.CLEAR);
    }
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        /*
         * Draw circle and transparency background
         */

        /* 
         * Since bitmap needs the canva's size, it wont be load at init() 
         * To prevent the DrawAllocation issue on low memory devices, the bitmap will be instantiate only when its null
         */
        if (bitmap == null) {
            bitmap = Bitmap.createBitmap(canvas.getWidth(), canvas.getHeight(), Bitmap.Config.ARGB_8888);
            temp = new Canvas(bitmap);
        }

        if (background_color != 0)
            paint.setColor(background_color);
        else
            paint.setColor(Color.parseColor("#000000"));

        paint.setAlpha(background_alpha);
        temp.drawRect(0, 0, temp.getWidth(), temp.getHeight(), paint);

        transparentPaint.setColor(getResources().getColor(android.R.color.transparent));
        transparentPaint.setXfermode(porterDuffXfermode);

        int x = showhintPoints.x;
        int y = showhintPoints.y;
        temp.drawCircle(x, y, radius + 200, transparentPaint);

        canvas.drawBitmap(bitmap, 0, 0, bitmapPaint);

        circleline.setStyle(Paint.Style.STROKE);
        if (circleColor != 0)
            circleline.setColor(circleColor);
        else
            circleline.setColor(Color.RED);

        circleline.setAntiAlias(true);
        circleline.setStrokeWidth(3);
//      canvas.drawCircle(x, y, radius, circleline);
    }

说下源码的思路吧:

  1. 先把当前的View也就是ShowTipsView添加到ActivityDecorView里面去
  2. 根据一系列条件去生成需要的showhintPoints,具体逻辑请看代码
  3. 最主要的使用了PorterDuff.Mode.CLEAR,实现了高亮的效果;从onDraw的源码可以看出,先生成一个bitmap,在拿到他的Canvas即是里面变量temp,重要的是temp.drawCircle(x, y, radius, transparentPaint);这里使用了CLEAR,清除画布,如果吧这里注释掉之后就没有高亮的效果了;看了感觉原来原理还是很简单的啊!!!!
    好了原理之后了,剩下的就是Enjoy yourself !!!

你可能感兴趣的:(Android)