美文网首页优秀案例自定义控件
Android蒙层特定区域透明的实现

Android蒙层特定区域透明的实现

作者: lion_6bb6 | 来源:发表于2020-05-14 21:10 被阅读0次

    刚好最近在做蒙层指引,记录下来,方便后续使用。

    先上一张效果图:


    screen.png

    具体代码实现:

    1、自定义drawable
    package com.xsoft.demo;
    
    import android.graphics.Canvas;
    import android.graphics.ColorFilter;
    import android.graphics.Paint;
    import android.graphics.Path;
    import android.graphics.PorterDuff;
    import android.graphics.PorterDuffXfermode;
    import android.graphics.drawable.Drawable;
    
    import androidx.annotation.NonNull;
    import androidx.annotation.Nullable;
    
    public class CoverDrawable extends Drawable {
        private Drawable drawable;
        private Paint paint;
        private Path path = new Path();
    
        public CoverDrawable(@NonNull Drawable drawable) {
            this.drawable = drawable;
            paint = new Paint(Paint.ANTI_ALIAS_FLAG);
            paint.setColor(0xffffffff);
        }
    
        /**
         * 绘制圆
         *
         * @param drawable
         * @param x
         * @param y
         * @param radius
         */
        public CoverDrawable(@NonNull Drawable drawable,
                             int x, int y, int radius) {
            this(drawable);
            path.addCircle(x, y, radius, Path.Direction.CW);
        }
    
        /**
         * 绘制圆角矩形
         *
         * @param drawable
         * @param left
         * @param top
         * @param right
         * @param bottom
         * @param rx
         * @param ry
         */
        public CoverDrawable(@NonNull Drawable drawable,
                             int left, int top, int right, int bottom, int rx, int ry) {
            this(drawable);
            path.addRoundRect(left, top, right, bottom, rx, ry, Path.Direction.CW);
        }
    
        @Override
        public void draw(@NonNull Canvas canvas) {
            drawable.setBounds(getBounds());
            if (path == null || path.isEmpty()) {
                drawable.draw(canvas);
            } else {
                //将绘制操作保存在新的图层,因为图像合成是很昂贵的操作,将用到硬件加速,这里将图像合成的处理放到离屏缓存中进行
                int saveCount = canvas.saveLayer(0, 0, canvas.getWidth(), canvas.getHeight(), paint, Canvas.ALL_SAVE_FLAG);
                //绘制目标图
                drawable.draw(canvas);
                //设置混合模式
                paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
                //绘制原图
                canvas.drawPath(path, paint);
                //清除混合模式
                paint.setXfermode(null);
                //还原画布
                canvas.restoreToCount(saveCount);
            }
        }
    
        @Override
        public void setAlpha(int i) {
            drawable.setAlpha(i);
        }
    
        @Override
        public void setColorFilter(@Nullable ColorFilter colorFilter) {
            drawable.setColorFilter(colorFilter);
        }
    
        @Override
        public int getOpacity() {
            return drawable.getOpacity();
        }
    }
    
    

    如果需要实现其他的效果,只需增加构造方法,修改path即可。
    可以看出最核心的技术就是使用混合模式PorterDuffXfermode,这个博客讲解的比较透彻。

    2、布局文件
    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        tools:context=".MainActivity">
    
        <FrameLayout
            android:id="@+id/fl1"
            android:layout_width="match_parent"
            android:layout_height="200dp">
    
        </FrameLayout>
    
        <FrameLayout
            android:id="@+id/fl2"
            android:layout_width="match_parent"
            android:layout_height="200dp">
    
        </FrameLayout>
    </LinearLayout>
    
    3、activity实现
    package com.xsoft.demo;
    
    import androidx.appcompat.app.AppCompatActivity;
    
    import android.graphics.drawable.ColorDrawable;
    import android.os.Bundle;
    
    public class MainActivity extends AppCompatActivity {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            findViewById(R.id.fl1).setBackground(new CoverDrawable(new ColorDrawable(0xb2000000), 
                    100, 100, 50));
            findViewById(R.id.fl2).setBackground(new CoverDrawable(new ColorDrawable(0xb2000000), 
                    50, 10, 300, 150, 8, 8));
        }
    }
    

    相关文章

      网友评论

        本文标题:Android蒙层特定区域透明的实现

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