How to set the elevation of an AppBarLayout programmatically in the Android Support Library v24.0.0?
Asked Answered
J

3

19

When upgrading from the Android Support Library v23.4.0 to v24.0.0, setting the elevation to 0 programmatically to an AppBarLayout stopped working:

appBayLayout.setElevation(0);

It does work when setting the elevation in the XML.

Jowers answered 23/6, 2016 at 12:58 Comment(0)
J
28

Edit

The AppBarLayout from v24.0.0 uses a StateListAnimator that defines the elevation depending on its state. So using setElevation will have no effect if a StateListAnimator is being used (which happens by default). Set the elevation via the XML or programmatically (both for API >= 21):

StateListAnimator stateListAnimator = new StateListAnimator();
stateListAnimator.addState(new int[0], ObjectAnimator.ofFloat(view, "elevation", 0));
appBarLayout.setStateListAnimator(stateListAnimator);

Old answer

This seems to be an issue of the design support library. The problem is related to the way the elevation is set programmatically, using setElevation. Setting it from the XML is placing a StateListAnimator in the view and not calling setElevation. However, setElevation should work.

Here there is a workaround:

setDefaultAppBarLayoutStateListAnimator(appBarLayout, 0);

@SuppressLint("PrivateResource")
private static void setDefaultAppBarLayoutStateListAnimator(final View view, final float targetElevation) {
    final StateListAnimator sla = new StateListAnimator();

    // Enabled, collapsible and collapsed == elevated
    sla.addState(new int[]{android.R.attr.enabled, android.support.design.R.attr.state_collapsible,
            android.support.design.R.attr.state_collapsed},
            ObjectAnimator.ofFloat(view, "elevation", targetElevation));

    // Enabled and collapsible, but not collapsed != elevated
    sla.addState(new int[]{android.R.attr.enabled, android.support.design.R.attr.state_collapsible,
            -android.support.design.R.attr.state_collapsed},
            ObjectAnimator.ofFloat(view, "elevation", 0f));

    // Enabled but not collapsible == elevated
    sla.addState(new int[]{android.R.attr.enabled, -android.support.design.R.attr.state_collapsible},
            ObjectAnimator.ofFloat(view, "elevation", targetElevation));

    // Default, none elevated state
    sla.addState(new int[0], ObjectAnimator.ofFloat(view, "elevation", 0));

    view.setStateListAnimator(sla);
}

This is taken from what the constructor does, calling a method in the class ViewUtilsLollipop in v24.0.0.

Jowers answered 23/6, 2016 at 12:58 Comment(4)
Which view is used in your example stateListAnimator.addState(new int[0], ObjectAnimator.ofFloat(view, "elevation", 0));?Lowlife
@VolodymyrKhodonovych the one passed as a parameterJowers
I have error in android 21 like this > JNI DETECTED ERROR IN APPLICATION: can't call void > android.view.View.setElevation(float) on null objectLowlife
@VolodymyrKhodonovych it seems that your view object reference is nullJowers
L
8

One more possible solution for this is to add android:stateListAnimator="@null" to your AppBarLayout as shown below.

<android.support.design.widget.AppBarLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:stateListAnimator="@null"
        android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">
Lowlife answered 2/12, 2016 at 21:46 Comment(1)
I used both appBarLayout.setElevation(0) and appBarLayout.setStateListAnimator(null) to disable elevation and appBarLayout.setElevation(10.5) to enable. It worked in run time and after screen rotationLamebrain
L
0

In my case I needed to change elevation of AppBarLayout in runtime and setElevation(..) did the trick.

However after screen rotation and calling setElevation(..) from onCreateOptionMenu didn't work, but setStateListAnimator(null) did the trick.

Therefore I got this logic:

public final float appBarElevation = 10.5f;

public void disableAppBarElevation() {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
        appBarLayout.setElevation(0);
        appBarLayout.setStateListAnimator(null);
    }
}

public void enableAppBarElevation() {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
        appBarLayout.setElevation(appBarElevation);
    }
}
Lamebrain answered 11/3, 2019 at 9:32 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.