- Create base SectionDecorationInfo.java and RecyclerViewAnimationController.java - SearchTransitionController now inherits from RecyclerViewAnimationController where RecyclerViewAnimationController will control animation for private space Bug: 299294792 Test: Verified SearchTransitionController didn't regress by turning off BACKGROUND_DRAWABLES flag. - Verified QL highlight still works - video: https://drive.google.com/file/d/15yjBWofebn6m7VgEnLK6kEYqhC_adJQ3/view?usp=sharing Flag: None Change-Id: If34f4bb199be0e113485279931d2927cb9fad397
140 lines
6.0 KiB
Java
140 lines
6.0 KiB
Java
/*
|
|
* Copyright (C) 2022 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.launcher3.allapps;
|
|
|
|
import static android.view.View.VISIBLE;
|
|
|
|
import static com.android.app.animation.Interpolators.DECELERATE_1_7;
|
|
import static com.android.app.animation.Interpolators.INSTANT;
|
|
import static com.android.app.animation.Interpolators.clampToProgress;
|
|
import static com.android.launcher3.anim.AnimatorListeners.forEndCallback;
|
|
import static com.android.launcher3.anim.AnimatorListeners.forSuccessCallback;
|
|
|
|
import android.animation.ObjectAnimator;
|
|
import android.animation.TimeInterpolator;
|
|
import android.view.View;
|
|
import android.view.animation.Interpolator;
|
|
|
|
import com.android.launcher3.R;
|
|
|
|
/** Coordinates the transition between Search and A-Z in All Apps. */
|
|
public class SearchTransitionController extends RecyclerViewAnimationController {
|
|
|
|
// Interpolator when the user taps the QSB while already in All Apps.
|
|
private static final Interpolator INTERPOLATOR_WITHIN_ALL_APPS = DECELERATE_1_7;
|
|
// Interpolator when the user taps the QSB from home screen, so transition to all apps is
|
|
// happening simultaneously.
|
|
private static final Interpolator INTERPOLATOR_TRANSITIONING_TO_ALL_APPS = INSTANT;
|
|
|
|
private boolean mSkipNextAnimationWithinAllApps;
|
|
|
|
public SearchTransitionController(ActivityAllAppsContainerView<?> allAppsContainerView) {
|
|
super(allAppsContainerView);
|
|
}
|
|
|
|
/**
|
|
* Starts the transition to or from search state. If a transition is already in progress, the
|
|
* animation will start from that point with the new duration, and the previous onEndRunnable
|
|
* will not be called.
|
|
*
|
|
* @param goingToSearch true if will be showing search results, otherwise will be showing a-z
|
|
* @param duration time in ms for the animation to run
|
|
* @param onEndRunnable will be called when the animation finishes, unless another animation is
|
|
* scheduled in the meantime
|
|
*/
|
|
@Override
|
|
protected void animateToState(boolean goingToSearch, long duration, Runnable onEndRunnable) {
|
|
super.animateToState(goingToSearch, duration, onEndRunnable);
|
|
if (!goingToSearch) {
|
|
mAnimator.addListener(forSuccessCallback(() -> {
|
|
mAllAppsContainerView.getFloatingHeaderView().setFloatingRowsCollapsed(false);
|
|
mAllAppsContainerView.getFloatingHeaderView().reset(false /* animate */);
|
|
mAllAppsContainerView.getAppsRecyclerViewContainer().setTranslationY(0);
|
|
}));
|
|
}
|
|
mAllAppsContainerView.getFloatingHeaderView().setFloatingRowsCollapsed(true);
|
|
mAllAppsContainerView.getFloatingHeaderView().setVisibility(VISIBLE);
|
|
mAllAppsContainerView.getFloatingHeaderView().maybeSetTabVisibility(VISIBLE);
|
|
mAllAppsContainerView.getAppsRecyclerViewContainer().setVisibility(VISIBLE);
|
|
getRecyclerView().setVisibility(VISIBLE);
|
|
}
|
|
|
|
@Override
|
|
protected SearchRecyclerView getRecyclerView() {
|
|
return mAllAppsContainerView.getSearchRecyclerView();
|
|
}
|
|
|
|
@Override
|
|
protected int onProgressUpdated(float searchToAzProgress) {
|
|
int searchHeight = super.onProgressUpdated(searchToAzProgress);
|
|
|
|
FloatingHeaderView headerView = mAllAppsContainerView.getFloatingHeaderView();
|
|
|
|
// Add predictions + app divider height to account for predicted apps which will now be in
|
|
// the Search RV instead of the floating header view. Note `getFloatingRowsHeight` returns 0
|
|
// when predictions are not shown.
|
|
int appsTranslationY = searchHeight + headerView.getFloatingRowsHeight();
|
|
|
|
if (headerView.usingTabs()) {
|
|
// Move tabs below the search results, and fade them out in 20% of the animation.
|
|
headerView.setTranslationY(searchHeight);
|
|
headerView.setAlpha(clampToProgress(searchToAzProgress, 0.8f, 1f));
|
|
|
|
// Account for the additional padding added for the tabs.
|
|
appsTranslationY +=
|
|
headerView.getTabsAdditionalPaddingBottom()
|
|
+ mAllAppsContainerView.getResources().getDimensionPixelOffset(
|
|
R.dimen.all_apps_tabs_margin_top)
|
|
- headerView.getPaddingTop();
|
|
}
|
|
|
|
View appsContainer = mAllAppsContainerView.getAppsRecyclerViewContainer();
|
|
appsContainer.setTranslationY(appsTranslationY);
|
|
// Fade apps out with tabs (in 20% of the total animation).
|
|
appsContainer.setAlpha(clampToProgress(searchToAzProgress, 0.8f, 1f));
|
|
return searchHeight;
|
|
}
|
|
|
|
/**
|
|
* Should only animate if the view is not an app icon or if the app row is complete.
|
|
*/
|
|
@Override
|
|
protected boolean shouldAnimate(View view, boolean hasDecorationInfo, boolean appRowComplete) {
|
|
return !isAppIcon(view) || appRowComplete;
|
|
}
|
|
|
|
@Override
|
|
protected TimeInterpolator getInterpolator() {
|
|
TimeInterpolator timeInterpolator =
|
|
mAllAppsContainerView.isInAllApps()
|
|
? INTERPOLATOR_WITHIN_ALL_APPS : INTERPOLATOR_TRANSITIONING_TO_ALL_APPS;
|
|
if (mSkipNextAnimationWithinAllApps) {
|
|
timeInterpolator = INSTANT;
|
|
mSkipNextAnimationWithinAllApps = false;
|
|
}
|
|
return timeInterpolator;
|
|
}
|
|
|
|
/**
|
|
* This should only be called from {@code LauncherSearchSessionManager} when app restarts due to
|
|
* theme changes.
|
|
*/
|
|
public void setSkipAnimationWithinAllApps(boolean skip) {
|
|
mSkipNextAnimationWithinAllApps = skip;
|
|
}
|
|
}
|