Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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.

like image 885
bryant1410 Avatar asked Jun 23 '16 12:06

bryant1410


2 Answers

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.

like image 188
bryant1410 Avatar answered Nov 10 '22 07:11

bryant1410


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">
like image 41
Volodymyr Avatar answered Nov 10 '22 06:11

Volodymyr