【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