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

2020/4/16 23:56:52

本文主要是介绍Android 灰白化处理(清明节效果 多种方法简单实现),对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

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

 

2.实现逻辑

首先我们看下布局的


我们第一种方法就是用布局替换的思维去实现

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

我们去自定义一个 FrameLayout代码如下:

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)这样我们就可以实现布局包括布局内的控件都有灰白的效果,下一步就是我们的替换步骤了
复制代码

1、如果你的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    
    }
}
复制代码

2、如果你的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我们的目的就是替换他

①我们在BaseActivity的onCreat方法中添加

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效果没有实现灰白化:

处理方法:第一种方法的第二个实现和第二种一起使用就可以了

结尾总结:

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





这篇关于Android 灰白化处理(清明节效果 多种方法简单实现)的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程