Search code examples
androidandroid-support-libraryandroid-support-design

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.


Solution

  • 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.