Loading res/layout/search_result_widget_preview.xml 0 → 100644 +8 −0 Original line number Diff line number Diff line <?xml version="1.0" encoding="utf-8"?> <com.android.launcher3.views.SearchResultWidgetPreview xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:padding="@dimen/dynamic_grid_cell_padding_x" android:layout_height="wrap_content"> <include layout="@layout/widget_cell" android:id="@+id/widget_cell"/> <!-- <include layout="@layout/widget_cell_content" />--> </com.android.launcher3.views.SearchResultWidgetPreview> No newline at end of file src/com/android/launcher3/allapps/AllAppsGridAdapter.java +8 −1 Original line number Diff line number Diff line Loading @@ -92,6 +92,8 @@ public class AllAppsGridAdapter extends public static final int VIEW_TYPE_SEARCH_WIDGET_LIVE = 1 << 15; public static final int VIEW_TYPE_SEARCH_WIDGET_PREVIEW = 1 << 16; // 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 | VIEW_TYPE_SEARCH_ICON; Loading Loading @@ -287,7 +289,8 @@ public class AllAppsGridAdapter extends int viewType = mApps.getAdapterItems().get(position).viewType; if (isIconViewType(viewType)) { return 1 * SPAN_MULTIPLIER; } else if (viewType == VIEW_TYPE_SEARCH_THUMBNAIL) { } else if (viewType == VIEW_TYPE_SEARCH_THUMBNAIL || viewType == VIEW_TYPE_SEARCH_WIDGET_PREVIEW) { return mAppsPerRow; } else { // Section breaks span the full width Loading Loading @@ -433,6 +436,9 @@ public class AllAppsGridAdapter extends case VIEW_TYPE_SEARCH_WIDGET_LIVE: return new ViewHolder(mLayoutInflater.inflate( R.layout.search_result_widget_live, parent, false)); case VIEW_TYPE_SEARCH_WIDGET_PREVIEW: return new ViewHolder(mLayoutInflater.inflate( R.layout.search_result_widget_preview, parent, false)); default: throw new RuntimeException("Unexpected view type"); } Loading Loading @@ -476,6 +482,7 @@ public class AllAppsGridAdapter extends case VIEW_TYPE_SEARCH_THUMBNAIL: case VIEW_TYPE_SEARCH_SUGGEST: case VIEW_TYPE_SEARCH_WIDGET_LIVE: case VIEW_TYPE_SEARCH_WIDGET_PREVIEW: SearchAdapterItem item = (SearchAdapterItem) mApps.getAdapterItems().get(position); SearchTargetHandler payloadResultView = (SearchTargetHandler) holder.itemView; Loading src/com/android/launcher3/views/SearchResultWidgetPreview.java 0 → 100644 +141 −0 Original line number Diff line number Diff line /* * 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. */ package com.android.launcher3.views; import static com.android.launcher3.util.Executors.MAIN_EXECUTOR; import static com.android.launcher3.util.Executors.MODEL_EXECUTOR; import android.appwidget.AppWidgetProviderInfo; import android.content.Context; import android.graphics.Point; import android.util.AttributeSet; import android.view.View; import android.widget.LinearLayout; import android.widget.Toast; import androidx.annotation.Nullable; import com.android.launcher3.Launcher; import com.android.launcher3.LauncherAppState; import com.android.launcher3.LauncherAppWidgetProviderInfo; import com.android.launcher3.R; import com.android.launcher3.allapps.search.AllAppsSearchBarController; import com.android.launcher3.allapps.search.SearchEventTracker; import com.android.launcher3.dragndrop.DragOptions; import com.android.launcher3.model.WidgetItem; import com.android.launcher3.touch.ItemLongClickListener; import com.android.launcher3.widget.BaseWidgetSheet; import com.android.launcher3.widget.PendingItemDragHelper; import com.android.launcher3.widget.WidgetCell; import com.android.launcher3.widget.WidgetImageView; import com.android.systemui.plugins.shared.SearchTarget; import com.android.systemui.plugins.shared.SearchTargetEvent; /** * displays preview of a widget upon receiving {@link AppWidgetProviderInfo} from Search provider */ public class SearchResultWidgetPreview extends LinearLayout implements AllAppsSearchBarController.SearchTargetHandler, View.OnLongClickListener, View.OnClickListener { public static final String TARGET_TYPE_WIDGET_PREVIEW = "widget_preview"; private final Launcher mLauncher; private final LauncherAppState mAppState; private WidgetCell mWidgetCell; private Toast mWidgetToast; private SearchTarget mSearchTarget; public SearchResultWidgetPreview(Context context) { this(context, null, 0); } public SearchResultWidgetPreview(Context context, @Nullable AttributeSet attrs) { this(context, attrs, 0); } public SearchResultWidgetPreview(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); mLauncher = Launcher.getLauncher(context); mAppState = LauncherAppState.getInstance(context); } @Override protected void onFinishInflate() { super.onFinishInflate(); mWidgetCell = findViewById(R.id.widget_cell); mWidgetCell.setOnLongClickListener(this); mWidgetCell.setOnClickListener(this); } @Override public void applySearchTarget(SearchTarget searchTarget) { if (searchTarget.getExtras() == null || searchTarget.getExtras().getParcelable("provider") == null) { setVisibility(GONE); return; } mSearchTarget = searchTarget; AppWidgetProviderInfo providerInfo = searchTarget.getExtras().getParcelable("provider"); LauncherAppWidgetProviderInfo pInfo = LauncherAppWidgetProviderInfo.fromProviderInfo( getContext(), providerInfo); MODEL_EXECUTOR.post(() -> { WidgetItem widgetItem = new WidgetItem(pInfo, mLauncher.getDeviceProfile().inv, mAppState.getIconCache()); MAIN_EXECUTOR.post(() -> { mWidgetCell.applyFromCellItem(widgetItem, mAppState.getWidgetCache()); mWidgetCell.ensurePreview(); }); }); } @Override public boolean onLongClick(View view) { view.cancelLongPress(); if (!ItemLongClickListener.canStartDrag(mLauncher)) return false; if (mWidgetCell.getTag() == null) return false; WidgetImageView imageView = mWidgetCell.getWidgetView(); if (imageView.getBitmap() == null) { return false; } int[] loc = new int[2]; mLauncher.getDragLayer().getLocationInDragLayer(imageView, loc); new PendingItemDragHelper(mWidgetCell).startDrag( imageView.getBitmapBounds(), imageView.getBitmap().getWidth(), imageView.getWidth(), new Point(loc[0], loc[1]), mLauncher.getAppsView(), new DragOptions()); handleSelection(SearchTargetEvent.LONG_PRESS); return true; } @Override public void onClick(View view) { mWidgetToast = BaseWidgetSheet.showWidgetToast(getContext(), mWidgetToast); handleSelection(SearchTargetEvent.SELECT); } @Override public void handleSelection(int eventType) { SearchEventTracker.INSTANCE.get(getContext()).notifySearchTargetEvent( new SearchTargetEvent.Builder(mSearchTarget, eventType).build()); } } src/com/android/launcher3/widget/BaseWidgetSheet.java +19 −11 Original line number Diff line number Diff line Loading @@ -42,7 +42,7 @@ import com.android.launcher3.views.AbstractSlideInView; /** * Base class for various widgets popup */ abstract class BaseWidgetSheet extends AbstractSlideInView public abstract class BaseWidgetSheet extends AbstractSlideInView implements OnClickListener, OnLongClickListener, DragSource, PopupDataProvider.PopupDataChangeListener { Loading Loading @@ -74,16 +74,7 @@ abstract class BaseWidgetSheet extends AbstractSlideInView @Override public final void onClick(View v) { // Let the user know that they have to long press to add a widget if (mWidgetInstructionToast != null) { mWidgetInstructionToast.cancel(); } CharSequence msg = Utilities.wrapForTts( getContext().getText(R.string.long_press_widget_to_add), getContext().getString(R.string.long_accessible_way_to_add)); mWidgetInstructionToast = Toast.makeText(getContext(), msg, Toast.LENGTH_SHORT); mWidgetInstructionToast.show(); mWidgetInstructionToast = showWidgetToast(getContext(), mWidgetInstructionToast); } @Override Loading Loading @@ -146,4 +137,21 @@ abstract class BaseWidgetSheet extends AbstractSlideInView protected SystemUiController getSystemUiController() { return mLauncher.getSystemUiController(); } /** * Show Widget tap toast prompting user to drag instead */ public static Toast showWidgetToast(Context context, Toast toast) { // Let the user know that they have to long press to add a widget if (toast != null) { toast.cancel(); } CharSequence msg = Utilities.wrapForTts( context.getText(R.string.long_press_widget_to_add), context.getString(R.string.long_accessible_way_to_add)); toast = Toast.makeText(context, msg, Toast.LENGTH_SHORT); toast.show(); return toast; } } Loading
res/layout/search_result_widget_preview.xml 0 → 100644 +8 −0 Original line number Diff line number Diff line <?xml version="1.0" encoding="utf-8"?> <com.android.launcher3.views.SearchResultWidgetPreview xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:padding="@dimen/dynamic_grid_cell_padding_x" android:layout_height="wrap_content"> <include layout="@layout/widget_cell" android:id="@+id/widget_cell"/> <!-- <include layout="@layout/widget_cell_content" />--> </com.android.launcher3.views.SearchResultWidgetPreview> No newline at end of file
src/com/android/launcher3/allapps/AllAppsGridAdapter.java +8 −1 Original line number Diff line number Diff line Loading @@ -92,6 +92,8 @@ public class AllAppsGridAdapter extends public static final int VIEW_TYPE_SEARCH_WIDGET_LIVE = 1 << 15; public static final int VIEW_TYPE_SEARCH_WIDGET_PREVIEW = 1 << 16; // 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 | VIEW_TYPE_SEARCH_ICON; Loading Loading @@ -287,7 +289,8 @@ public class AllAppsGridAdapter extends int viewType = mApps.getAdapterItems().get(position).viewType; if (isIconViewType(viewType)) { return 1 * SPAN_MULTIPLIER; } else if (viewType == VIEW_TYPE_SEARCH_THUMBNAIL) { } else if (viewType == VIEW_TYPE_SEARCH_THUMBNAIL || viewType == VIEW_TYPE_SEARCH_WIDGET_PREVIEW) { return mAppsPerRow; } else { // Section breaks span the full width Loading Loading @@ -433,6 +436,9 @@ public class AllAppsGridAdapter extends case VIEW_TYPE_SEARCH_WIDGET_LIVE: return new ViewHolder(mLayoutInflater.inflate( R.layout.search_result_widget_live, parent, false)); case VIEW_TYPE_SEARCH_WIDGET_PREVIEW: return new ViewHolder(mLayoutInflater.inflate( R.layout.search_result_widget_preview, parent, false)); default: throw new RuntimeException("Unexpected view type"); } Loading Loading @@ -476,6 +482,7 @@ public class AllAppsGridAdapter extends case VIEW_TYPE_SEARCH_THUMBNAIL: case VIEW_TYPE_SEARCH_SUGGEST: case VIEW_TYPE_SEARCH_WIDGET_LIVE: case VIEW_TYPE_SEARCH_WIDGET_PREVIEW: SearchAdapterItem item = (SearchAdapterItem) mApps.getAdapterItems().get(position); SearchTargetHandler payloadResultView = (SearchTargetHandler) holder.itemView; Loading
src/com/android/launcher3/views/SearchResultWidgetPreview.java 0 → 100644 +141 −0 Original line number Diff line number Diff line /* * 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. */ package com.android.launcher3.views; import static com.android.launcher3.util.Executors.MAIN_EXECUTOR; import static com.android.launcher3.util.Executors.MODEL_EXECUTOR; import android.appwidget.AppWidgetProviderInfo; import android.content.Context; import android.graphics.Point; import android.util.AttributeSet; import android.view.View; import android.widget.LinearLayout; import android.widget.Toast; import androidx.annotation.Nullable; import com.android.launcher3.Launcher; import com.android.launcher3.LauncherAppState; import com.android.launcher3.LauncherAppWidgetProviderInfo; import com.android.launcher3.R; import com.android.launcher3.allapps.search.AllAppsSearchBarController; import com.android.launcher3.allapps.search.SearchEventTracker; import com.android.launcher3.dragndrop.DragOptions; import com.android.launcher3.model.WidgetItem; import com.android.launcher3.touch.ItemLongClickListener; import com.android.launcher3.widget.BaseWidgetSheet; import com.android.launcher3.widget.PendingItemDragHelper; import com.android.launcher3.widget.WidgetCell; import com.android.launcher3.widget.WidgetImageView; import com.android.systemui.plugins.shared.SearchTarget; import com.android.systemui.plugins.shared.SearchTargetEvent; /** * displays preview of a widget upon receiving {@link AppWidgetProviderInfo} from Search provider */ public class SearchResultWidgetPreview extends LinearLayout implements AllAppsSearchBarController.SearchTargetHandler, View.OnLongClickListener, View.OnClickListener { public static final String TARGET_TYPE_WIDGET_PREVIEW = "widget_preview"; private final Launcher mLauncher; private final LauncherAppState mAppState; private WidgetCell mWidgetCell; private Toast mWidgetToast; private SearchTarget mSearchTarget; public SearchResultWidgetPreview(Context context) { this(context, null, 0); } public SearchResultWidgetPreview(Context context, @Nullable AttributeSet attrs) { this(context, attrs, 0); } public SearchResultWidgetPreview(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); mLauncher = Launcher.getLauncher(context); mAppState = LauncherAppState.getInstance(context); } @Override protected void onFinishInflate() { super.onFinishInflate(); mWidgetCell = findViewById(R.id.widget_cell); mWidgetCell.setOnLongClickListener(this); mWidgetCell.setOnClickListener(this); } @Override public void applySearchTarget(SearchTarget searchTarget) { if (searchTarget.getExtras() == null || searchTarget.getExtras().getParcelable("provider") == null) { setVisibility(GONE); return; } mSearchTarget = searchTarget; AppWidgetProviderInfo providerInfo = searchTarget.getExtras().getParcelable("provider"); LauncherAppWidgetProviderInfo pInfo = LauncherAppWidgetProviderInfo.fromProviderInfo( getContext(), providerInfo); MODEL_EXECUTOR.post(() -> { WidgetItem widgetItem = new WidgetItem(pInfo, mLauncher.getDeviceProfile().inv, mAppState.getIconCache()); MAIN_EXECUTOR.post(() -> { mWidgetCell.applyFromCellItem(widgetItem, mAppState.getWidgetCache()); mWidgetCell.ensurePreview(); }); }); } @Override public boolean onLongClick(View view) { view.cancelLongPress(); if (!ItemLongClickListener.canStartDrag(mLauncher)) return false; if (mWidgetCell.getTag() == null) return false; WidgetImageView imageView = mWidgetCell.getWidgetView(); if (imageView.getBitmap() == null) { return false; } int[] loc = new int[2]; mLauncher.getDragLayer().getLocationInDragLayer(imageView, loc); new PendingItemDragHelper(mWidgetCell).startDrag( imageView.getBitmapBounds(), imageView.getBitmap().getWidth(), imageView.getWidth(), new Point(loc[0], loc[1]), mLauncher.getAppsView(), new DragOptions()); handleSelection(SearchTargetEvent.LONG_PRESS); return true; } @Override public void onClick(View view) { mWidgetToast = BaseWidgetSheet.showWidgetToast(getContext(), mWidgetToast); handleSelection(SearchTargetEvent.SELECT); } @Override public void handleSelection(int eventType) { SearchEventTracker.INSTANCE.get(getContext()).notifySearchTargetEvent( new SearchTargetEvent.Builder(mSearchTarget, eventType).build()); } }
src/com/android/launcher3/widget/BaseWidgetSheet.java +19 −11 Original line number Diff line number Diff line Loading @@ -42,7 +42,7 @@ import com.android.launcher3.views.AbstractSlideInView; /** * Base class for various widgets popup */ abstract class BaseWidgetSheet extends AbstractSlideInView public abstract class BaseWidgetSheet extends AbstractSlideInView implements OnClickListener, OnLongClickListener, DragSource, PopupDataProvider.PopupDataChangeListener { Loading Loading @@ -74,16 +74,7 @@ abstract class BaseWidgetSheet extends AbstractSlideInView @Override public final void onClick(View v) { // Let the user know that they have to long press to add a widget if (mWidgetInstructionToast != null) { mWidgetInstructionToast.cancel(); } CharSequence msg = Utilities.wrapForTts( getContext().getText(R.string.long_press_widget_to_add), getContext().getString(R.string.long_accessible_way_to_add)); mWidgetInstructionToast = Toast.makeText(getContext(), msg, Toast.LENGTH_SHORT); mWidgetInstructionToast.show(); mWidgetInstructionToast = showWidgetToast(getContext(), mWidgetInstructionToast); } @Override Loading Loading @@ -146,4 +137,21 @@ abstract class BaseWidgetSheet extends AbstractSlideInView protected SystemUiController getSystemUiController() { return mLauncher.getSystemUiController(); } /** * Show Widget tap toast prompting user to drag instead */ public static Toast showWidgetToast(Context context, Toast toast) { // Let the user know that they have to long press to add a widget if (toast != null) { toast.cancel(); } CharSequence msg = Utilities.wrapForTts( context.getText(R.string.long_press_widget_to_add), context.getString(R.string.long_accessible_way_to_add)); toast = Toast.makeText(context, msg, Toast.LENGTH_SHORT); toast.show(); return toast; } }