Merge changes from topics "all-apps-search-delegate-qpr", "search-container-view" into udc-qpr-dev
* changes: Add initial support for search session in Taskbar All Apps. Add All Apps search delegate for inflating search box.
This commit is contained in:
committed by
Android (Google) Code Review
commit
992065ba38
@@ -14,18 +14,11 @@
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
<com.android.launcher3.taskbar.allapps.TaskbarAllAppsSlideInView
|
||||
<com.android.launcher3.taskbar.allapps.TaskbarAllAppsContainerView
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:accessibilityPaneTitle="@string/all_apps_label">
|
||||
|
||||
<com.android.launcher3.taskbar.allapps.TaskbarAllAppsContainerView
|
||||
android:id="@+id/apps_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:clipChildren="true"
|
||||
android:clipToPadding="false"
|
||||
android:focusable="false"
|
||||
android:saveEnabled="false" />
|
||||
</com.android.launcher3.taskbar.allapps.TaskbarAllAppsSlideInView>
|
||||
android:clipChildren="true"
|
||||
android:clipToPadding="false"
|
||||
android:focusable="false"
|
||||
android:saveEnabled="false" />
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright (C) 2023 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.
|
||||
-->
|
||||
<com.android.launcher3.taskbar.allapps.TaskbarAllAppsSlideInView
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:accessibilityPaneTitle="@string/all_apps_label">
|
||||
|
||||
<include
|
||||
android:id="@+id/apps_view"
|
||||
layout="@layout/taskbar_all_apps" />
|
||||
</com.android.launcher3.taskbar.allapps.TaskbarAllAppsSlideInView>
|
||||
@@ -226,6 +226,7 @@ public class TaskbarControllers {
|
||||
taskbarPopupController.onDestroy();
|
||||
taskbarForceVisibleImmersiveController.onDestroy();
|
||||
taskbarOverlayController.onDestroy();
|
||||
taskbarAllAppsController.onDestroy();
|
||||
navButtonController.onDestroy();
|
||||
taskbarInsetsController.onDestroy();
|
||||
voiceInteractionWindowController.onDestroy();
|
||||
|
||||
@@ -45,8 +45,10 @@ import java.util.function.Predicate;
|
||||
public final class TaskbarAllAppsController {
|
||||
|
||||
private TaskbarControllers mControllers;
|
||||
private @Nullable TaskbarOverlayContext mOverlayContext;
|
||||
private @Nullable TaskbarAllAppsSlideInView mSlideInView;
|
||||
private @Nullable TaskbarAllAppsContainerView mAppsView;
|
||||
private @Nullable TaskbarSearchSessionController mSearchSessionController;
|
||||
|
||||
// Application data models.
|
||||
private AppInfo[] mApps;
|
||||
@@ -70,6 +72,11 @@ public final class TaskbarAllAppsController {
|
||||
}
|
||||
}
|
||||
|
||||
/** Clean up the controller. */
|
||||
public void onDestroy() {
|
||||
cleanUpOverlay();
|
||||
}
|
||||
|
||||
/** Updates the current {@link AppInfo} instances. */
|
||||
public void setApps(AppInfo[] apps, int flags, Map<PackageUserKey, Integer> map) {
|
||||
mApps = apps;
|
||||
@@ -96,6 +103,9 @@ public final class TaskbarAllAppsController {
|
||||
.findFixedRowByType(PredictionRowView.class)
|
||||
.setPredictedApps(mPredictedApps);
|
||||
}
|
||||
if (mSearchSessionController != null) {
|
||||
mSearchSessionController.setZeroStatePredictedItems(predictedApps);
|
||||
}
|
||||
}
|
||||
|
||||
/** Updates the current notification dots. */
|
||||
@@ -127,20 +137,25 @@ public final class TaskbarAllAppsController {
|
||||
// to catch invalid states.
|
||||
mControllers.getSharedState().allAppsVisible = true;
|
||||
|
||||
TaskbarOverlayContext overlayContext =
|
||||
mControllers.taskbarOverlayController.requestWindow();
|
||||
mSlideInView = (TaskbarAllAppsSlideInView) overlayContext.getLayoutInflater().inflate(
|
||||
R.layout.taskbar_all_apps, overlayContext.getDragLayer(), false);
|
||||
mOverlayContext = mControllers.taskbarOverlayController.requestWindow();
|
||||
|
||||
// Initialize search session for All Apps.
|
||||
mSearchSessionController = TaskbarSearchSessionController.newInstance(mOverlayContext);
|
||||
mOverlayContext.setSearchSessionController(mSearchSessionController);
|
||||
mSearchSessionController.setZeroStatePredictedItems(mPredictedApps);
|
||||
mSearchSessionController.startLifecycle();
|
||||
|
||||
mSlideInView = (TaskbarAllAppsSlideInView) mOverlayContext.getLayoutInflater().inflate(
|
||||
R.layout.taskbar_all_apps_sheet, mOverlayContext.getDragLayer(), false);
|
||||
mSlideInView.addOnCloseListener(() -> {
|
||||
mControllers.getSharedState().allAppsVisible = false;
|
||||
mSlideInView = null;
|
||||
mAppsView = null;
|
||||
cleanUpOverlay();
|
||||
});
|
||||
TaskbarAllAppsViewController viewController = new TaskbarAllAppsViewController(
|
||||
overlayContext, mSlideInView, mControllers);
|
||||
mOverlayContext, mSlideInView, mControllers);
|
||||
|
||||
viewController.show(animate);
|
||||
mAppsView = overlayContext.getAppsView();
|
||||
mAppsView = mOverlayContext.getAppsView();
|
||||
mAppsView.getAppsStore().setApps(mApps, mAppsModelFlags, mPackageUserKeytoUidMap);
|
||||
mAppsView.getFloatingHeaderView()
|
||||
.findFixedRowByType(PredictionRowView.class)
|
||||
@@ -149,8 +164,21 @@ public final class TaskbarAllAppsController {
|
||||
// Create a shared drag layer between taskbar and taskbarAllApps so that when dragging
|
||||
// starts and taskbarAllApps can close, but the drag layer that the view is being dragged in
|
||||
// doesn't also close
|
||||
overlayContext.getDragController().setDisallowGlobalDrag(mDisallowGlobalDrag);
|
||||
overlayContext.getDragController().setDisallowLongClick(mDisallowLongClick);
|
||||
mOverlayContext.getDragController().setDisallowGlobalDrag(mDisallowGlobalDrag);
|
||||
mOverlayContext.getDragController().setDisallowLongClick(mDisallowLongClick);
|
||||
}
|
||||
|
||||
private void cleanUpOverlay() {
|
||||
if (mSearchSessionController != null) {
|
||||
mSearchSessionController.onDestroy();
|
||||
mSearchSessionController = null;
|
||||
}
|
||||
if (mOverlayContext != null) {
|
||||
mOverlayContext.setSearchSessionController(null);
|
||||
mOverlayContext = null;
|
||||
}
|
||||
mSlideInView = null;
|
||||
mAppsView = null;
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright (C) 2023 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.taskbar.allapps
|
||||
|
||||
import android.content.Context
|
||||
import com.android.launcher3.R
|
||||
import com.android.launcher3.config.FeatureFlags
|
||||
import com.android.launcher3.model.data.ItemInfo
|
||||
import com.android.launcher3.util.ResourceBasedOverride
|
||||
import com.android.launcher3.util.ResourceBasedOverride.Overrides
|
||||
|
||||
/** Stub for managing the Taskbar search session. */
|
||||
open class TaskbarSearchSessionController : ResourceBasedOverride {
|
||||
|
||||
/** Start the search session lifecycle. */
|
||||
open fun startLifecycle() {}
|
||||
|
||||
/** Destroy the search session. */
|
||||
open fun onDestroy() {}
|
||||
|
||||
/** Updates the predicted items shown in the zero-state. */
|
||||
open fun setZeroStatePredictedItems(items: List<ItemInfo>) {}
|
||||
|
||||
companion object {
|
||||
@JvmStatic
|
||||
fun newInstance(context: Context): TaskbarSearchSessionController {
|
||||
if (!FeatureFlags.ENABLE_ALL_APPS_SEARCH_IN_TASKBAR.get()) {
|
||||
return TaskbarSearchSessionController()
|
||||
}
|
||||
|
||||
return Overrides.getObject(
|
||||
TaskbarSearchSessionController::class.java,
|
||||
context,
|
||||
R.string.taskbar_search_session_controller_class,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -18,6 +18,8 @@ package com.android.launcher3.taskbar.overlay;
|
||||
import android.content.Context;
|
||||
import android.view.View;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.android.launcher3.DeviceProfile;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.dot.DotInfo;
|
||||
@@ -29,6 +31,7 @@ import com.android.launcher3.taskbar.TaskbarControllers;
|
||||
import com.android.launcher3.taskbar.TaskbarDragController;
|
||||
import com.android.launcher3.taskbar.TaskbarUIController;
|
||||
import com.android.launcher3.taskbar.allapps.TaskbarAllAppsContainerView;
|
||||
import com.android.launcher3.taskbar.allapps.TaskbarSearchSessionController;
|
||||
import com.android.launcher3.util.SplitConfigurationOptions.SplitSelectSource;
|
||||
|
||||
/**
|
||||
@@ -47,6 +50,8 @@ public class TaskbarOverlayContext extends BaseTaskbarContext {
|
||||
private final int mStashedTaskbarHeight;
|
||||
private final TaskbarUIController mUiController;
|
||||
|
||||
private @Nullable TaskbarSearchSessionController mSearchSessionController;
|
||||
|
||||
public TaskbarOverlayContext(
|
||||
Context windowContext,
|
||||
TaskbarActivityContext taskbarContext,
|
||||
@@ -62,6 +67,15 @@ public class TaskbarOverlayContext extends BaseTaskbarContext {
|
||||
mUiController = controllers.uiController;
|
||||
}
|
||||
|
||||
public @Nullable TaskbarSearchSessionController getSearchSessionController() {
|
||||
return mSearchSessionController;
|
||||
}
|
||||
|
||||
public void setSearchSessionController(
|
||||
@Nullable TaskbarSearchSessionController searchSessionController) {
|
||||
mSearchSessionController = searchSessionController;
|
||||
}
|
||||
|
||||
int getStashedTaskbarHeight() {
|
||||
return mStashedTaskbarHeight;
|
||||
}
|
||||
|
||||
@@ -84,6 +84,7 @@
|
||||
<string name="window_manager_proxy_class" translatable="false"></string>
|
||||
<string name="secondary_display_predictions_class" translatable="false"></string>
|
||||
<string name="widget_holder_factory_class" translatable="false"></string>
|
||||
<string name="taskbar_search_session_controller_class" translatable="false"></string>
|
||||
|
||||
<!-- View ID to use for QSB widget -->
|
||||
<item type="id" name="qsb_widget" />
|
||||
|
||||
@@ -70,7 +70,7 @@ import com.android.launcher3.InsettableFrameLayout;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.Utilities;
|
||||
import com.android.launcher3.allapps.BaseAllAppsAdapter.AdapterItem;
|
||||
import com.android.launcher3.allapps.search.DefaultSearchAdapterProvider;
|
||||
import com.android.launcher3.allapps.search.AllAppsSearchUiDelegate;
|
||||
import com.android.launcher3.allapps.search.SearchAdapterProvider;
|
||||
import com.android.launcher3.config.FeatureFlags;
|
||||
import com.android.launcher3.keyboard.FocusedItemDecorator;
|
||||
@@ -132,6 +132,7 @@ public class ActivityAllAppsContainerView<T extends Context & ActivityContext>
|
||||
protected final Point mFastScrollerOffset = new Point();
|
||||
protected final int mScrimColor;
|
||||
protected final float mHeaderThreshold;
|
||||
protected final AllAppsSearchUiDelegate mSearchUiDelegate;
|
||||
|
||||
// Used to animate Search results out and A-Z apps in, or vice-versa.
|
||||
private final SearchTransitionController mSearchTransitionController;
|
||||
@@ -217,11 +218,17 @@ public class ActivityAllAppsContainerView<T extends Context & ActivityContext>
|
||||
getActiveRecyclerView().requestFocus();
|
||||
}
|
||||
});
|
||||
mSearchUiDelegate = createSearchUiDelegate();
|
||||
initContent();
|
||||
|
||||
mSearchTransitionController = new SearchTransitionController(this);
|
||||
}
|
||||
|
||||
/** Creates the delegate for initializing search. */
|
||||
protected AllAppsSearchUiDelegate createSearchUiDelegate() {
|
||||
return new AllAppsSearchUiDelegate(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the view hierarchy and internal variables. Any initialization which actually uses
|
||||
* these members should be done in {@link #onFinishInflate()}.
|
||||
@@ -231,7 +238,7 @@ public class ActivityAllAppsContainerView<T extends Context & ActivityContext>
|
||||
* onFinishInflate -> onPostCreate
|
||||
*/
|
||||
protected void initContent() {
|
||||
mMainAdapterProvider = createMainAdapterProvider();
|
||||
mMainAdapterProvider = mSearchUiDelegate.createMainAdapterProvider();
|
||||
|
||||
mAH.set(AdapterHolder.MAIN, new AdapterHolder(AdapterHolder.MAIN,
|
||||
new AlphabeticalAppsList<>(mActivityContext, mAllAppsStore, null)));
|
||||
@@ -252,6 +259,7 @@ public class ActivityAllAppsContainerView<T extends Context & ActivityContext>
|
||||
mSearchContainer = inflateSearchBox();
|
||||
addView(mSearchContainer);
|
||||
mSearchUiManager = (SearchUiManager) mSearchContainer;
|
||||
mSearchUiDelegate.onInitializeSearchBox();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -341,6 +349,7 @@ public class ActivityAllAppsContainerView<T extends Context & ActivityContext>
|
||||
*/
|
||||
public void setSearchResults(ArrayList<AdapterItem> results, int searchResultCode) {
|
||||
setSearchResults(results);
|
||||
mSearchUiDelegate.onSearchResultsChanged(results, searchResultCode);
|
||||
}
|
||||
|
||||
private void animateToSearchState(boolean goingToSearch) {
|
||||
@@ -788,12 +797,7 @@ public class ActivityAllAppsContainerView<T extends Context & ActivityContext>
|
||||
* Inflates the search box
|
||||
*/
|
||||
protected View inflateSearchBox() {
|
||||
return getLayoutInflater().inflate(R.layout.search_container_all_apps, this, false);
|
||||
}
|
||||
|
||||
/** Creates the adapter provider for the main section. */
|
||||
protected SearchAdapterProvider<?> createMainAdapterProvider() {
|
||||
return new DefaultSearchAdapterProvider(mActivityContext);
|
||||
return mSearchUiDelegate.inflateSearchBox();
|
||||
}
|
||||
|
||||
/** The adapter provider for the main section. */
|
||||
@@ -998,7 +1002,7 @@ public class ActivityAllAppsContainerView<T extends Context & ActivityContext>
|
||||
}
|
||||
|
||||
public LayoutInflater getLayoutInflater() {
|
||||
return LayoutInflater.from(getContext());
|
||||
return mSearchUiDelegate.getLayoutInflater();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1306,6 +1310,7 @@ public class ActivityAllAppsContainerView<T extends Context & ActivityContext>
|
||||
|
||||
protected void onInitializeRecyclerView(RecyclerView rv) {
|
||||
rv.addOnScrollListener(mScrollListener);
|
||||
mSearchUiDelegate.onInitializeRecyclerView(rv);
|
||||
}
|
||||
|
||||
/** Returns the instance of @{code SearchTransitionController}. */
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Copyright (C) 2023 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.search;
|
||||
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.allapps.ActivityAllAppsContainerView;
|
||||
import com.android.launcher3.allapps.BaseAllAppsAdapter.AdapterItem;
|
||||
import com.android.launcher3.views.ActivityContext;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/** Initializes the search box and its interactions with All Apps. */
|
||||
public class AllAppsSearchUiDelegate {
|
||||
|
||||
protected final ActivityAllAppsContainerView<?> mAppsView;
|
||||
protected final ActivityContext mActivityContext;
|
||||
|
||||
public AllAppsSearchUiDelegate(ActivityAllAppsContainerView<?> appsView) {
|
||||
mAppsView = appsView;
|
||||
mActivityContext = ActivityContext.lookupContext(mAppsView.getContext());
|
||||
}
|
||||
|
||||
/** Invoked when an All Apps {@link RecyclerView} is initialized. */
|
||||
public void onInitializeRecyclerView(RecyclerView rv) {
|
||||
// Do nothing.
|
||||
}
|
||||
|
||||
/** Invoked when search results are updated in All Apps. */
|
||||
public void onSearchResultsChanged(List<AdapterItem> results, int searchResultCode) {
|
||||
// Do nothing.
|
||||
}
|
||||
|
||||
/** Invoked when the search box has been added to All Apps. */
|
||||
public void onInitializeSearchBox() {
|
||||
// Do nothing.
|
||||
}
|
||||
|
||||
/** The layout inflater for All Apps and search UI. */
|
||||
public LayoutInflater getLayoutInflater() {
|
||||
return LayoutInflater.from(mAppsView.getContext());
|
||||
}
|
||||
|
||||
/** Inflate the search box for All Apps. */
|
||||
public View inflateSearchBox() {
|
||||
return getLayoutInflater().inflate(R.layout.search_container_all_apps, mAppsView, false);
|
||||
}
|
||||
|
||||
/** Creates the adapter provider for the main section. */
|
||||
public SearchAdapterProvider<?> createMainAdapterProvider() {
|
||||
return new DefaultSearchAdapterProvider(mActivityContext);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user