Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android: setBackgroundTintList works on support fab, setSupportBackgroundTintList causes npe

I have a support fab defined as follows:

<android.support.design.widget.FloatingActionButton
        android:id="@+id/somefab"
        android:layout_width="50dp"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="20dp"
        app:elevation="6dp"
        app:rippleColor="@android:color/white"
        />

if I set the backgroundtintlist programmatically like this then it works:

somefab.setBackgroundTintList(ColorStateList.valueOf(Color.GRAY));

however, this is a support fab that should be visible on lower apis, so I want to use the support method:

somefab.setSupportBackgroundTintList(ColorStateList.valueOf(Color.GRAY));

and here already I'm getting a null pointer exception.

    java.lang.RuntimeException: Unable to start activity ComponentInfo{myprojectpath}: java.lang.NullPointerException: Attempt to invoke virtual method 'android.graphics.drawable.Drawable android.graphics.drawable.Drawable$ConstantState.newDrawable()' on a null object reference
  at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2416)
  at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2476)
  at android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:4077)
  at android.app.ActivityThread.-wrap15(ActivityThread.java)
  at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1350)
  at android.os.Handler.dispatchMessage(Handler.java:102)
  at android.os.Looper.loop(Looper.java:148)
  at android.app.ActivityThread.main(ActivityThread.java:5417)
  at java.lang.reflect.Method.invoke(Native Method)
  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
                                                                            Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'android.graphics.drawable.Drawable android.graphics.drawable.Drawable$ConstantState.newDrawable()' on a null object reference
  at android.graphics.drawable.LayerDrawable$ChildDrawable.<init>(LayerDrawable.java:1723)
  at android.graphics.drawable.LayerDrawable$LayerState.<init>(LayerDrawable.java:1792)
  at android.graphics.drawable.RippleDrawable$RippleState.<init>(RippleDrawable.java:998)
  at android.graphics.drawable.RippleDrawable.createConstantState(RippleDrawable.java:989)
  at android.graphics.drawable.RippleDrawable.createConstantState(RippleDrawable.java:988)
  at android.graphics.drawable.LayerDrawable.mutate(LayerDrawable.java:1652)
  at android.graphics.drawable.RippleDrawable.mutate(RippleDrawable.java:975)
  at android.support.v7.widget.AppCompatDrawableManager.tintDrawable(AppCompatDrawableManager.java:773)
  at android.support.v7.widget.AppCompatBackgroundHelper.applySupportBackgroundTint(AppCompatBackgroundHelper.java:115)
  at android.support.v7.widget.AppCompatBackgroundHelper.setSupportBackgroundTintList(AppCompatBackgroundHelper.java:90)
  at android.support.v7.widget.AppCompatImageButton.setSupportBackgroundTintList(AppCompatImageButton.java:99)
  at myproject.myActivity$override.onCreate(myActivity.java:126)
  at myproject.myActivity$override.access$dispatch(myActivity.java)
  at myproject.myActivity.onCreate(myActivity.java:0)
  at android.app.Activity.performCreate(Activity.java:6251)
  at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1107)
  at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2369)
  at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2476) 
  at android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:4077) 
  at android.app.ActivityThread.-wrap15(ActivityThread.java) 
  at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1350) 
  at android.os.Handler.dispatchMessage(Handler.java:102) 
  at android.os.Looper.loop(Looper.java:148) 
  at android.app.ActivityThread.main(ActivityThread.java:5417) 
  at java.lang.reflect.Method.invoke(Native Method) 
  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726) 
  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616) 

Why does the first method work but not the second?

like image 305
Jon Avatar asked Feb 08 '23 13:02

Jon


1 Answers

This should work, I tested it on API 15, 21 and 23:

ViewCompat.setBackgroundTintList(somefab, ColorStateList.valueOf(Color.GRAY));

Why? Going to the source of setSupportBackgroundTintList() shows this:

/**
 * This should be accessed via
 * {@link android.support.v4.view.ViewCompat#setBackgroundTintList(android.view.View, ColorStateList)}
 *
 * @hide
 */
@Override
public void setSupportBackgroundTintList(@Nullable ColorStateList tint) {
    if (mBackgroundTintHelper != null) {
        mBackgroundTintHelper.setSupportBackgroundTintList(tint);
    }
}

It seems the setSupportBackgroundTintList() method should be called indirectly using ViewCompat.setBackgroundTintList(). I tried to call setSupportBackgroundTintList() directly, it worked on API 15 and 21 but crashed on API 23, giving the same NullPointerException you gave.

like image 151
Benjamin Ting Avatar answered Feb 10 '23 04:02

Benjamin Ting