Android 8.0设备FloatingActionButton涟漪失效及Drawable归属报错求助
嘿,我之前也碰到过一模一样的情况!这个报错Error: Invalid drawable added to LayerDrawable! Drawable already belongs to another owner but does not expose a constant state,本质是Android 8.0(API 26)对Drawable的状态管理变得更严格了——当一个Drawable实例被多个View同时引用,但它没有提供可复用的ConstantState时,系统就会抛出这个错误,连带导致涟漪这类依赖Drawable状态的效果直接失效。
下面是几个我亲测有效的排查和解决方向:
检查是否存在Drawable复用场景
如果你在代码里直接把同一个Drawable实例赋值给了多个View(比如同时给FloatingActionButton和另一个按钮设置了同一个ripple drawable),就会触发这个问题。解决方法是用mutate()方法为每个View生成独立的Drawable实例,或者通过ConstantState创建新实例:// 错误示例:复用同一个Drawable实例 Drawable ripple = getResources().getDrawable(R.drawable.fab_ripple); fab1.setBackground(ripple); fab2.setBackground(ripple); // 这里会触发报错 // 正确做法1:使用mutate()生成独立实例 Drawable ripple1 = getResources().getDrawable(R.drawable.fab_ripple).mutate(); fab1.setBackground(ripple1); Drawable ripple2 = getResources().getDrawable(R.drawable.fab_ripple).mutate(); fab2.setBackground(ripple2); // 正确做法2:通过ConstantState创建新实例 Drawable.ConstantState state = getResources().getDrawable(R.drawable.fab_ripple).getConstantState(); fab1.setBackground(state.newDrawable()); fab2.setBackground(state.newDrawable());检查自定义Drawable的ConstantState实现
如果你用了自定义的RippleDrawable或LayerDrawable,要确保它正确实现了getConstantState()方法,返回一个能创建新实例的ConstantState对象。如果自定义Drawable没有处理这个逻辑,Android 8.0就会认为它无法被安全复用,从而抛出错误。排查XML布局中的资源引用
有时候在XML里给多个FAB引用同一个ripple资源,虽然理论上系统会自动为每个View创建独立实例,但如果你的Theme或资源配置有特殊处理(比如复用了Drawable缓存),也可能出现问题。这种情况下,可以在代码中手动为FAB设置mutate后的Drawable来规避。确认FAB的基础属性
最后别忘了检查FAB的clickable属性是否设为true,虽然这不是报错的直接原因,但如果按钮不可点击,涟漪效果本身也不会触发,可以作为辅助排查项。
按照上面的步骤排查后,应该就能解决无涟漪效果和报错的问题啦!
内容的提问来源于stack exchange,提问作者eckc

