Files
Lawnchair/src/com/android/launcher3/allapps/ActivityAllAppsContainerView.java
T
Brian Isganitis 5eb66d8abb Refactor ActivityAllAppsContainerView to depend on ActivityContext.
All of the all apps search support is in this class which is also being
refactored to depend on ActivityContext. At the end of this refactor,
this class can be merged with BaseAllAppsContainerView.

Test: Manual
Bug: 216683257
Change-Id: I8cbf21c8d9ce97cc60e9846cfe8c2a7bcb800a01
2022-03-18 10:36:15 -07:00

263 lines
8.9 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 android.content.Context;
import android.content.Intent;
import android.util.AttributeSet;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
import android.widget.RelativeLayout;
import androidx.core.graphics.ColorUtils;
import androidx.recyclerview.widget.RecyclerView;
import com.android.launcher3.DeviceProfile.DeviceProfileListenable;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
import com.android.launcher3.allapps.search.SearchAdapterProvider;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.util.PackageManagerHelper;
import com.android.launcher3.views.AppLauncher;
import java.util.Objects;
/**
* All apps container view with search support for use in a dragging activity.
*
* @param <T> Type of context inflating all apps.
*/
public class ActivityAllAppsContainerView<T extends Context & AppLauncher
& DeviceProfileListenable> extends BaseAllAppsContainerView<T> {
protected SearchUiManager mSearchUiManager;
/**
* View that defines the search box. Result is rendered inside the recycler view defined in the
* base class.
*/
private View mSearchContainer;
/** {@code true} when rendered view is in search state instead of the scroll state. */
private boolean mIsSearching;
public ActivityAllAppsContainerView(Context context) {
this(context, null);
}
public ActivityAllAppsContainerView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public ActivityAllAppsContainerView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
public SearchUiManager getSearchUiManager() {
return mSearchUiManager;
}
public View getSearchView() {
return mSearchContainer;
}
/** Updates all apps container with the latest search query. */
public void setLastSearchQuery(String query) {
Intent marketSearchIntent = PackageManagerHelper.getMarketSearchIntent(
mActivityContext, query);
OnClickListener marketSearchClickListener = (v) -> mActivityContext.startActivitySafely(v,
marketSearchIntent, null);
for (int i = 0; i < mAH.size(); i++) {
mAH.get(i).adapter.setLastSearchQuery(query, marketSearchClickListener);
}
mIsSearching = true;
rebindAdapters();
mHeader.setCollapsed(true);
}
/** Invoke when the current search session is finished. */
public void onClearSearchResult() {
mIsSearching = false;
mHeader.setCollapsed(false);
rebindAdapters();
mHeader.reset(false);
}
/** Invoke when the search results change. */
public void onSearchResultsChanged() {
for (int i = 0; i < mAH.size(); i++) {
if (mAH.get(i).mRecyclerView != null) {
mAH.get(i).mRecyclerView.onSearchResultsChanged();
}
}
}
@Override
protected final SearchAdapterProvider<?> createMainAdapterProvider() {
return mActivityContext.createSearchAdapterProvider(this);
}
@Override
public boolean shouldContainerScroll(MotionEvent ev) {
// IF the MotionEvent is inside the search box, and the container keeps on receiving
// touch input, container should move down.
if (mActivityContext.getDragLayer().isEventOverView(mSearchContainer, ev)) {
return true;
}
return super.shouldContainerScroll(ev);
}
@Override
public void reset(boolean animate) {
super.reset(animate);
// Reset the search bar after transitioning home.
mSearchUiManager.resetSearch();
}
@Override
protected void onFinishInflate() {
super.onFinishInflate();
mSearchContainer = findViewById(R.id.search_container_all_apps);
mSearchUiManager = (SearchUiManager) mSearchContainer;
mSearchUiManager.initializeSearch(this);
}
@Override
public boolean dispatchKeyEvent(KeyEvent event) {
mSearchUiManager.preDispatchKeyEvent(event);
return super.dispatchKeyEvent(event);
}
@Override
public String getDescription() {
if (!mUsingTabs && mIsSearching) {
return getContext().getString(R.string.all_apps_search_results);
} else {
return super.getDescription();
}
}
@Override
protected boolean showTabs() {
return super.showTabs() && !mIsSearching;
}
@Override
protected void rebindAdapters(boolean force) {
super.rebindAdapters(force);
if (!FeatureFlags.ENABLE_DEVICE_SEARCH.get()
|| getMainAdapterProvider().getDecorator() == null) {
return;
}
RecyclerView.ItemDecoration decoration = getMainAdapterProvider().getDecorator();
mAH.stream()
.map(adapterHolder -> adapterHolder.mRecyclerView)
.filter(Objects::nonNull)
.forEach(v -> {
v.removeItemDecoration(decoration); // Remove in case it is already added.
v.addItemDecoration(decoration);
});
}
@Override
protected View replaceRVContainer(boolean showTabs) {
View rvContainer = super.replaceRVContainer(showTabs);
if (FeatureFlags.ENABLE_FLOATING_SEARCH_BAR.get()) {
alignParentTop(rvContainer);
layoutAboveSearchContainer(rvContainer);
} else {
layoutBelowSearchContainer(rvContainer);
}
return rvContainer;
}
@Override
void setupHeader() {
super.setupHeader();
if (FeatureFlags.ENABLE_FLOATING_SEARCH_BAR.get()) {
alignParentTop(mHeader);
} else {
layoutBelowSearchContainer(mHeader);
}
}
@Override
protected void updateHeaderScroll(int scrolledOffset) {
super.updateHeaderScroll(scrolledOffset);
if (mSearchUiManager.getEditText() == null) {
return;
}
float prog = Utilities.boundToRange((float) scrolledOffset / mHeaderThreshold, 0f, 1f);
boolean bgVisible = mSearchUiManager.getBackgroundVisibility();
if (scrolledOffset == 0 && !mIsSearching) {
bgVisible = true;
} else if (scrolledOffset > mHeaderThreshold) {
bgVisible = false;
}
mSearchUiManager.setBackgroundVisibility(bgVisible, 1 - prog);
}
@Override
protected int getHeaderColor(float blendRatio) {
return ColorUtils.setAlphaComponent(
super.getHeaderColor(blendRatio),
(int) (mSearchContainer.getAlpha() * 255));
}
@Override
protected int getHeaderBottom() {
if (FeatureFlags.ENABLE_FLOATING_SEARCH_BAR.get()) {
return super.getHeaderBottom();
}
return super.getHeaderBottom() + mSearchContainer.getBottom();
}
private void layoutBelowSearchContainer(View v) {
if (!(v.getLayoutParams() instanceof RelativeLayout.LayoutParams)) {
return;
}
RelativeLayout.LayoutParams layoutParams = (LayoutParams) v.getLayoutParams();
layoutParams.removeRule(RelativeLayout.ALIGN_PARENT_TOP);
layoutParams.removeRule(RelativeLayout.ABOVE);
layoutParams.addRule(RelativeLayout.BELOW, R.id.search_container_all_apps);
}
private void layoutAboveSearchContainer(View v) {
if (!(v.getLayoutParams() instanceof RelativeLayout.LayoutParams)) {
return;
}
RelativeLayout.LayoutParams layoutParams = (LayoutParams) v.getLayoutParams();
layoutParams.addRule(RelativeLayout.ABOVE, R.id.search_container_all_apps);
}
private void alignParentTop(View v) {
if (!(v.getLayoutParams() instanceof RelativeLayout.LayoutParams)) {
return;
}
RelativeLayout.LayoutParams layoutParams = (LayoutParams) v.getLayoutParams();
layoutParams.removeRule(RelativeLayout.BELOW);
layoutParams.addRule(RelativeLayout.ALIGN_PARENT_TOP);
}
@Override
protected BaseAllAppsAdapter getAdapter(AlphabeticalAppsList<T> mAppsList,
BaseAdapterProvider[] adapterProviders) {
return new AllAppsGridAdapter<>(mActivityContext, getLayoutInflater(), mAppsList,
adapterProviders);
}
}