1. 程式人生 > >Android中的自繪View的那些事兒(五)之 遮罩濾鏡:BlurMaskFilter 和 EmbossMaskFilter 的簡介

Android中的自繪View的那些事兒(五)之 遮罩濾鏡:BlurMaskFilter 和 EmbossMaskFilter 的簡介

MaskFilter

MaskFilter翻譯過來叫遮罩濾鏡,它可以為Paint邊緣的alpha通道應用轉換。目前有兩個子類:BlurMaskFilter 和 EmbossMaskFilter。它們分別可實現出模糊效果和浮雕效果。

BlurMaskFilter

BlurMaskFilter是指定一個半徑值使處理Paint的邊緣變模糊。我們來看看它的建構函式:

BlurMaskFilter(float radius,          // 半徑值,必須大於0
        BlurMaskFilter.Blur style)    // 模糊效果,它是一個列舉值,其值包括:NORMAL、SOLID、OUTER 和 INNER

示例:

public class MyView extends View {
   public MyView(Context context) {
        this(context, null, 0);
    }
 
   public MyView(Context context, @Nullable AttributeSet attrs) {
       this(context, attrs, 0);
    }
 
   public MyView(Context context, @Nullable AttributeSet attrs, intdefStyleAttr) {
       super(context, attrs, defStyleAttr);
    }
 
   @Override
   protected void onDraw(Canvas canvas) {
       super.onDraw(canvas);
 
       Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
       paint.setColor(Color.RED);
 
       paint.setMaskFilter(new BlurMaskFilter(30, BlurMaskFilter.Blur.NORMAL));
       canvas.drawRect(100, 100, 250, 250, paint);
 
       paint.setMaskFilter(new BlurMaskFilter(30, BlurMaskFilter.Blur.SOLID));
       canvas.drawRect(100, 350, 250, 500, paint);
 
       paint.setMaskFilter(new BlurMaskFilter(30, BlurMaskFilter.Blur.OUTER));
       canvas.drawRect(100, 600, 250, 750, paint);
 
       paint.setMaskFilter(new BlurMaskFilter(30, BlurMaskFilter.Blur.INNER));
       canvas.drawRect(100, 850, 250, 1000, paint);
    }
}

執行效果:

看到執行效果後,是不是感覺到哪裡不對呢?原來因為在GPU硬體加速模式下,Paint的setMaskFilter是不被GPU支援的,所以為了能夠正常顯示MaskFilter的效果,需要將要繪製的Paint使用軟體渲染模式,即關閉硬體加速。我們來修改一下onDraw的程式碼:

@Override
   protected void onDraw(Canvas canvas) {
       super.onDraw(canvas);
 
       Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
       paint.setColor(Color.RED);
       setLayerType(View.LAYER_TYPE_SOFTWARE, paint);
 
       paint.setMaskFilter(new BlurMaskFilter(30, BlurMaskFilter.Blur.NORMAL));
       canvas.drawRect(100, 100, 250, 250, paint);
 
       paint.setMaskFilter(new BlurMaskFilter(30, BlurMaskFilter.Blur.SOLID));
       canvas.drawRect(100, 350, 250, 500, paint);
 
       paint.setMaskFilter(new BlurMaskFilter(30, BlurMaskFilter.Blur.OUTER));
       canvas.drawRect(100, 600, 250, 750, paint);
 
       paint.setMaskFilter(new BlurMaskFilter(30, BlurMaskFilter.Blur.INNER));
       canvas.drawRect(100, 850, 250, 1000, paint);
    }

執行效果:


注意到了嗎,新程式碼比舊程式碼就只是多了一行:setLayerType(View.LAYER_TYPE_SOFTWARE, paint); 便可以使paint的繪製關閉了硬體加速。其中,第二個引數也可為null,就表示當前View所有的繪製都會關閉硬體加速。除了針對View外,其實還可以對Activity或Application做關閉硬體加速的處理。方法就是在AndroidManifest.xml中使用android:hardwareAccelerated = "false",像這樣:

<application
         ……
       android:hardwareAccelerated = "false">
        
 
         <activity
                   ……
                   android:hardwareAccelerated="false"/>
</application>

EmbossMaskFilter

EmbossMaskFilter是指定方向、光亮度、反射等級以及模糊級別這些引數來決定繪出浮雕效果。我們來看看它的建構函式:

EmbossMaskFilter (float[] direction,       // 3個浮點值的陣列,X、Y、Z方向指定光源
                  float ambient,           // 環境光亮度,取值範圍是0~1
                  float specular,          // 反射等級,值如:8
                  float blurRadius)        // 照明前的模糊量,值如:3

示例:

public class MyView extends View {
   public MyView(Context context) {
       this(context, null, 0);
    }
 
   public MyView(Context context, @Nullable AttributeSet attrs) {
       this(context, attrs, 0);
    }
 
   public MyView(Context context, @Nullable AttributeSet attrs, intdefStyleAttr) {
       super(context, attrs, defStyleAttr);
    }
 
   @Override
   protected void onDraw(Canvas canvas) {
       super.onDraw(canvas);
 
       Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
       paint.setColor(Color.RED);
       setLayerType(View.LAYER_TYPE_SOFTWARE, paint);
 
 
       float[] direction = new float[] { 1, 1, 1 };
       float light = 1f;
       float specular = 1;
       float blur = 5;
       paint.setMaskFilter(new EmbossMaskFilter(direction, light, specular,blur));
       paint.setTextSize(100);
       paint.setFlags(Paint.FAKE_BOLD_TEXT_FLAG);
       canvas.drawText("Hello World", 50, 200, paint);
    }
}

上面程式碼中,在Paint的setMaskFilter方法中傳入了一個EmbossMaskFilter物件,最後效果將輸出在的繪製文字Hello World中。EmbossMaskFilter的四個引數的值決定了浮雕的效果,大家可自行去試驗。

執行效果: