Loading res/layout/search_result_play_item.xml 0 → 100644 +75 −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.views.SearchResultPlayItem xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:padding="8dp" android:orientation="horizontal"> <View android:id="@+id/icon" android:layout_width="@dimen/deep_shortcut_icon_size" android:layout_height="@dimen/deep_shortcut_icon_size" android:layout_gravity="start|center_vertical" android:background="@drawable/ic_deepshortcut_placeholder" /> <LinearLayout android:layout_width="0dp" android:layout_height="wrap_content" android:layout_gravity="start|center_vertical" android:layout_weight="1" android:orientation="vertical" android:padding="8dp"> <TextView android:id="@+id/title_view" style="@style/TextHeadline" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textAlignment="viewStart" android:textColor="?android:attr/textColorPrimary" android:textSize="16sp" /> <TextView android:id="@+id/detail_0" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textColor="?android:attr/textColorPrimary" /> <TextView android:id="@+id/detail_1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textColor="?android:attr/textColorPrimary" android:visibility="gone" /> <TextView android:id="@+id/detail_2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textColor="?android:attr/textColorPrimary" android:visibility="gone" /> </LinearLayout> <Button android:id="@+id/try_button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="start|center_vertical" android:background="?android:attr/selectableItemBackground" android:text="@string/search_action_try_now"> </Button> </com.android.launcher3.views.SearchResultPlayItem> res/layout/search_section_title.xml +8 −8 Original line number Diff line number Diff line Loading @@ -13,11 +13,11 @@ See the License for the specific language governing permissions and limitations under the License. --> <TextView xmlns:android="http://schemas.android.com/apk/res/android" <com.android.launcher3.views.SearchSectionHeaderView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/section_title" android:textSize="14sp" android:fontFamily="@style/TextHeadline" android:layout_width="wrap_content" android:textColor="?android:attr/textColorPrimary" android:layout_height="wrap_content" android:fontFamily="@style/TextHeadline" android:padding="4dp" android:layout_height="wrap_content"/> No newline at end of file android:textColor="?android:attr/textColorPrimary" android:textSize="14sp" /> No newline at end of file res/values/strings.xml +2 −0 Original line number Diff line number Diff line Loading @@ -70,6 +70,8 @@ <!--All apps Search--> <!-- Section title for apps [CHAR_LIMIT=50] --> <string name="search_corpus_apps">Apps</string> <!-- try instant app action for play search result [CHAR_LIMIT=50 --> <string name="search_action_try_now">Try Now</string> <!-- Popup items --> <!-- Text to display as the header above notifications. [CHAR_LIMIT=30] --> Loading src/com/android/launcher3/allapps/AllAppsContainerView.java +21 −0 Original line number Diff line number Diff line Loading @@ -15,6 +15,8 @@ */ package com.android.launcher3.allapps; import static com.android.launcher3.allapps.AllAppsGridAdapter.AdapterItem; import static com.android.launcher3.allapps.AllAppsGridAdapter.AdapterItemWithPayload; import static com.android.launcher3.logging.LoggerUtils.newContainerTarget; import static com.android.launcher3.model.BgDataModel.Callbacks.FLAG_HAS_SHORTCUT_PERMISSION; import static com.android.launcher3.model.BgDataModel.Callbacks.FLAG_QUIET_MODE_CHANGE_PERMISSION; Loading Loading @@ -527,6 +529,25 @@ public class AllAppsContainerView extends SpringRelativeLayout implements DragSo return mViewPager == null ? getActiveRecyclerView() : mViewPager; } /** * Handles selection on focused view and returns success */ public boolean selectFocusedView(View v) { ItemInfo itemInfo = getHighlightedItemInfo(); if (itemInfo != null) { return mLauncher.startActivitySafely(v, itemInfo.getIntent(), itemInfo); } AdapterItem focusedItem = getActiveRecyclerView().getApps().getFocusedChild(); if (focusedItem instanceof AdapterItemWithPayload) { Runnable onSelection = ((AdapterItemWithPayload) focusedItem).getSelectionHandler(); if (onSelection != null) { onSelection.run(); return true; } } return false; } /** * Returns the ItemInfo of a view that is in focus, ready to be launched by an IME. */ Loading src/com/android/launcher3/allapps/AllAppsGridAdapter.java +114 −11 Original line number Diff line number Diff line Loading @@ -40,10 +40,10 @@ import androidx.recyclerview.widget.RecyclerView; import com.android.launcher3.BaseDraggingActivity; import com.android.launcher3.BubbleTextView; import com.android.launcher3.R; import com.android.launcher3.allapps.AlphabeticalAppsList.AdapterItem; import com.android.launcher3.allapps.search.AllAppsSearchBarController.PayloadResultHandler; import com.android.launcher3.allapps.search.SearchSectionInfo; import com.android.launcher3.model.data.AppInfo; import com.android.launcher3.util.PackageManagerHelper; import com.android.launcher3.views.HeroSearchResultView; import java.util.List; Loading Loading @@ -71,6 +71,8 @@ public class AllAppsGridAdapter extends RecyclerView.Adapter<AllAppsGridAdapter. public static final int VIEW_TYPE_SEARCH_HERO_APP = 1 << 6; public static final int DETAIL_ROW_WITH_BUTTON = 1 << 7; // Common view type masks public static final int VIEW_TYPE_MASK_DIVIDER = VIEW_TYPE_ALL_APPS_DIVIDER; public static final int VIEW_TYPE_MASK_ICON = VIEW_TYPE_ICON; Loading @@ -85,6 +87,108 @@ public class AllAppsGridAdapter extends RecyclerView.Adapter<AllAppsGridAdapter. } } /** * Info about a particular adapter item (can be either section or app) */ public static class AdapterItem { /** Common properties */ // The index of this adapter item in the list public int position; // The type of this item public int viewType; /** App-only properties */ // The section name of this app. Note that there can be multiple items with different // sectionNames in the same section public String sectionName = null; // The row that this item shows up on public int rowIndex; // The index of this app in the row public int rowAppIndex; // The associated AppInfo for the app public AppInfo appInfo = null; // The index of this app not including sections public int appIndex = -1; // Search section associated to result public SearchSectionInfo searchSectionInfo = null; /** * Factory method for AppIcon AdapterItem */ public static AdapterItem asApp(int pos, String sectionName, AppInfo appInfo, int appIndex) { AdapterItem item = new AdapterItem(); item.viewType = VIEW_TYPE_ICON; item.position = pos; item.sectionName = sectionName; item.appInfo = appInfo; item.appIndex = appIndex; return item; } /** * Factory method for empty search results view */ public static AdapterItem asEmptySearch(int pos) { AdapterItem item = new AdapterItem(); item.viewType = VIEW_TYPE_EMPTY_SEARCH; item.position = pos; return item; } /** * Factory method for a dividerView in AllAppsSearch */ public static AdapterItem asAllAppsDivider(int pos) { AdapterItem item = new AdapterItem(); item.viewType = VIEW_TYPE_ALL_APPS_DIVIDER; item.position = pos; return item; } /** * Factory method for a market search button */ public static AdapterItem asMarketSearch(int pos) { AdapterItem item = new AdapterItem(); item.viewType = VIEW_TYPE_SEARCH_MARKET; item.position = pos; return item; } boolean isCountedForAccessibility() { return viewType == VIEW_TYPE_ICON || viewType == VIEW_TYPE_SEARCH_HERO_APP || viewType == DETAIL_ROW_WITH_BUTTON; } } /** * Extension of AdapterItem that contains an extra payload specific to item * @param <T> Play load Type */ public static class AdapterItemWithPayload<T> extends AdapterItem { private T mPayload; private Runnable mSelectionHandler; public AdapterItemWithPayload(T payload, int type) { mPayload = payload; viewType = type; } public void setSelectionHandler(Runnable runnable) { mSelectionHandler = runnable; } public Runnable getSelectionHandler() { return mSelectionHandler; } public T getPayload() { return mPayload; } } /** * A subclass of GridLayoutManager that overrides accessibility values during app search. */ Loading Loading @@ -286,6 +390,9 @@ public class AllAppsGridAdapter extends RecyclerView.Adapter<AllAppsGridAdapter. case VIEW_TYPE_SEARCH_HERO_APP: return new ViewHolder(mLayoutInflater.inflate( R.layout.search_result_hero_app, parent, false)); case DETAIL_ROW_WITH_BUTTON: return new ViewHolder(mLayoutInflater.inflate( R.layout.search_result_play_item, parent, false)); default: throw new RuntimeException("Unexpected view type"); } Loading Loading @@ -315,15 +422,11 @@ public class AllAppsGridAdapter extends RecyclerView.Adapter<AllAppsGridAdapter. } break; case VIEW_TYPE_SEARCH_CORPUS_TITLE: TextView titleView = (TextView) holder.itemView; titleView.setText(mApps.getAdapterItems().get(position).searchSectionInfo.getTitle( titleView.getContext())); break; case DETAIL_ROW_WITH_BUTTON: case VIEW_TYPE_SEARCH_HERO_APP: HeroSearchResultView heroView = (HeroSearchResultView) holder.itemView; heroView.prepareUsingAdapterItem( (AlphabeticalAppsList.HeroAppAdapterItem) mApps.getAdapterItems().get( position)); PayloadResultHandler payloadResultView = (PayloadResultHandler) holder.itemView; payloadResultView.applyAdapterInfo( (AdapterItemWithPayload) mApps.getAdapterItems().get(position)); break; case VIEW_TYPE_ALL_APPS_DIVIDER: // nothing to do Loading @@ -344,7 +447,7 @@ public class AllAppsGridAdapter extends RecyclerView.Adapter<AllAppsGridAdapter. @Override public int getItemViewType(int position) { AlphabeticalAppsList.AdapterItem item = mApps.getAdapterItems().get(position); AdapterItem item = mApps.getAdapterItems().get(position); return item.viewType; } Loading Loading
res/layout/search_result_play_item.xml 0 → 100644 +75 −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.views.SearchResultPlayItem xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:padding="8dp" android:orientation="horizontal"> <View android:id="@+id/icon" android:layout_width="@dimen/deep_shortcut_icon_size" android:layout_height="@dimen/deep_shortcut_icon_size" android:layout_gravity="start|center_vertical" android:background="@drawable/ic_deepshortcut_placeholder" /> <LinearLayout android:layout_width="0dp" android:layout_height="wrap_content" android:layout_gravity="start|center_vertical" android:layout_weight="1" android:orientation="vertical" android:padding="8dp"> <TextView android:id="@+id/title_view" style="@style/TextHeadline" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textAlignment="viewStart" android:textColor="?android:attr/textColorPrimary" android:textSize="16sp" /> <TextView android:id="@+id/detail_0" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textColor="?android:attr/textColorPrimary" /> <TextView android:id="@+id/detail_1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textColor="?android:attr/textColorPrimary" android:visibility="gone" /> <TextView android:id="@+id/detail_2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textColor="?android:attr/textColorPrimary" android:visibility="gone" /> </LinearLayout> <Button android:id="@+id/try_button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="start|center_vertical" android:background="?android:attr/selectableItemBackground" android:text="@string/search_action_try_now"> </Button> </com.android.launcher3.views.SearchResultPlayItem>
res/layout/search_section_title.xml +8 −8 Original line number Diff line number Diff line Loading @@ -13,11 +13,11 @@ See the License for the specific language governing permissions and limitations under the License. --> <TextView xmlns:android="http://schemas.android.com/apk/res/android" <com.android.launcher3.views.SearchSectionHeaderView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/section_title" android:textSize="14sp" android:fontFamily="@style/TextHeadline" android:layout_width="wrap_content" android:textColor="?android:attr/textColorPrimary" android:layout_height="wrap_content" android:fontFamily="@style/TextHeadline" android:padding="4dp" android:layout_height="wrap_content"/> No newline at end of file android:textColor="?android:attr/textColorPrimary" android:textSize="14sp" /> No newline at end of file
res/values/strings.xml +2 −0 Original line number Diff line number Diff line Loading @@ -70,6 +70,8 @@ <!--All apps Search--> <!-- Section title for apps [CHAR_LIMIT=50] --> <string name="search_corpus_apps">Apps</string> <!-- try instant app action for play search result [CHAR_LIMIT=50 --> <string name="search_action_try_now">Try Now</string> <!-- Popup items --> <!-- Text to display as the header above notifications. [CHAR_LIMIT=30] --> Loading
src/com/android/launcher3/allapps/AllAppsContainerView.java +21 −0 Original line number Diff line number Diff line Loading @@ -15,6 +15,8 @@ */ package com.android.launcher3.allapps; import static com.android.launcher3.allapps.AllAppsGridAdapter.AdapterItem; import static com.android.launcher3.allapps.AllAppsGridAdapter.AdapterItemWithPayload; import static com.android.launcher3.logging.LoggerUtils.newContainerTarget; import static com.android.launcher3.model.BgDataModel.Callbacks.FLAG_HAS_SHORTCUT_PERMISSION; import static com.android.launcher3.model.BgDataModel.Callbacks.FLAG_QUIET_MODE_CHANGE_PERMISSION; Loading Loading @@ -527,6 +529,25 @@ public class AllAppsContainerView extends SpringRelativeLayout implements DragSo return mViewPager == null ? getActiveRecyclerView() : mViewPager; } /** * Handles selection on focused view and returns success */ public boolean selectFocusedView(View v) { ItemInfo itemInfo = getHighlightedItemInfo(); if (itemInfo != null) { return mLauncher.startActivitySafely(v, itemInfo.getIntent(), itemInfo); } AdapterItem focusedItem = getActiveRecyclerView().getApps().getFocusedChild(); if (focusedItem instanceof AdapterItemWithPayload) { Runnable onSelection = ((AdapterItemWithPayload) focusedItem).getSelectionHandler(); if (onSelection != null) { onSelection.run(); return true; } } return false; } /** * Returns the ItemInfo of a view that is in focus, ready to be launched by an IME. */ Loading
src/com/android/launcher3/allapps/AllAppsGridAdapter.java +114 −11 Original line number Diff line number Diff line Loading @@ -40,10 +40,10 @@ import androidx.recyclerview.widget.RecyclerView; import com.android.launcher3.BaseDraggingActivity; import com.android.launcher3.BubbleTextView; import com.android.launcher3.R; import com.android.launcher3.allapps.AlphabeticalAppsList.AdapterItem; import com.android.launcher3.allapps.search.AllAppsSearchBarController.PayloadResultHandler; import com.android.launcher3.allapps.search.SearchSectionInfo; import com.android.launcher3.model.data.AppInfo; import com.android.launcher3.util.PackageManagerHelper; import com.android.launcher3.views.HeroSearchResultView; import java.util.List; Loading Loading @@ -71,6 +71,8 @@ public class AllAppsGridAdapter extends RecyclerView.Adapter<AllAppsGridAdapter. public static final int VIEW_TYPE_SEARCH_HERO_APP = 1 << 6; public static final int DETAIL_ROW_WITH_BUTTON = 1 << 7; // Common view type masks public static final int VIEW_TYPE_MASK_DIVIDER = VIEW_TYPE_ALL_APPS_DIVIDER; public static final int VIEW_TYPE_MASK_ICON = VIEW_TYPE_ICON; Loading @@ -85,6 +87,108 @@ public class AllAppsGridAdapter extends RecyclerView.Adapter<AllAppsGridAdapter. } } /** * Info about a particular adapter item (can be either section or app) */ public static class AdapterItem { /** Common properties */ // The index of this adapter item in the list public int position; // The type of this item public int viewType; /** App-only properties */ // The section name of this app. Note that there can be multiple items with different // sectionNames in the same section public String sectionName = null; // The row that this item shows up on public int rowIndex; // The index of this app in the row public int rowAppIndex; // The associated AppInfo for the app public AppInfo appInfo = null; // The index of this app not including sections public int appIndex = -1; // Search section associated to result public SearchSectionInfo searchSectionInfo = null; /** * Factory method for AppIcon AdapterItem */ public static AdapterItem asApp(int pos, String sectionName, AppInfo appInfo, int appIndex) { AdapterItem item = new AdapterItem(); item.viewType = VIEW_TYPE_ICON; item.position = pos; item.sectionName = sectionName; item.appInfo = appInfo; item.appIndex = appIndex; return item; } /** * Factory method for empty search results view */ public static AdapterItem asEmptySearch(int pos) { AdapterItem item = new AdapterItem(); item.viewType = VIEW_TYPE_EMPTY_SEARCH; item.position = pos; return item; } /** * Factory method for a dividerView in AllAppsSearch */ public static AdapterItem asAllAppsDivider(int pos) { AdapterItem item = new AdapterItem(); item.viewType = VIEW_TYPE_ALL_APPS_DIVIDER; item.position = pos; return item; } /** * Factory method for a market search button */ public static AdapterItem asMarketSearch(int pos) { AdapterItem item = new AdapterItem(); item.viewType = VIEW_TYPE_SEARCH_MARKET; item.position = pos; return item; } boolean isCountedForAccessibility() { return viewType == VIEW_TYPE_ICON || viewType == VIEW_TYPE_SEARCH_HERO_APP || viewType == DETAIL_ROW_WITH_BUTTON; } } /** * Extension of AdapterItem that contains an extra payload specific to item * @param <T> Play load Type */ public static class AdapterItemWithPayload<T> extends AdapterItem { private T mPayload; private Runnable mSelectionHandler; public AdapterItemWithPayload(T payload, int type) { mPayload = payload; viewType = type; } public void setSelectionHandler(Runnable runnable) { mSelectionHandler = runnable; } public Runnable getSelectionHandler() { return mSelectionHandler; } public T getPayload() { return mPayload; } } /** * A subclass of GridLayoutManager that overrides accessibility values during app search. */ Loading Loading @@ -286,6 +390,9 @@ public class AllAppsGridAdapter extends RecyclerView.Adapter<AllAppsGridAdapter. case VIEW_TYPE_SEARCH_HERO_APP: return new ViewHolder(mLayoutInflater.inflate( R.layout.search_result_hero_app, parent, false)); case DETAIL_ROW_WITH_BUTTON: return new ViewHolder(mLayoutInflater.inflate( R.layout.search_result_play_item, parent, false)); default: throw new RuntimeException("Unexpected view type"); } Loading Loading @@ -315,15 +422,11 @@ public class AllAppsGridAdapter extends RecyclerView.Adapter<AllAppsGridAdapter. } break; case VIEW_TYPE_SEARCH_CORPUS_TITLE: TextView titleView = (TextView) holder.itemView; titleView.setText(mApps.getAdapterItems().get(position).searchSectionInfo.getTitle( titleView.getContext())); break; case DETAIL_ROW_WITH_BUTTON: case VIEW_TYPE_SEARCH_HERO_APP: HeroSearchResultView heroView = (HeroSearchResultView) holder.itemView; heroView.prepareUsingAdapterItem( (AlphabeticalAppsList.HeroAppAdapterItem) mApps.getAdapterItems().get( position)); PayloadResultHandler payloadResultView = (PayloadResultHandler) holder.itemView; payloadResultView.applyAdapterInfo( (AdapterItemWithPayload) mApps.getAdapterItems().get(position)); break; case VIEW_TYPE_ALL_APPS_DIVIDER: // nothing to do Loading @@ -344,7 +447,7 @@ public class AllAppsGridAdapter extends RecyclerView.Adapter<AllAppsGridAdapter. @Override public int getItemViewType(int position) { AlphabeticalAppsList.AdapterItem item = mApps.getAdapterItems().get(position); AdapterItem item = mApps.getAdapterItems().get(position); return item.viewType; } Loading