Android 灰白化处理(清明节效果 多种方法简单实现)

  1. 首先看下没有灰白化的和灰白化后的效果对比

 

2.实现逻辑java

首先咱们看下布局的android


咱们第一种方法就是用布局替换的思惟去实现canvas

首先咱们能看到id/content的ContentFrameLayout咱们的目的就是替换他bash

咱们去自定义一个 FrameLayout代码以下:ide

class GrayFrameLayout(    context: Context,    attrs: AttributeSet?
) : FrameLayout(context, attrs) { 
   private val paint: Paint    
/**   
  * 绘制控件自己     
  * @param canvas     
  */   
override fun draw(canvas: Canvas) {    
    canvas.saveLayer(null, paint, Canvas.ALL_SAVE_FLAG)        
    super.draw(canvas)        
    canvas.restore()    
}    
/**     
* 绘制子控件     
* @param canvas     
*/    
override fun dispatchDraw(canvas: Canvas) {        
    canvas.saveLayer(null, paint, Canvas.ALL_SAVE_FLAG)        
    super.dispatchDraw(canvas)        
    canvas.restore()    
}    
init {        
        paint = Paint()        
        val colorMatrixColorFilter =ColorMatrixColorFilter(MatrixArrays.gray_matrix)        
        paint.colorFilter = colorMatrixColorFilter    
    }
}复制代码
MatrixArrays.gray_matrix是用矩阵实现的灰白效果
/** 
* 灰白 
*/
val gray_matrix = floatArrayOf(    
0.33f, 0.59f, 0.11f, 0f, 0f,    
0.33f, 0.59f, 0.11f, 0f, 0f,    
0.33f, 0.59f, 0.11f, 0f, 0f, 
0f, 0f, 0f, 1f, 0f)这样咱们就能够实现布局包括布局内的控件都有灰白的效果,下一步就是咱们的替换步骤了
复制代码

一、若是你的BaseActivity继承的是Activity那下面的就你的替换流程
咱们利用布局加载器在BaseActivity的onCreate方法中:
LayoutInflaterCompat.setFactory2(layoutInflater,GrayFactory())①GrayFactory代码以下:
class GrayFactory : Factory2 {    
//Android5.0以前继承activity的灰白化处理    
override fun onCreateView(        
parent: View?,        
name: String,        
context: Context,        
attrs: AttributeSet    ): View? {        
    if (TextUtils.equals("FrameLayout", name)) {            
        val attributeCount = attrs.attributeCount            
    for (i in 0 until attributeCount) {                
        val attributeName = attrs.getAttributeName(i)                
        val attributeValue = attrs.getAttributeValue(i)                
            if (TextUtils.equals("id", attributeName)) {                    
                val id = attributeValue.substring(1).toInt()                    
                    val resourceName = context.resources.getResourceName(id)                    
                        if (TextUtils.equals("android:id/content", resourceName)) {                        
                             return GrayFrameLayout(context, attrs) //建立灰白化framelayout                    
                }                
            }            
        }        
    }        
    return onCreateView(name, context, attrs)    
}    
override fun onCreateView(        
name: String,        
context: Context,        
attrs: AttributeSet    ): View? {        
var view: View? = null        
try {            
val aClass = context.classLoader.loadClass(name)            
val constructor: Constructor<out View> =                
                    aClass.getConstructor(                    
                    Context::class.java, AttributeSet::class.java                
                    ) as Constructor<out View>            
view = constructor.newInstance(context, attrs)        
} 
catch (e: ClassNotFoundException) {            
e.printStackTrace()        
} 
catch (e: NoSuchMethodException) {            
e.printStackTrace()        } 
catch (e: IllegalAccessException) {            
e.printStackTrace()        } 
catch (e: InstantiationException) {            
e.printStackTrace()        } 
catch (e: InvocationTargetException) {            
e.printStackTrace()        }        
return view    
    }
}
复制代码

二、若是你的BaseActivity继承的是AppCompatActivity那下面的就你的替换流程:就是把上面的简化了
在BaseActivity的onCreateView方法中:
if (TextUtils.equals("FrameLayout", name)) {
        val attributeCount = attrs.attributeCount
        for (i in 0 until attributeCount) {
            val attributeName = attrs.getAttributeName(i)
            val attributeValue = attrs.getAttributeValue(i)
            if (TextUtils.equals("id", attributeName)) {
                val id = attributeValue.substring(1).toInt()
                val resourceName = context.resources.getResourceName(id)
                if (TextUtils.equals("android:id/content", resourceName)) {
                    return GrayFrameLayout(context, attrs) //建立灰白化framelayout
                }
            }
        }
    }
return super.onCreateView(name, context, attrs)//必定是调super的,这里容易出现死循环
复制代码

咱们第二种方法就是用布局替换的思惟去实现布局

首先咱们看到上面的最根的根布局是DecorView咱们的目的就是替换他ui

①咱们在BaseActivity的onCreat方法中添加spa

var decorView = window.decorViewvar
var paint = Paint()
val colorMatrixColorFilter =    ColorMatrixColorFilter(MatrixArrays.gray_matrix)
paint.colorFilter = colorMatrixColorFilter
decorView.setLayerType(View.LAYER_TYPE_HARDWARE,paint)//记得在清单文件中打开硬件加速

还有一种实现//不用矩阵计算用系统自带的
 Paint paint = new Paint();
            ColorMatrix cm = new ColorMatrix();
            cm.setSaturation(0);//0就是灰白效果
            paint.setColorFilter(new ColorMatrixColorFilter(cm));
            activity.getWindow().getDecorView().setLayerType(View.LAYER_TYPE_HARDWARE, paint);复制代码

在使用的过程当中可能会发现dialog效果没有实现灰白化:3d

处理方法:第一种方法的第二个实现和第二种一块儿使用就能够了rest

结尾总结:

本文主要用到的是布局替换,项目中每一个界面都有相同的系统根布局DecorView、ContentFrameLayout因此从这里入手这个能够看下源码更清楚   

相关文章
相关标签/搜索