Loading quickstep/res/layout/fallback_search_input.xml 0 → 100644 +35 −0 Original line number Diff line number Diff line <?xml version="1.0" encoding="utf-8"?> <!-- Copyright (C) 2020 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.search.FallbackSearchInputView xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_gravity="center_vertical" android:layout_marginLeft="48dp" android:layout_marginRight="48dp" android:background="@android:color/transparent" android:focusableInTouchMode="true" android:gravity="start|center_vertical" android:inputType="textNoSuggestions" android:imeOptions="actionSearch|flagNoExtractUi" android:maxLines="1" android:privateImeOptions="bc_search" android:scrollHorizontally="true" android:singleLine="true" android:textColor="?android:attr/textColorSecondary" android:textColorHint="?android:attr/textColorTertiary" android:textSize="16sp" /> No newline at end of file quickstep/res/layout/search_edu_view.xml 0 → 100644 +73 −0 Original line number Diff line number Diff line <?xml version="1.0" encoding="utf-8"?><!-- Copyright (C) 2008 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.search.DeviceSearchEdu xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_gravity="center_horizontal" android:orientation="vertical"> <FrameLayout android:layout_height="wrap_content" android:id="@+id/search_box_wrapper" android:layout_width="match_parent"> <include layout="@layout/fallback_search_input" android:id="@+id/mock_search_box" /> </FrameLayout> <LinearLayout android:layout_height="wrap_content" android:id="@+id/edu_wrapper" android:padding="24dp" android:layout_marginTop="40dp" android:orientation="vertical" android:layout_width="match_parent"> <TextView style="@style/TextHeadline" android:layout_width="match_parent" android:gravity="center" android:textSize="24sp" android:textColor="?android:attr/textColorPrimary" android:layout_height="wrap_content" android:text="@string/search_edu_primary" /> <TextView style="@style/TextHeadline" android:layout_width="match_parent" android:gravity="center" android:textSize="18sp" android:layout_marginTop="30dp" android:textColor="?android:attr/textColorPrimary" android:layout_height="wrap_content" android:text="@string/search_edu_secondary" /> <Button android:id="@+id/dismiss_edu" android:layout_width="wrap_content" android:layout_marginTop="@dimen/dynamic_grid_edge_margin" android:background="?android:attr/selectableItemBackground" android:layout_height="wrap_content" android:textColor="?android:attr/textColorPrimary" android:gravity="center" android:layout_gravity="center" android:text="@string/search_edu_dismiss" /> </LinearLayout> </com.android.launcher3.search.DeviceSearchEdu> No newline at end of file quickstep/res/values/strings.xml +9 −0 Original line number Diff line number Diff line Loading @@ -93,6 +93,15 @@ <!-- content description for hotseat items --> <string name="hotseat_prediction_content_description">Predicted app: <xliff:g id="title" example="Chrome">%1$s</xliff:g></string> <!-- primary educational text shown for first time search users --> <string name="search_edu_primary">Search your phone for apps, people, settings and more!</string> <!-- secondary educational text shown for first time search users --> <string name="search_edu_secondary">Tap keyboard search button to launch the first search result.</string> <!-- Dismiss button string for search education view --> <string name="search_edu_dismiss">Got it.</string> <!-- Title shown during interactive part of Back gesture tutorial for right edge. [CHAR LIMIT=30] --> <string name="back_gesture_tutorial_playground_title_swipe_inward_right_edge" translatable="false">Try the back gesture</string> <!-- Subtitle shown during interactive parts of Back gesture tutorial for right edge. [CHAR LIMIT=60] --> Loading quickstep/src/com/android/launcher3/search/DeviceSearchEdu.java 0 → 100644 +221 −0 Original line number Diff line number Diff line /* * Copyright (C) 2021 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.search; import static com.android.launcher3.util.OnboardingPrefs.SEARCH_EDU_SEEN; import android.animation.PropertyValuesHolder; import android.content.Context; import android.graphics.Rect; import android.text.Editable; import android.text.TextWatcher; import android.util.AttributeSet; import android.view.KeyEvent; import android.view.LayoutInflater; import android.view.View; import android.view.inputmethod.InputMethodManager; import android.widget.EditText; import android.widget.TextView; import androidx.core.graphics.ColorUtils; import com.android.launcher3.AbstractFloatingView; import com.android.launcher3.Insettable; import com.android.launcher3.Launcher; import com.android.launcher3.LauncherState; import com.android.launcher3.R; import com.android.launcher3.anim.Interpolators; import com.android.launcher3.statemanager.StateManager; import com.android.launcher3.util.Themes; import com.android.launcher3.views.AbstractSlideInView; /** * Feature education for on-device Search. Shown the first time user opens AllApps Search */ public class DeviceSearchEdu extends AbstractSlideInView implements StateManager.StateListener<LauncherState>, TextWatcher, Insettable, TextView.OnEditorActionListener { private static final long ANIMATION_DURATION = 350; private static final int ANIMATION_CONTENT_TRANSLATION = 200; private EditText mEduInput; private View mInputWrapper; private EditText mSearchInput; private boolean mSwitchFocusOnDismiss; public DeviceSearchEdu(Context context) { this(context, null, 0); } public DeviceSearchEdu(Context context, AttributeSet attrs) { this(context, attrs, 0); } public DeviceSearchEdu(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } private void close(boolean animate, boolean markAsSeen) { handleClose(animate); if (markAsSeen) { mLauncher.getOnboardingPrefs().markChecked(SEARCH_EDU_SEEN); } } @Override protected void handleClose(boolean animate) { handleClose(animate, ANIMATION_DURATION); mLauncher.getStateManager().removeStateListener(this); } @Override protected boolean isOfType(int type) { return false; } @Override protected void onFinishInflate() { super.onFinishInflate(); mSearchInput = mLauncher.getAppsView().getSearchUiManager().getEditText(); mInputWrapper = findViewById(R.id.search_box_wrapper); mContent = findViewById(R.id.edu_wrapper); mEduInput = findViewById(R.id.mock_search_box); mEduInput.setHint(R.string.all_apps_on_device_search_bar_hint); mEduInput.addTextChangedListener(this); if (mSearchInput != null) { mEduInput.getLayoutParams().height = mSearchInput.getHeight(); mEduInput.setOnEditorActionListener(this); } else { mEduInput.setVisibility(INVISIBLE); } findViewById(R.id.dismiss_edu).setOnClickListener((view) -> { mSwitchFocusOnDismiss = true; close(true, true); }); } private void showInternal() { mLauncher.getStateManager().addStateListener(this); AbstractFloatingView.closeAllOpenViews(mLauncher); attachToContainer(); if (mSearchInput != null) { Rect r = mLauncher.getViewBounds(mSearchInput); mEduInput.requestFocus(); InputMethodManager imm = mLauncher.getSystemService(InputMethodManager.class); imm.showSoftInput(mEduInput, InputMethodManager.SHOW_IMPLICIT); ((LayoutParams) mInputWrapper.getLayoutParams()).setMargins(0, r.top, 0, 0); } animateOpen(); } @Override protected int getScrimColor(Context context) { return ColorUtils.setAlphaComponent(Themes.getAttrColor(context, R.attr.allAppsScrimColor), 230); } protected void setTranslationShift(float translationShift) { mTranslationShift = translationShift; mContent.setAlpha(getBoxedProgress(1 - mTranslationShift, .25f, 1)); mContent.setTranslationY(ANIMATION_CONTENT_TRANSLATION * translationShift); if (mColorScrim != null) { mColorScrim.setAlpha(getBoxedProgress(1 - mTranslationShift, 0, .75f)); } } /** * Given input [0-1], returns progress within bounds [min,max] allowing for staged animations */ private float getBoxedProgress(float input, float min, float max) { if (input < min) return 0; if (input > max) return 1; return (input - min) / (max - min); } private void animateOpen() { if (mIsOpen || mOpenCloseAnimator.isRunning()) { return; } mIsOpen = true; mOpenCloseAnimator.setValues( PropertyValuesHolder.ofFloat(TRANSLATION_SHIFT, TRANSLATION_SHIFT_OPENED)); mOpenCloseAnimator.setInterpolator(Interpolators.FAST_OUT_SLOW_IN); mOpenCloseAnimator.setDuration(ANIMATION_DURATION); mOpenCloseAnimator.start(); } /** * Show On-device search education view. */ public static void show(Launcher launcher) { LayoutInflater layoutInflater = LayoutInflater.from(launcher); ((DeviceSearchEdu) layoutInflater.inflate( R.layout.search_edu_view, launcher.getDragLayer(), false)).showInternal(); } @Override public void onStateTransitionStart(LauncherState toState) { close(true, false); } @Override protected void onCloseComplete() { super.onCloseComplete(); if (mSearchInput != null && mSwitchFocusOnDismiss) { mSearchInput.requestFocus(); mSearchInput.setSelection(mSearchInput.getText().length()); } } @Override public void afterTextChanged(Editable editable) { //Does nothing } @Override public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) { //Does nothing } @Override public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) { if (mSearchInput != null) { mSearchInput.setText(charSequence.toString()); mSwitchFocusOnDismiss = true; close(true, true); } } @Override public void setInsets(Rect insets) { } @Override public boolean onEditorAction(TextView textView, int i, KeyEvent keyEvent) { mSearchInput.onEditorAction(i); close(true, true); return true; } } quickstep/src/com/android/launcher3/search/FallbackSearchInputView.java 0 → 100644 +140 −0 Original line number Diff line number Diff line /* * Copyright (C) 2021 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.search; import static com.android.launcher3.LauncherState.ALL_APPS; import android.content.Context; import android.graphics.Rect; import android.util.AttributeSet; import com.android.launcher3.ExtendedEditText; import com.android.launcher3.Launcher; import com.android.launcher3.allapps.AllAppsContainerView; import com.android.launcher3.allapps.AllAppsGridAdapter.AdapterItem; import com.android.launcher3.allapps.AllAppsStore; import com.android.launcher3.allapps.AlphabeticalAppsList; import com.android.launcher3.allapps.FloatingHeaderView; import com.android.launcher3.allapps.search.AllAppsSearchBarController; import com.android.launcher3.allapps.search.SearchAlgorithm; import java.util.ArrayList; /** * A search view shown in all apps for on device search */ public class FallbackSearchInputView extends ExtendedEditText implements AllAppsSearchBarController.Callbacks, AllAppsStore.OnUpdateListener { private final AllAppsSearchBarController mSearchBarController; private AlphabeticalAppsList mApps; private Runnable mOnResultsChanged; private AllAppsContainerView mAppsView; public FallbackSearchInputView(Context context) { this(context, null); } public FallbackSearchInputView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public FallbackSearchInputView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); mSearchBarController = new AllAppsSearchBarController(); } @Override protected void onAttachedToWindow() { super.onAttachedToWindow(); Launcher.getLauncher(getContext()).getAppsView().getAppsStore().addUpdateListener(this); } @Override protected void onDetachedFromWindow() { super.onDetachedFromWindow(); Launcher.getLauncher(getContext()).getAppsView().getAppsStore().removeUpdateListener(this); } /** * Initializes SearchInput */ public void initialize(AllAppsContainerView appsView, SearchAlgorithm algo, Runnable changed) { mOnResultsChanged = changed; mApps = appsView.getApps(); mAppsView = appsView; mSearchBarController.initialize(algo, this, Launcher.getLauncher(getContext()), this); } @Override public void onSearchResult(String query, ArrayList<AdapterItem> items) { if (mApps != null && getParent() != null) { mApps.setSearchResults(items); notifyResultChanged(); collapseAppsViewHeader(true); mAppsView.setLastSearchQuery(query); } } @Override public void onAppendSearchResult(String query, ArrayList<AdapterItem> items) { if (mApps != null && getParent() != null) { mApps.appendSearchResults(items); notifyResultChanged(); } } @Override public void clearSearchResult() { if (getParent() != null && mApps != null) { mApps.setSearchResults(null); notifyResultChanged(); collapseAppsViewHeader(false); mAppsView.onClearSearchResult(); } } @Override public void onAppsUpdated() { mSearchBarController.refreshSearchResult(); } private void collapseAppsViewHeader(boolean collapse) { FloatingHeaderView header = mAppsView.getFloatingHeaderView(); if (header != null) { header.setCollapsed(collapse); } } private void notifyResultChanged() { if (mOnResultsChanged != null) { mOnResultsChanged.run(); } mAppsView.onSearchResultsChanged(); } @Override protected void onFocusChanged(boolean focused, int direction, Rect previouslyFocusedRect) { // TODO: Consider animating the state transition here if (focused) { // Getting focus will open the keyboard. Go to the all-apps state, so that the input // box is at the top and there is enough space below to show search results. Launcher.getLauncher(getContext()).getStateManager().goToState(ALL_APPS, false); } super.onFocusChanged(focused, direction, previouslyFocusedRect); } } Loading
quickstep/res/layout/fallback_search_input.xml 0 → 100644 +35 −0 Original line number Diff line number Diff line <?xml version="1.0" encoding="utf-8"?> <!-- Copyright (C) 2020 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.search.FallbackSearchInputView xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_gravity="center_vertical" android:layout_marginLeft="48dp" android:layout_marginRight="48dp" android:background="@android:color/transparent" android:focusableInTouchMode="true" android:gravity="start|center_vertical" android:inputType="textNoSuggestions" android:imeOptions="actionSearch|flagNoExtractUi" android:maxLines="1" android:privateImeOptions="bc_search" android:scrollHorizontally="true" android:singleLine="true" android:textColor="?android:attr/textColorSecondary" android:textColorHint="?android:attr/textColorTertiary" android:textSize="16sp" /> No newline at end of file
quickstep/res/layout/search_edu_view.xml 0 → 100644 +73 −0 Original line number Diff line number Diff line <?xml version="1.0" encoding="utf-8"?><!-- Copyright (C) 2008 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.search.DeviceSearchEdu xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_gravity="center_horizontal" android:orientation="vertical"> <FrameLayout android:layout_height="wrap_content" android:id="@+id/search_box_wrapper" android:layout_width="match_parent"> <include layout="@layout/fallback_search_input" android:id="@+id/mock_search_box" /> </FrameLayout> <LinearLayout android:layout_height="wrap_content" android:id="@+id/edu_wrapper" android:padding="24dp" android:layout_marginTop="40dp" android:orientation="vertical" android:layout_width="match_parent"> <TextView style="@style/TextHeadline" android:layout_width="match_parent" android:gravity="center" android:textSize="24sp" android:textColor="?android:attr/textColorPrimary" android:layout_height="wrap_content" android:text="@string/search_edu_primary" /> <TextView style="@style/TextHeadline" android:layout_width="match_parent" android:gravity="center" android:textSize="18sp" android:layout_marginTop="30dp" android:textColor="?android:attr/textColorPrimary" android:layout_height="wrap_content" android:text="@string/search_edu_secondary" /> <Button android:id="@+id/dismiss_edu" android:layout_width="wrap_content" android:layout_marginTop="@dimen/dynamic_grid_edge_margin" android:background="?android:attr/selectableItemBackground" android:layout_height="wrap_content" android:textColor="?android:attr/textColorPrimary" android:gravity="center" android:layout_gravity="center" android:text="@string/search_edu_dismiss" /> </LinearLayout> </com.android.launcher3.search.DeviceSearchEdu> No newline at end of file
quickstep/res/values/strings.xml +9 −0 Original line number Diff line number Diff line Loading @@ -93,6 +93,15 @@ <!-- content description for hotseat items --> <string name="hotseat_prediction_content_description">Predicted app: <xliff:g id="title" example="Chrome">%1$s</xliff:g></string> <!-- primary educational text shown for first time search users --> <string name="search_edu_primary">Search your phone for apps, people, settings and more!</string> <!-- secondary educational text shown for first time search users --> <string name="search_edu_secondary">Tap keyboard search button to launch the first search result.</string> <!-- Dismiss button string for search education view --> <string name="search_edu_dismiss">Got it.</string> <!-- Title shown during interactive part of Back gesture tutorial for right edge. [CHAR LIMIT=30] --> <string name="back_gesture_tutorial_playground_title_swipe_inward_right_edge" translatable="false">Try the back gesture</string> <!-- Subtitle shown during interactive parts of Back gesture tutorial for right edge. [CHAR LIMIT=60] --> Loading
quickstep/src/com/android/launcher3/search/DeviceSearchEdu.java 0 → 100644 +221 −0 Original line number Diff line number Diff line /* * Copyright (C) 2021 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.search; import static com.android.launcher3.util.OnboardingPrefs.SEARCH_EDU_SEEN; import android.animation.PropertyValuesHolder; import android.content.Context; import android.graphics.Rect; import android.text.Editable; import android.text.TextWatcher; import android.util.AttributeSet; import android.view.KeyEvent; import android.view.LayoutInflater; import android.view.View; import android.view.inputmethod.InputMethodManager; import android.widget.EditText; import android.widget.TextView; import androidx.core.graphics.ColorUtils; import com.android.launcher3.AbstractFloatingView; import com.android.launcher3.Insettable; import com.android.launcher3.Launcher; import com.android.launcher3.LauncherState; import com.android.launcher3.R; import com.android.launcher3.anim.Interpolators; import com.android.launcher3.statemanager.StateManager; import com.android.launcher3.util.Themes; import com.android.launcher3.views.AbstractSlideInView; /** * Feature education for on-device Search. Shown the first time user opens AllApps Search */ public class DeviceSearchEdu extends AbstractSlideInView implements StateManager.StateListener<LauncherState>, TextWatcher, Insettable, TextView.OnEditorActionListener { private static final long ANIMATION_DURATION = 350; private static final int ANIMATION_CONTENT_TRANSLATION = 200; private EditText mEduInput; private View mInputWrapper; private EditText mSearchInput; private boolean mSwitchFocusOnDismiss; public DeviceSearchEdu(Context context) { this(context, null, 0); } public DeviceSearchEdu(Context context, AttributeSet attrs) { this(context, attrs, 0); } public DeviceSearchEdu(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } private void close(boolean animate, boolean markAsSeen) { handleClose(animate); if (markAsSeen) { mLauncher.getOnboardingPrefs().markChecked(SEARCH_EDU_SEEN); } } @Override protected void handleClose(boolean animate) { handleClose(animate, ANIMATION_DURATION); mLauncher.getStateManager().removeStateListener(this); } @Override protected boolean isOfType(int type) { return false; } @Override protected void onFinishInflate() { super.onFinishInflate(); mSearchInput = mLauncher.getAppsView().getSearchUiManager().getEditText(); mInputWrapper = findViewById(R.id.search_box_wrapper); mContent = findViewById(R.id.edu_wrapper); mEduInput = findViewById(R.id.mock_search_box); mEduInput.setHint(R.string.all_apps_on_device_search_bar_hint); mEduInput.addTextChangedListener(this); if (mSearchInput != null) { mEduInput.getLayoutParams().height = mSearchInput.getHeight(); mEduInput.setOnEditorActionListener(this); } else { mEduInput.setVisibility(INVISIBLE); } findViewById(R.id.dismiss_edu).setOnClickListener((view) -> { mSwitchFocusOnDismiss = true; close(true, true); }); } private void showInternal() { mLauncher.getStateManager().addStateListener(this); AbstractFloatingView.closeAllOpenViews(mLauncher); attachToContainer(); if (mSearchInput != null) { Rect r = mLauncher.getViewBounds(mSearchInput); mEduInput.requestFocus(); InputMethodManager imm = mLauncher.getSystemService(InputMethodManager.class); imm.showSoftInput(mEduInput, InputMethodManager.SHOW_IMPLICIT); ((LayoutParams) mInputWrapper.getLayoutParams()).setMargins(0, r.top, 0, 0); } animateOpen(); } @Override protected int getScrimColor(Context context) { return ColorUtils.setAlphaComponent(Themes.getAttrColor(context, R.attr.allAppsScrimColor), 230); } protected void setTranslationShift(float translationShift) { mTranslationShift = translationShift; mContent.setAlpha(getBoxedProgress(1 - mTranslationShift, .25f, 1)); mContent.setTranslationY(ANIMATION_CONTENT_TRANSLATION * translationShift); if (mColorScrim != null) { mColorScrim.setAlpha(getBoxedProgress(1 - mTranslationShift, 0, .75f)); } } /** * Given input [0-1], returns progress within bounds [min,max] allowing for staged animations */ private float getBoxedProgress(float input, float min, float max) { if (input < min) return 0; if (input > max) return 1; return (input - min) / (max - min); } private void animateOpen() { if (mIsOpen || mOpenCloseAnimator.isRunning()) { return; } mIsOpen = true; mOpenCloseAnimator.setValues( PropertyValuesHolder.ofFloat(TRANSLATION_SHIFT, TRANSLATION_SHIFT_OPENED)); mOpenCloseAnimator.setInterpolator(Interpolators.FAST_OUT_SLOW_IN); mOpenCloseAnimator.setDuration(ANIMATION_DURATION); mOpenCloseAnimator.start(); } /** * Show On-device search education view. */ public static void show(Launcher launcher) { LayoutInflater layoutInflater = LayoutInflater.from(launcher); ((DeviceSearchEdu) layoutInflater.inflate( R.layout.search_edu_view, launcher.getDragLayer(), false)).showInternal(); } @Override public void onStateTransitionStart(LauncherState toState) { close(true, false); } @Override protected void onCloseComplete() { super.onCloseComplete(); if (mSearchInput != null && mSwitchFocusOnDismiss) { mSearchInput.requestFocus(); mSearchInput.setSelection(mSearchInput.getText().length()); } } @Override public void afterTextChanged(Editable editable) { //Does nothing } @Override public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) { //Does nothing } @Override public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) { if (mSearchInput != null) { mSearchInput.setText(charSequence.toString()); mSwitchFocusOnDismiss = true; close(true, true); } } @Override public void setInsets(Rect insets) { } @Override public boolean onEditorAction(TextView textView, int i, KeyEvent keyEvent) { mSearchInput.onEditorAction(i); close(true, true); return true; } }
quickstep/src/com/android/launcher3/search/FallbackSearchInputView.java 0 → 100644 +140 −0 Original line number Diff line number Diff line /* * Copyright (C) 2021 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.search; import static com.android.launcher3.LauncherState.ALL_APPS; import android.content.Context; import android.graphics.Rect; import android.util.AttributeSet; import com.android.launcher3.ExtendedEditText; import com.android.launcher3.Launcher; import com.android.launcher3.allapps.AllAppsContainerView; import com.android.launcher3.allapps.AllAppsGridAdapter.AdapterItem; import com.android.launcher3.allapps.AllAppsStore; import com.android.launcher3.allapps.AlphabeticalAppsList; import com.android.launcher3.allapps.FloatingHeaderView; import com.android.launcher3.allapps.search.AllAppsSearchBarController; import com.android.launcher3.allapps.search.SearchAlgorithm; import java.util.ArrayList; /** * A search view shown in all apps for on device search */ public class FallbackSearchInputView extends ExtendedEditText implements AllAppsSearchBarController.Callbacks, AllAppsStore.OnUpdateListener { private final AllAppsSearchBarController mSearchBarController; private AlphabeticalAppsList mApps; private Runnable mOnResultsChanged; private AllAppsContainerView mAppsView; public FallbackSearchInputView(Context context) { this(context, null); } public FallbackSearchInputView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public FallbackSearchInputView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); mSearchBarController = new AllAppsSearchBarController(); } @Override protected void onAttachedToWindow() { super.onAttachedToWindow(); Launcher.getLauncher(getContext()).getAppsView().getAppsStore().addUpdateListener(this); } @Override protected void onDetachedFromWindow() { super.onDetachedFromWindow(); Launcher.getLauncher(getContext()).getAppsView().getAppsStore().removeUpdateListener(this); } /** * Initializes SearchInput */ public void initialize(AllAppsContainerView appsView, SearchAlgorithm algo, Runnable changed) { mOnResultsChanged = changed; mApps = appsView.getApps(); mAppsView = appsView; mSearchBarController.initialize(algo, this, Launcher.getLauncher(getContext()), this); } @Override public void onSearchResult(String query, ArrayList<AdapterItem> items) { if (mApps != null && getParent() != null) { mApps.setSearchResults(items); notifyResultChanged(); collapseAppsViewHeader(true); mAppsView.setLastSearchQuery(query); } } @Override public void onAppendSearchResult(String query, ArrayList<AdapterItem> items) { if (mApps != null && getParent() != null) { mApps.appendSearchResults(items); notifyResultChanged(); } } @Override public void clearSearchResult() { if (getParent() != null && mApps != null) { mApps.setSearchResults(null); notifyResultChanged(); collapseAppsViewHeader(false); mAppsView.onClearSearchResult(); } } @Override public void onAppsUpdated() { mSearchBarController.refreshSearchResult(); } private void collapseAppsViewHeader(boolean collapse) { FloatingHeaderView header = mAppsView.getFloatingHeaderView(); if (header != null) { header.setCollapsed(collapse); } } private void notifyResultChanged() { if (mOnResultsChanged != null) { mOnResultsChanged.run(); } mAppsView.onSearchResultsChanged(); } @Override protected void onFocusChanged(boolean focused, int direction, Rect previouslyFocusedRect) { // TODO: Consider animating the state transition here if (focused) { // Getting focus will open the keyboard. Go to the all-apps state, so that the input // box is at the top and there is enough space below to show search results. Launcher.getLauncher(getContext()).getStateManager().goToState(ALL_APPS, false); } super.onFocusChanged(focused, direction, previouslyFocusedRect); } }