请忽略我之前的评论。我对此进行了一些研究,发现我之前的建议毫无意义。
当您调用
setSupportActionBar(Toolbar)
时,会发生以下情况:
public void setSupportActionBar(Toolbar toolbar) {
....
ToolbarActionBar tbab = new ToolbarActionBar(toolbar, ((Activity) mContext).getTitle(),
mAppCompatWindowCallback);
mActionBar = tbab;
....
}
因此,随后对
getSupportActionBar()
的调用将返回
ToolbarActionBar
的实例。看一下这个类如何实现我们感兴趣的特性:
setShowHideAnimationEnabled(boolean): 正如您指出的那样,该方法不会产生任何差异。
@Override
public void setShowHideAnimationEnabled(boolean enabled) {
}
show(): 仅使 ActionBar 可见 - 不支持动画效果。
@Override
public void show() {
mDecorToolbar.setVisibility(View.VISIBLE);
}
hide(): 只是让 ActionBar 再次可见 - 没有动画支持。
@Override
public void hide() {
mDecorToolbar.setVisibility(View.GONE);
}
show()
和 hide()
中的注释提示开发者应该提供动画过渡效果。也许可以像这样:
protected void hideActionBar(){
final ActionBar ab = getSupportActionBar();
if (ab != null && ab.isShowing()) {
if(mToolbar != null) {
mToolbar.animate().translationY(-112).setDuration(600L)
.withEndAction(new Runnable() {
@Override
public void run() {
ab.hide();
}
}).start();
} else {
ab.hide();
}
}
}
protected void showActionBar(){
ActionBar ab = getSupportActionBar();
if (ab != null && !ab.isShowing()) {
ab.show();
if(mToolbar != null) {
mToolbar.animate().translationY(0).setDuration(600L).start();
}
}
}
mToolbar.animate()
部分是凭记忆编写的 - 语法可能不正确 :(。您还可以添加 .alpha(0(隐藏期间)或1(显示期间))
以使过渡效果更好。
实现:
现在应该清楚的是,getSupportActionBar().show() & hide()
不关心您对 Toolbar
进行了什么操作。此外,Toolbar
应被视为 Activity 中的任何其他 View。考虑到这些要点,问题归结为 - 我们如何 动画地 隐藏(然后显示)一个 View
。由于我们需要 Activity 内容随着隐藏(或显示)的 Toolbar
滑动,因此我建议使用以下实现。请注意,这只是一个基本的例行程序。您肯定可以对此进行微调,或者提出完全不同(读作更好的)动画转换:
int mToolbarHeight, mAnimDuration = 600;
ValueAnimator mVaActionBar;
void hideActionBar() {
if (mToolbarHeight == 0) {
mToolbarHeight = mToolbar.getHeight();
}
if (mVaActionBar != null && mVaActionBar.isRunning()) {
return;
}
mVaActionBar = ValueAnimator.ofInt(mToolbarHeight , 0);
mVaActionBar.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
((AppBarLayout.LayoutParams)mToolbar.getLayoutParams()).height
= (Integer)animation.getAnimatedValue();
mToolbar.requestLayout();
}
});
mVaActionBar.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
if (getSupportActionBar() != null) {
getSupportActionBar().hide();
}
}
});
mVaActionBar.setDuration(mAnimDuration);
mVaActionBar.start();
}
void showActionBar() {
if (mVaActionBar != null && mVaActionBar.isRunning()) {
return;
}
mVaActionBar = ValueAnimator.ofInt(0 , mToolbarHeight);
mVaActionBar.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
((AppBarLayout.LayoutParams)mToolbar.getLayoutParams()).height
= (Integer)animation.getAnimatedValue();
mToolbar.requestLayout();
}
});
mVaActionBar.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationStart(Animator animation) {
super.onAnimationStart(animation);
if (getSupportActionBar() != null) {
getSupportActionBar().show();
}
}
});
mVaActionBar.setDuration(mAnimDuration);
mVaActionBar.start();
}
在您的评论中,提到了
I do see an animation now but the space still gets reserved for the toolbar until ab.hide() happens
。对我来说,这意味着您正在使用
AppBarLayout
来托管
Toolbar
。 如果不是,请告诉我,我们会想出其他办法。
最后,对这些方法的调用将根据以下方式进行分派:
if (getSupportActionBar().isShowing()) {
hideActionBar();
} else {
showActionBar();
}
getSupportActionBar().setShowHideAnimationEnabled(true)
。请注意,动画显示和隐藏仅适用于API 14及以上版本。 - VikramActionBar
还是ToolBar
? - Vladimir MarkeevToolBar
,请参考此链接 - https://dev59.com/018d5IYBdhLWcg3wsT4b - Vladimir Markeev