zoukankan      html  css  js  c++  java
  • 【Android】解析Paint类中MaskFilter的使用

    目录结构:

    contents structure [+]

    MaskFilter可以用来指定画笔的边缘效果。如果引用开启硬件加速的话,那么MaskFilter将不会起作用。
    关闭硬件加速:

    android:hardwareAccelerated="false"

    Android中有两个已知的MaskFilter实现类,分别是:BlurMaskFilter和EmbossMaskFilter:
    BlurMaskFilter:指定模糊样式和影响半径。
    EmbossMaskFilter:指定浮雕的光源方向和周围光强度。

    在实际中,使用不同的方法可能会有不同的硬件加速情况,比如笔者测试发现drawText默认是关闭硬件加速的,drawRect默认是开启硬件加速的。除了在Application.xml文件中指定硬件加速的开关情况,也可以通过代码来实现:

    //不使用硬件加速
    myview.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
    //...
    //使用硬件加速
    myview.setLayerType(View.LAYER_TYPE_HARDWARE,null);

    1.EmbossMaskFilter

    EmbossMaskFilter用于完成浮雕效果,通过PS可以更简单的完成类似的效果。EmbossMaskFilter的唯一构造方法是:

    public EmbossMaskFilter (float[] direction,float ambient,float specular,float blurRadius)

    这个构造方法在API 28(Android 9.0)中已经被废弃了。

    在指定参数的时候需要指定光源方向(direction)、环境光强度(ambient)、镜面反射系数(specular)和模糊半径(blurRadius)。

    float[] direction=new float[]{1,1,1};//指定光源方向
    float light=0.4f;//指定环境光强度(0~1),0~1表示环境从暗到亮
    float specular=6f;//指定镜面反射系数,越接近0,反射光越强。
    float blur=3f;//指定模糊半径,值越大,越清晰。
    
    EmbossMaskFilter emboss=new EmbossMaskFilter(direction,light,specular,blur);
    if(!canvas.isHardwareAccelerated()){//在未硬件加速的情况下设置效果
        myPaint.setMaskFilter(emboss);
    }

    如下代码:

    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        Paint paint=new Paint();
        paint.setColor(Color.RED);
        paint.setStyle(Style.FILL);
        paint.setTextSize(70);
    
        float[] direction=new float[]{1,1,1};//指定光源方向
        float light=0.3f;//指定环境光强度
        float specular=5;//指定镜面反射强度
        float blur=5f;//指定模糊程度
    
        EmbossMaskFilter emboss=new EmbossMaskFilter(direction,light,specular,blur);
        
        if(!canvas.isHardwareAccelerated()){//如果没有开启硬件加速,就设置浮雕效果
            paint.setMaskFilter(emboss);
        }
        canvas.drawText("test测试", 200,200, paint);//绘制文本
    }

    效果图:

    通过改变为不同的参数,可以得到不同的效果。

    2.BlurMaskFilter

    BlurMaskFilter有一个构造方法如下:

    BlurMaskFilter(float radius, BlurMaskFilter.Blur style)

    在构建BlurMaskFilter时,需要传入BlurMaskFilter.Blur枚举值,该枚举值有如下4种:

    BlurMaskFilter.Blur.INNER 在边界内模糊,边界外不模糊
    BlurMaskFilter.Blur.NORMAL 在边界内和边界外都模糊
    BlurMaskFilter.Blur.OUTER 在边界外模糊,边界内不模糊
    BlurMaskFilter.Blur.SOLID 在边边界内使用solid边框,边界外模糊


    下面是使用示例:
    activity_main.xml

    <RelativeLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:id="@+id/rl"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:padding="16dp"
        tools:context=".MainActivity"
        android:background="#ffffff"
        >
        <TextView
            android:id="@+id/tv"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_centerInParent="true"
            android:text="ANDROID"
            android:textSize="100dp"
            android:textStyle="bold"
            android:textColor="#ff0000"
            android:gravity="center"
            />
        <RadioGroup
            android:id="@+id/rg"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="horizontal"
            >
            <RadioButton
                android:id="@+id/rb_none"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="No blur"
                />
            <RadioButton
                android:id="@+id/rb_inner"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Inner blur"
                />
            <RadioButton
                android:id="@+id/rb_normal"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Normal blur"
                />
            <RadioButton
                android:id="@+id/rb_outer"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Outer blur"
                />
            <RadioButton
                android:id="@+id/rb_solid"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Solid blur"
                />
        </RadioGroup>
    </RelativeLayout>

    MainActivity.jave

    import android.app.Activity;
    import android.content.Context;
    import android.content.pm.ActivityInfo;
    import android.content.res.Resources;
    import android.graphics.BlurMaskFilter;
    import android.graphics.Paint;
    import android.os.Bundle;
    import android.view.View;
    import android.view.Window;
    import android.widget.RadioGroup;
    import android.widget.RelativeLayout;
    import android.widget.TextView;
    
    public class MainActivity extends Activity {
        Context mContext=null;
        Resources mResources=null;
        RelativeLayout mRelativeLayout=null;
        TextView mTextView=null;
        RadioGroup mRadioGroup=null;
        
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);//设置横屏
            
            mContext = getApplicationContext();
    
            mResources = getResources();
    
            mRelativeLayout = (RelativeLayout) findViewById(R.id.rl);
            mTextView = (TextView) findViewById(R.id.tv);
            mRadioGroup = (RadioGroup) findViewById(R.id.rg);
    
            // Set a checked change listener for RadioGroup
            mRadioGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
                @Override
                public void onCheckedChanged(RadioGroup radioGroup, int i) {
                    if (i == R.id.rb_none) {
                        // If no blur is checked
                        // Set the TextView layer type
                        mTextView.setLayerType(View.LAYER_TYPE_SOFTWARE,null);
                        // Clear any previous MaskFilter
                        mTextView.getPaint().setMaskFilter(null);
                    }
                    if(i == R.id.rb_inner){
                        // If inner blur checked
                        applyBlurMaskFilter(mTextView, BlurMaskFilter.Blur.INNER);
                    }
                    if(i == R.id.rb_normal){
                        // If normal blur checked
                        applyBlurMaskFilter(mTextView, BlurMaskFilter.Blur.NORMAL);
                    }
                    if(i == R.id.rb_outer){
                        // If outer blur checked
                        applyBlurMaskFilter(mTextView, BlurMaskFilter.Blur.OUTER);
                    }
                    if(i == R.id.rb_solid){
                        // If solid blur checked
                        applyBlurMaskFilter(mTextView, BlurMaskFilter.Blur.SOLID);
                    }
                }
            });
        }
    
        // Custom method to apply BlurMaskFilter to a TextView text
        protected void applyBlurMaskFilter(TextView tv, BlurMaskFilter.Blur style){
    
            // Define the blur effect radius
            float radius = tv.getTextSize()/10;
    
            // Initialize a new BlurMaskFilter instance
            BlurMaskFilter filter = new BlurMaskFilter(radius,style);
    
            /*
                public void setLayerType (int layerType, Paint paint)
                    Specifies the type of layer backing this view. The layer can be LAYER_TYPE_NONE,
                    LAYER_TYPE_SOFTWARE or LAYER_TYPE_HARDWARE.
    
                    A layer is associated with an optional Paint instance that controls how the
                    layer is composed on screen.
                    
                Parameters
                    layerType : The type of layer to use with this view, must be one of
                        LAYER_TYPE_NONE, LAYER_TYPE_SOFTWARE or LAYER_TYPE_HARDWARE
                    paint : The paint used to compose the layer. This argument is optional and can be null. It is ignored when the layer type is LAYER_TYPE_NONE
            */
            /*
                public static final int LAYER_TYPE_SOFTWARE
                    Indicates that the view has a software layer. A software layer is backed by
                    a bitmap and causes the view to be rendered using Android's software rendering
                    pipeline, even if hardware acceleration is enabled.
            */
            
            // Set the TextView layer type
            tv.setLayerType(View.LAYER_TYPE_SOFTWARE, new Paint());//取消硬件加速
    
            tv.getPaint().setMaskFilter(filter);
        }
    }

    效果图:

    参考文章:

    How to use BlurMaskFilter In Android

  • 相关阅读:
    [vue Debugger] sourcemap
    [vuex]持久化存储
    [vuex]字典值封装到vuex缓存
    [vue]常用指令集合
    VSCode插件集合
    [element-ui] 表格点击出现编辑效果实现
    [pdf] 插件实现pdf上传预览、打印
    [html] 特殊字符
    [element-ui] 穿梭框对象重复不添加方案
    Redis持久化
  • 原文地址:https://www.cnblogs.com/HDK2016/p/9721633.html
Copyright © 2011-2022 走看看