如何在Android Support Library v24.0.0中以编程方式设置AppBarLayout的高度?

19

将安卓支持库从v23.4.0升级到v24.0.0后,对AppBarLayout编程设置高度为0的阴影已经不再有效:

appBayLayout.setElevation(0);

当在XML中设置海拔高度时,它确实起作用。

3个回答

28

编辑

v24.0.0中的AppBarLayout使用了一个StateListAnimator,根据其状态定义高度。因此,如果正在使用StateListAnimator(默认情况下会发生这种情况),则使用setElevation将没有任何影响。通过XML或编程方式设置elevation(API>= 21都适用)。

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

旧答案

这似乎是设计支持库的一个问题。问题与程序设置高程的方式有关,使用setElevation。从XML中设置它会在视图中放置一个StateListAnimator而不调用setElevation。然而,setElevation应该能够工作。

这里有一个解决方法:

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);
}

这是从构造函数中获取的,调用了类ViewUtilsLollipop中的一个方法,在v24.0.0版本中。


在您的示例 stateListAnimator.addState(new int[0], ObjectAnimator.ofFloat(view, "elevation", 0)); 中使用了哪个 view - Volodymyr
@VolodymyrKhodonovych 作为参数传递的那个。 - bryant1410
2
我在Android 21中遇到了以下错误:JNI检测到应用程序错误:无法在空对象上调用void android.view.View.setElevation(float)。 - Volodymyr
@VolodymyrKhodonovych,看起来你的视图对象引用为空。 - bryant1410

8

另一种可能的解决方案是在您的 AppBarLayout 中添加android:stateListAnimator="@null",如下所示。

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

2
我同时使用了 appBarLayout.setElevation(0)appBarLayout.setStateListAnimator(null) 来禁用阴影,以及 appBarLayout.setElevation(10.5) 来启用。它在运行时和屏幕旋转后都有效。 - Johnny Five

0
在我的情况下,我需要在运行时更改AppBarLayout的高度,并且setElevation(..)起到了作用。
然而,在屏幕旋转后,从onCreateOptionMenu调用setElevation(..)没有起作用,但是setStateListAnimator(null)起到了作用。
因此,我得出了这个逻辑:
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);
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接