使用 java 创建的 Ripple Drawable 在 pre lollipop 上崩溃

Ripple Drawable created using java crashes on pre lollipop

我没有使用 XML 文件来设置波纹可绘制对象的状态,而是使用 java new RippleDrawable(color, backgroundDrawable, null) constructor在每个项目都有自己的颜色的适配器中使用它。该代码在 post 棒棒糖设备上按预期工作,但它在棒棒糖之前的设备上崩溃并出现以下错误,即使我添加了 SDK_INT check

   if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
        holder.rootView.setBackground(getBackgroundDrawable(ColorConverter.lightenColor(Color.parseColor(item.getTextColor()), 0.6f), background));
    }

getBackgroundDrawable()

 @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
private static RippleDrawable getBackgroundDrawable(int pressedColor, Drawable backgroundDrawable) {
    return new RippleDrawable(getPressedState(pressedColor), backgroundDrawable, null);
}

getPressedState()

 private static ColorStateList getPressedState(int pressedColor) {
    return new ColorStateList(new int[][]{new int[]{}}, new int[]{pressedColor});
}

错误堆栈跟踪

E/dalvikvm: Could not find class 'android.graphics.drawable.RippleDrawable', referenced from method com.test.app.adapter.util.DashboardButtonsAdapter.getBackgroundDrawable
12-11 18:40:07.745 14717-14717/com.test.app E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.test.app, PID: 14717
java.lang.VerifyError: com/test/app/adapter/util/DashboardButtonsAdapter
    at com.test.app.fragment.dashboard.DashboardPageFragment.onCreateView(DashboardPageFragment.java:71)
    at androidx.fragment.app.Fragment.performCreateView(Fragment.java:2439)
    at androidx.fragment.app.FragmentManagerImpl.moveToState(FragmentManager.java:1460)
    at androidx.fragment.app.FragmentManagerImpl.moveFragmentToExpectedState(FragmentManager.java:1784)
    at androidx.fragment.app.FragmentManagerImpl.moveToState(FragmentManager.java:1852)
    at androidx.fragment.app.BackStackRecord.executeOps(BackStackRecord.java:802)
    at androidx.fragment.app.FragmentManagerImpl.executeOps(FragmentManager.java:2625)
    at androidx.fragment.app.FragmentManagerImpl.executeOpsTogether(FragmentManager.java:2411)
    at androidx.fragment.app.FragmentManagerImpl.removeRedundantOperationsAndExecute(FragmentManager.java:2366)
    at androidx.fragment.app.FragmentManagerImpl.execSingleAction(FragmentManager.java:2243)
    at androidx.fragment.app.BackStackRecord.commitNowAllowingStateLoss(BackStackRecord.java:654)
    at androidx.fragment.app.FragmentStatePagerAdapter.finishUpdate(FragmentStatePagerAdapter.java:168)
    at androidx.viewpager.widget.ViewPager.populate(ViewPager.java:1244)
    at androidx.viewpager.widget.ViewPager.populate(ViewPager.java:1092)
    at androidx.viewpager.widget.ViewPager.onMeasure(ViewPager.java:1622)
    at android.view.View.measure(View.java:16504)
    at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5125)
    at androidx.coordinatorlayout.widget.CoordinatorLayout.onMeasureChild(CoordinatorLayout.java:733)
    at androidx.coordinatorlayout.widget.CoordinatorLayout.onMeasure(CoordinatorLayout.java:805)
    at android.view.View.measure(View.java:16504)
    at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5125)
    at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1404)
    at android.widget.LinearLayout.measureHorizontal(LinearLayout.java:1052)
    at android.widget.LinearLayout.onMeasure(LinearLayout.java:590)
    at android.view.View.measure(View.java:16504)
    at android.widget.LinearLayout.measureVertical(LinearLayout.java:847)
    at android.widget.LinearLayout.onMeasure(LinearLayout.java:588)
    at android.view.View.measure(View.java:16504)
    at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5125)
    at android.widget.FrameLayout.onMeasure(FrameLayout.java:310)
    at androidx.appcompat.widget.ContentFrameLayout.onMeasure(ContentFrameLayout.java:143)
    at android.view.View.measure(View.java:16504)
    at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5125)
    at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1404)
    at android.widget.LinearLayout.measureVertical(LinearLayout.java:695)
    at android.widget.LinearLayout.onMeasure(LinearLayout.java:588)
    at android.view.View.measure(View.java:16504)
    at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5125)
    at android.widget.FrameLayout.onMeasure(FrameLayout.java:310)
    at android.view.View.measure(View.java:16504)
    at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5125)
    at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1404)
    at android.widget.LinearLayout.measureVertical(LinearLayout.java:695)
    at android.widget.LinearLayout.onMeasure(LinearLayout.java:588)
    at android.view.View.measure(View.java:16504)
    at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5125)
    at android.widget.FrameLayout.onMeasure(FrameLayout.java:310)
    at com.android.internal.policy.impl.PhoneWindow$DecorView.onMeasure(PhoneWindow.java:2291)
    at android.view.View.measure(View.java:16504)
    at android.view.ViewRootImpl.performMeasure(ViewRootImpl.java:1912)
    at android.view.ViewRootImpl.measureHierarchy(ViewRootImpl.java:1109)
    at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1291)
    at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:996)
    at android.view.ViewRootImpl$TraversalRunnable.run(ViewRo

#getBackgroundDrawable 的原因是 returning a RippleDrawable 。因为它只有 21+ 可用,所以验证错误,因为它是一个独立的方法,并且 android 找不到方法签名中的 return 类型。 要验证这一点,当您 运行 下面的代码时,您不会得到相同的错误,因为对整个代码块进行了版本检查。

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
        RippleDrawable rippleDrawable= new RippleDrawable(getPressedState(Color.GREEN), null, null);
        textView.setBackground(rippleDrawable);
    }

解决您问题的最简单方法是将 #getBackgroundDrawable 的 return 类型更改为 Drawable

@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
private static Drawable getBackgroundDrawable(int pressedColor, Drawable backgroundDrawable) {
    return new RippleDrawable(getPressedState(pressedColor), backgroundDrawable, null);
}

java.lang.VerifyError 表示您的代码引用了 android 无法找到的内容。将返回类型更改为 Drawable 方法签名将对 API-19 有效。 如果你 运行 这个代码没有版本检查那么你会得到 ClassNotFoundException 因为现在实际的方法体正在执行。看看 This thread.

我们知道RippleDrawable()不支持android版本以下的棒棒糖(21版本以下)。

所以对于之前的棒棒糖版本, 对于连锁反应,你可以试试这个。

这个图书馆Material

dependencies { 
implementation 'com.github.rey5137:material:1.3.1'
 }
    

这是您的按钮代码,

<com.rey.material.widget.Button 
   style="@style/YourOwnStyle" 
   android:layout_width="wrap_content" 
   android:layout_height="wrap_content" 
   android:text="BUTTON" 
  app:rd_style="@style/YourRippleDrawableStyle"/>

自定义视图也支持,

有关更多详细信息,请查看此 link、

https://github.com/rey5137/Material/wiki/Button