简体   繁体   中英

Ripple Drawable created using java crashes on pre lollipop

I'm not using the XML file to set the state of the ripple drawable instead I'm using the java new RippleDrawable(color, backgroundDrawable, null) constructor as I'm using it in adapter where each item has there own color. The code works as expected on post lollipop devices but it crashes with the following error on pre lollipop ones even though I have added an 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});
}

Error Stacktrace

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

The reason for is #getBackgroundDrawable is returning a RippleDrawable . Because its available only 21+ hence the Verify error because its an independent method and return type in method signature is not found by android. To verify this when you run the code below you won't get the same error because there is a version check for whole code block.

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

The easiest solution for your problem is to change the return type of #getBackgroundDrawable to 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 means your code is referring to something that android cannot find. Changing the returt type to Drawable method signature will be valid for API-19. If you run this code without version check then u will get ClassNotFoundException because now actual method body is getting executed. Have a look at This thread .

As we know RippleDrawable() is not supported lollipop below android version(below 21 version).

So for before lollipop version, For ripple effect you can try this.

This library Material

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

And it's your button code,

<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"/>

在此处输入图像描述

It's also support in custom view,

For more detail checkout this link,

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM