如何在 Android 支持库 v24.0.0 中以编程方式设置 AppBarLayout 的高度?
How to set the elevation of an AppBarLayout programmatically in the Android Support Library v24.0.0?
从 Android 支持库 v23.4.0 升级到 v24.0.0 时,以编程方式将 AppBarLayout 的高度设置为 0 停止工作:
appBayLayout.setElevation(0);
在 XML 中设置海拔时确实有效。
编辑
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);
旧答案
这似乎是 issue of the design support library。该问题与使用 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);
}
这取自构造函数所做的事情,在 v24.0.0.
中调用 class ViewUtilsLollipop
中的方法
另一种可能的解决方案是将 android:stateListAnimator="@null"
添加到您的 AppBarLayout
中,如下所示。
<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">
在我的例子中,我需要在运行时更改 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);
}
}
从 Android 支持库 v23.4.0 升级到 v24.0.0 时,以编程方式将 AppBarLayout 的高度设置为 0 停止工作:
appBayLayout.setElevation(0);
在 XML 中设置海拔时确实有效。
编辑
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);
旧答案
这似乎是 issue of the design support library。该问题与使用 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);
}
这取自构造函数所做的事情,在 v24.0.0.
中调用 classViewUtilsLollipop
中的方法
另一种可能的解决方案是将 android:stateListAnimator="@null"
添加到您的 AppBarLayout
中,如下所示。
<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">
在我的例子中,我需要在运行时更改 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);
}
}