mirror of
https://github.com/LawnchairLauncher/lawnchair.git
synced 2026-02-19 10:48:19 +00:00
> Recycling DigitalWellBeingToast so that the view is not inflated everytime > Simplifying DigitalWellBeingToast to use a single text view > Adding support for footers in taskView without creating additional layout Bug: 122345781 Change-Id: Ia889819b93eb8644532ea95c6767554874d5e2d1
225 lines
8.2 KiB
Java
225 lines
8.2 KiB
Java
/*
|
|
* Copyright (C) 2017 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 static android.view.View.MeasureSpec.EXACTLY;
|
|
import static android.view.View.MeasureSpec.getSize;
|
|
import static android.view.View.MeasureSpec.makeMeasureSpec;
|
|
|
|
import static com.android.launcher3.LauncherState.ALL_APPS_HEADER;
|
|
import static com.android.launcher3.Utilities.prefixTextWithIcon;
|
|
import static com.android.launcher3.icons.IconNormalizer.ICON_VISIBLE_AREA_FACTOR;
|
|
|
|
import android.content.Context;
|
|
import android.graphics.Rect;
|
|
import android.text.Selection;
|
|
import android.text.Spannable;
|
|
import android.text.SpannableString;
|
|
import android.text.SpannableStringBuilder;
|
|
import android.text.method.TextKeyListener;
|
|
import android.util.AttributeSet;
|
|
import android.view.KeyEvent;
|
|
import android.view.View;
|
|
import android.view.ViewGroup.MarginLayoutParams;
|
|
import android.view.animation.Interpolator;
|
|
|
|
import com.android.launcher3.DeviceProfile;
|
|
import com.android.launcher3.ExtendedEditText;
|
|
import com.android.launcher3.Insettable;
|
|
import com.android.launcher3.Launcher;
|
|
import com.android.launcher3.R;
|
|
import com.android.launcher3.Utilities;
|
|
import com.android.launcher3.allapps.AllAppsContainerView;
|
|
import com.android.launcher3.allapps.AllAppsStore;
|
|
import com.android.launcher3.allapps.AlphabeticalAppsList;
|
|
import com.android.launcher3.allapps.SearchUiManager;
|
|
import com.android.launcher3.anim.PropertySetter;
|
|
import com.android.launcher3.graphics.TintedDrawableSpan;
|
|
import com.android.launcher3.util.ComponentKey;
|
|
|
|
import java.util.ArrayList;
|
|
|
|
/**
|
|
* Layout to contain the All-apps search UI.
|
|
*/
|
|
public class AppsSearchContainerLayout extends ExtendedEditText
|
|
implements SearchUiManager, AllAppsSearchBarController.Callbacks,
|
|
AllAppsStore.OnUpdateListener, Insettable {
|
|
|
|
|
|
private final Launcher mLauncher;
|
|
private final AllAppsSearchBarController mSearchBarController;
|
|
private final SpannableStringBuilder mSearchQueryBuilder;
|
|
|
|
private AlphabeticalAppsList mApps;
|
|
private AllAppsContainerView mAppsView;
|
|
|
|
// This value was used to position the QSB. We store it here for translationY animations.
|
|
private final float mFixedTranslationY;
|
|
private final float mMarginTopAdjusting;
|
|
|
|
public AppsSearchContainerLayout(Context context) {
|
|
this(context, null);
|
|
}
|
|
|
|
public AppsSearchContainerLayout(Context context, AttributeSet attrs) {
|
|
this(context, attrs, 0);
|
|
}
|
|
|
|
public AppsSearchContainerLayout(Context context, AttributeSet attrs, int defStyleAttr) {
|
|
super(context, attrs, defStyleAttr);
|
|
|
|
mLauncher = Launcher.getLauncher(context);
|
|
mSearchBarController = new AllAppsSearchBarController();
|
|
|
|
mSearchQueryBuilder = new SpannableStringBuilder();
|
|
Selection.setSelection(mSearchQueryBuilder, 0);
|
|
|
|
mFixedTranslationY = getTranslationY();
|
|
mMarginTopAdjusting = mFixedTranslationY - getPaddingTop();
|
|
|
|
setHint(prefixTextWithIcon(getContext(), R.drawable.ic_allapps_search, getHint()));
|
|
}
|
|
|
|
@Override
|
|
protected void onAttachedToWindow() {
|
|
super.onAttachedToWindow();
|
|
mLauncher.getAppsView().getAppsStore().addUpdateListener(this);
|
|
}
|
|
|
|
@Override
|
|
protected void onDetachedFromWindow() {
|
|
super.onDetachedFromWindow();
|
|
mLauncher.getAppsView().getAppsStore().removeUpdateListener(this);
|
|
}
|
|
|
|
@Override
|
|
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
|
// Update the width to match the grid padding
|
|
DeviceProfile dp = mLauncher.getDeviceProfile();
|
|
int myRequestedWidth = getSize(widthMeasureSpec);
|
|
int rowWidth = myRequestedWidth - mAppsView.getActiveRecyclerView().getPaddingLeft()
|
|
- mAppsView.getActiveRecyclerView().getPaddingRight();
|
|
|
|
int cellWidth = DeviceProfile.calculateCellWidth(rowWidth, dp.inv.numHotseatIcons);
|
|
int iconVisibleSize = Math.round(ICON_VISIBLE_AREA_FACTOR * dp.iconSizePx);
|
|
int iconPadding = cellWidth - iconVisibleSize;
|
|
|
|
int myWidth = rowWidth - iconPadding + getPaddingLeft() + getPaddingRight();
|
|
super.onMeasure(makeMeasureSpec(myWidth, EXACTLY), heightMeasureSpec);
|
|
}
|
|
|
|
@Override
|
|
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
|
|
super.onLayout(changed, left, top, right, bottom);
|
|
|
|
// Shift the widget horizontally so that its centered in the parent (b/63428078)
|
|
View parent = (View) getParent();
|
|
int availableWidth = parent.getWidth() - parent.getPaddingLeft() - parent.getPaddingRight();
|
|
int myWidth = right - left;
|
|
int expectedLeft = parent.getPaddingLeft() + (availableWidth - myWidth) / 2;
|
|
int shift = expectedLeft - left;
|
|
setTranslationX(shift);
|
|
}
|
|
|
|
@Override
|
|
public void initialize(AllAppsContainerView appsView) {
|
|
mApps = appsView.getApps();
|
|
mAppsView = appsView;
|
|
mSearchBarController.initialize(
|
|
new DefaultAppSearchAlgorithm(mApps.getApps()), this, mLauncher, this);
|
|
}
|
|
|
|
@Override
|
|
public void onAppsUpdated() {
|
|
mSearchBarController.refreshSearchResult();
|
|
}
|
|
|
|
@Override
|
|
public void resetSearch() {
|
|
mSearchBarController.reset();
|
|
}
|
|
|
|
@Override
|
|
public void preDispatchKeyEvent(KeyEvent event) {
|
|
// Determine if the key event was actual text, if so, focus the search bar and then dispatch
|
|
// the key normally so that it can process this key event
|
|
if (!mSearchBarController.isSearchFieldFocused() &&
|
|
event.getAction() == KeyEvent.ACTION_DOWN) {
|
|
final int unicodeChar = event.getUnicodeChar();
|
|
final boolean isKeyNotWhitespace = unicodeChar > 0 &&
|
|
!Character.isWhitespace(unicodeChar) && !Character.isSpaceChar(unicodeChar);
|
|
if (isKeyNotWhitespace) {
|
|
boolean gotKey = TextKeyListener.getInstance().onKeyDown(this, mSearchQueryBuilder,
|
|
event.getKeyCode(), event);
|
|
if (gotKey && mSearchQueryBuilder.length() > 0) {
|
|
mSearchBarController.focusSearchField();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void onSearchResult(String query, ArrayList<ComponentKey> apps) {
|
|
if (apps != null) {
|
|
mApps.setOrderedFilter(apps);
|
|
notifyResultChanged();
|
|
mAppsView.setLastSearchQuery(query);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void clearSearchResult() {
|
|
if (mApps.setOrderedFilter(null)) {
|
|
notifyResultChanged();
|
|
}
|
|
|
|
// Clear the search query
|
|
mSearchQueryBuilder.clear();
|
|
mSearchQueryBuilder.clearSpans();
|
|
Selection.setSelection(mSearchQueryBuilder, 0);
|
|
mAppsView.onClearSearchResult();
|
|
}
|
|
|
|
private void notifyResultChanged() {
|
|
mAppsView.onSearchResultsChanged();
|
|
}
|
|
|
|
@Override
|
|
public void setInsets(Rect insets) {
|
|
MarginLayoutParams mlp = (MarginLayoutParams) getLayoutParams();
|
|
mlp.topMargin = Math.round(Math.max(-mFixedTranslationY, insets.top - mMarginTopAdjusting));
|
|
requestLayout();
|
|
}
|
|
|
|
@Override
|
|
public float getScrollRangeDelta(Rect insets) {
|
|
if (mLauncher.getDeviceProfile().isVerticalBarLayout()) {
|
|
return 0;
|
|
} else {
|
|
int topMargin = Math.round(Math.max(
|
|
-mFixedTranslationY, insets.top - mMarginTopAdjusting));
|
|
return insets.bottom + topMargin + mFixedTranslationY;
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void setContentVisibility(int visibleElements, PropertySetter setter,
|
|
Interpolator interpolator) {
|
|
setter.setViewAlpha(this, (visibleElements & ALL_APPS_HEADER) != 0 ? 1 : 0, interpolator);
|
|
}
|
|
}
|