blob: 8ab57bcfb2cdb80c394e1e019a988cd813ab056d [file] [log] [blame]
/*
* Copyright (C) 2013 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.dialer.app.widget;
import android.animation.ValueAnimator;
import android.os.Bundle;
import com.android.dialer.animation.AnimUtils.AnimationCallback;
import com.android.dialer.common.LogUtil;
/**
* Controls the various animated properties of the actionBar: showing/hiding, fading/revealing, and
* collapsing/expanding, and assigns suitable properties to the actionBar based on the current state
* of the UI.
*/
public class ActionBarController {
private static final String KEY_IS_SLID_UP = "key_actionbar_is_slid_up";
private static final String KEY_IS_FADED_OUT = "key_actionbar_is_faded_out";
private static final String KEY_IS_EXPANDED = "key_actionbar_is_expanded";
private ActivityUi activityUi;
private SearchEditTextLayout searchBox;
private boolean isActionBarSlidUp;
private final AnimationCallback fadeOutCallback =
new AnimationCallback() {
@Override
public void onAnimationEnd() {
slideActionBar(true /* slideUp */, false /* animate */);
}
@Override
public void onAnimationCancel() {
slideActionBar(true /* slideUp */, false /* animate */);
}
};
private ValueAnimator animator;
public ActionBarController(ActivityUi activityUi, SearchEditTextLayout searchBox) {
this.activityUi = activityUi;
this.searchBox = searchBox;
}
/** @return Whether or not the action bar is currently showing (both slid down and visible) */
public boolean isActionBarShowing() {
return !isActionBarSlidUp && !searchBox.isFadedOut();
}
/** Called when the user has tapped on the collapsed search box, to start a new search query. */
public void onSearchBoxTapped() {
LogUtil.d("ActionBarController.onSearchBoxTapped", "isInSearchUi " + activityUi.isInSearchUi());
if (!activityUi.isInSearchUi()) {
searchBox.expand(true /* animate */, true /* requestFocus */);
}
}
/** Called when search UI has been exited for some reason. */
public void onSearchUiExited() {
LogUtil.d(
"ActionBarController.onSearchUIExited",
"isExpanded: %b, isFadedOut %b",
searchBox.isExpanded(),
searchBox.isFadedOut());
if (searchBox.isExpanded()) {
searchBox.collapse(true /* animate */);
}
if (searchBox.isFadedOut()) {
searchBox.fadeIn();
}
slideActionBar(false /* slideUp */, false /* animate */);
}
/**
* Called to indicate that the user is trying to hide the dialpad. Should be called before any
* state changes have actually occurred.
*/
public void onDialpadDown() {
LogUtil.d(
"ActionBarController.onDialpadDown",
"isInSearchUi: %b, hasSearchQuery: %b, isFadedOut: %b, isExpanded: %b",
activityUi.isInSearchUi(),
activityUi.hasSearchQuery(),
searchBox.isFadedOut(),
searchBox.isExpanded());
if (activityUi.isInSearchUi()) {
if (searchBox.isFadedOut()) {
searchBox.setVisible(true);
}
if (!searchBox.isExpanded()) {
searchBox.expand(false /* animate */, false /* requestFocus */);
}
slideActionBar(false /* slideUp */, true /* animate */);
}
}
/**
* Called to indicate that the user is trying to show the dialpad. Should be called before any
* state changes have actually occurred.
*/
public void onDialpadUp() {
LogUtil.d("ActionBarController.onDialpadUp", "isInSearchUi " + activityUi.isInSearchUi());
if (activityUi.isInSearchUi()) {
slideActionBar(true /* slideUp */, true /* animate */);
} else {
// From the lists fragment
searchBox.fadeOut(fadeOutCallback);
}
}
public void slideActionBar(boolean slideUp, boolean animate) {
LogUtil.d("ActionBarController.slidingActionBar", "up: %b, animate: %b", slideUp, animate);
if (animator != null && animator.isRunning()) {
animator.cancel();
animator.removeAllUpdateListeners();
}
if (animate) {
animator = slideUp ? ValueAnimator.ofFloat(0, 1) : ValueAnimator.ofFloat(1, 0);
animator.addUpdateListener(
animation -> {
final float value = (float) animation.getAnimatedValue();
setHideOffset((int) (activityUi.getActionBarHeight() * value));
});
animator.start();
} else {
setHideOffset(slideUp ? activityUi.getActionBarHeight() : 0);
}
isActionBarSlidUp = slideUp;
}
public void setAlpha(float alphaValue) {
searchBox.animate().alpha(alphaValue).start();
}
private void setHideOffset(int offset) {
activityUi.setActionBarHideOffset(offset);
}
/** Saves the current state of the action bar into a provided {@link Bundle} */
public void saveInstanceState(Bundle outState) {
outState.putBoolean(KEY_IS_SLID_UP, isActionBarSlidUp);
outState.putBoolean(KEY_IS_FADED_OUT, searchBox.isFadedOut());
outState.putBoolean(KEY_IS_EXPANDED, searchBox.isExpanded());
}
/** Restores the action bar state from a provided {@link Bundle}. */
public void restoreInstanceState(Bundle inState) {
isActionBarSlidUp = inState.getBoolean(KEY_IS_SLID_UP);
final boolean isSearchBoxFadedOut = inState.getBoolean(KEY_IS_FADED_OUT);
if (isSearchBoxFadedOut) {
if (!searchBox.isFadedOut()) {
searchBox.setVisible(false);
}
} else if (searchBox.isFadedOut()) {
searchBox.setVisible(true);
}
final boolean isSearchBoxExpanded = inState.getBoolean(KEY_IS_EXPANDED);
if (isSearchBoxExpanded) {
if (!searchBox.isExpanded()) {
searchBox.expand(false, false);
}
} else if (searchBox.isExpanded()) {
searchBox.collapse(false);
}
}
/**
* This should be called after onCreateOptionsMenu has been called, when the actionbar has been
* laid out and actually has a height.
*/
public void restoreActionBarOffset() {
slideActionBar(isActionBarSlidUp /* slideUp */, false /* animate */);
}
public interface ActivityUi {
boolean isInSearchUi();
boolean hasSearchQuery();
int getActionBarHeight();
void setActionBarHideOffset(int offset);
}
}