mirror of
https://github.com/LawnchairLauncher/lawnchair.git
synced 2026-02-17 17:48:20 +00:00
Consolidate Hero search result with SearchResultIconRow
With this, we can now show app title and support drag/drop for shortcut results. Bug: 172245107 preview: https://drive.google.com/file/d/1A4eKKTDPht-MDbfA2VFI3OuAO36fc3AS/view?usp=sharing Change-Id: Icf94a2d23b44bfe5527aea71e27178906e5deb3e
This commit is contained in:
@@ -1,74 +0,0 @@
|
||||
<?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.HeroSearchResultView
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:launcher="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:gravity="center_vertical"
|
||||
android:padding="@dimen/dynamic_grid_edge_margin">
|
||||
|
||||
<FrameLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_weight="1">
|
||||
<com.android.launcher3.BubbleTextView
|
||||
android:id="@+id/bubble_text"
|
||||
style="@style/BaseIcon"
|
||||
android:drawablePadding="@dimen/dynamic_grid_icon_drawable_padding"
|
||||
android:gravity="start|center_vertical"
|
||||
android:textAlignment="viewStart"
|
||||
android:textColor="?android:attr/textColorPrimary"
|
||||
android:textSize="16sp"
|
||||
android:layout_height="wrap_content"
|
||||
launcher:iconDisplay="hero_app"
|
||||
launcher:layoutHorizontal="true"/>
|
||||
|
||||
<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"/>
|
||||
</FrameLayout>
|
||||
|
||||
<com.android.launcher3.BubbleTextView
|
||||
android:id="@+id/shortcut_0"
|
||||
style="@style/BaseIcon"
|
||||
android:layout_width="@dimen/deep_shortcut_icon_size"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="start|center_vertical"
|
||||
android:textAlignment="center"
|
||||
launcher:iconDisplay="shortcut_popup"
|
||||
android:textSize="12sp"
|
||||
launcher:iconSizeOverride="@dimen/deep_shortcut_icon_size"
|
||||
launcher:layoutHorizontal="false"/>
|
||||
|
||||
<com.android.launcher3.BubbleTextView
|
||||
android:id="@+id/shortcut_1"
|
||||
style="@style/BaseIcon"
|
||||
android:layout_width="@dimen/deep_shortcut_icon_size"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="start|center_vertical"
|
||||
android:textAlignment="center"
|
||||
launcher:iconDisplay="shortcut_popup"
|
||||
android:textSize="12sp"
|
||||
launcher:iconSizeOverride="@dimen/deep_shortcut_icon_size"
|
||||
launcher:layoutHorizontal="false"/>
|
||||
|
||||
</com.android.launcher3.views.HeroSearchResultView>
|
||||
@@ -1,4 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?><!-- Copyright (C) 2020 The Android Open Source Projectza
|
||||
<?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.
|
||||
@@ -14,18 +14,61 @@
|
||||
-->
|
||||
<com.android.launcher3.views.SearchResultIconRow xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:launcher="http://schemas.android.com/apk/res-auto"
|
||||
style="@style/BaseIcon"
|
||||
android:orientation="horizontal"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:drawablePadding="@dimen/dynamic_grid_icon_drawable_padding"
|
||||
android:gravity="start|center_vertical"
|
||||
android:textAlignment="viewStart"
|
||||
android:textColor="?android:attr/textColorPrimary"
|
||||
android:textSize="16sp"
|
||||
android:padding="@dimen/dynamic_grid_edge_margin"
|
||||
launcher:iconDisplay="hero_app"
|
||||
launcher:layoutHorizontal="true"
|
||||
>
|
||||
android:padding="@dimen/dynamic_grid_edge_margin">
|
||||
|
||||
<com.android.launcher3.views.SearchResultIcon
|
||||
android:layout_width="wrap_content"
|
||||
android:id="@+id/icon"
|
||||
launcher:iconDisplay="hero_app"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_weight="1"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="@dimen/dynamic_grid_edge_margin"
|
||||
android:orientation="vertical"
|
||||
android:layout_gravity="center_vertical">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:id="@id/title"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="start|center_vertical"
|
||||
android:textAlignment="viewStart"
|
||||
android:textColor="?android:attr/textColorPrimary"
|
||||
android:textSize="@dimen/settings_hero_title_size" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:id="@+id/desc"
|
||||
android:textColor="?android:attr/textColorTertiary"
|
||||
android:textSize="@dimen/settings_hero_subtitle_size"
|
||||
android:layout_height="wrap_content" />
|
||||
</LinearLayout>
|
||||
|
||||
<com.android.launcher3.BubbleTextView
|
||||
android:id="@+id/shortcut_0"
|
||||
style="@style/BaseIcon"
|
||||
android:layout_width="@dimen/deep_shortcut_icon_size"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="start|center_vertical"
|
||||
launcher:iconDisplay="shortcut_popup"
|
||||
android:textSize="@dimen/settings_hero_subtitle_size"
|
||||
launcher:iconSizeOverride="@dimen/deep_shortcut_icon_size"
|
||||
launcher:layoutHorizontal="false" />
|
||||
|
||||
<com.android.launcher3.BubbleTextView
|
||||
android:id="@+id/shortcut_1"
|
||||
style="@style/BaseIcon"
|
||||
android:layout_width="@dimen/deep_shortcut_icon_size"
|
||||
android:layout_height="match_parent"
|
||||
launcher:iconDisplay="shortcut_popup"
|
||||
android:textSize="@dimen/settings_hero_inline_button_size"
|
||||
launcher:iconSizeOverride="@dimen/deep_shortcut_icon_size"
|
||||
launcher:layoutHorizontal="false" />
|
||||
|
||||
</com.android.launcher3.views.SearchResultIconRow>
|
||||
@@ -12,7 +12,7 @@
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
<com.android.launcher3.views.SearchResultIconRow xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<com.android.launcher3.views.SearchResultSuggestion xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:launcher="http://schemas.android.com/apk/res-auto"
|
||||
style="@style/BaseIcon"
|
||||
android:layout_width="match_parent"
|
||||
@@ -26,10 +26,9 @@
|
||||
launcher:iconDisplay="hero_app"
|
||||
android:drawableTint="?android:attr/textColorPrimary"
|
||||
launcher:customIcon="@drawable/ic_allapps_search"
|
||||
launcher:iconSizeOverride="48dp"
|
||||
launcher:iconSizeOverride="24dp"
|
||||
launcher:matchTextInsetWithQuery="true"
|
||||
launcher:layoutHorizontal="true"
|
||||
android:drawablePadding="@dimen/dynamic_grid_icon_drawable_padding"
|
||||
>
|
||||
android:drawablePadding="@dimen/dynamic_grid_icon_drawable_padding">
|
||||
|
||||
</com.android.launcher3.views.SearchResultIconRow>
|
||||
</com.android.launcher3.views.SearchResultSuggestion>
|
||||
@@ -1,5 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
<?xml version="1.0" encoding="utf-8"?><!--
|
||||
/* Copyright 2008, The Android Open Source Project
|
||||
**
|
||||
** Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@@ -30,13 +29,13 @@
|
||||
<attr name="isWorkspaceDarkText" format="boolean" />
|
||||
<attr name="workspaceTextColor" format="color" />
|
||||
<attr name="workspaceShadowColor" format="color" />
|
||||
<attr name="workspaceAmbientShadowColor" format="color"/>
|
||||
<attr name="workspaceAmbientShadowColor" format="color" />
|
||||
<attr name="workspaceKeyShadowColor" format="color" />
|
||||
<attr name="workspaceStatusBarScrim" format="reference" />
|
||||
<attr name="widgetsTheme" format="reference" />
|
||||
<attr name="loadingIconColor" format="color" />
|
||||
<attr name="iconOnlyShortcutColor" format="color"/>
|
||||
<attr name="eduHalfSheetBGColor" format="color"/>
|
||||
<attr name="iconOnlyShortcutColor" format="color" />
|
||||
<attr name="eduHalfSheetBGColor" format="color" />
|
||||
|
||||
<attr name="folderDotColor" format="color" />
|
||||
<attr name="folderFillColor" format="color" />
|
||||
@@ -69,13 +68,12 @@
|
||||
<attr name="folderDotColor" />
|
||||
</declare-styleable>
|
||||
|
||||
<declare-styleable name="SearchResultIconRow">
|
||||
<declare-styleable name="SearchResultSuggestion">
|
||||
<attr name="customIcon" format="reference" />
|
||||
<attr name="matchTextInsetWithQuery" format="boolean" />
|
||||
</declare-styleable>
|
||||
|
||||
|
||||
|
||||
<declare-styleable name="ShadowInfo">
|
||||
<attr name="ambientShadowColor" format="color" />
|
||||
<attr name="ambientShadowBlur" format="dimension" />
|
||||
@@ -167,7 +165,7 @@
|
||||
<attr name="android:src" />
|
||||
<attr name="android:shadowColor" />
|
||||
<attr name="android:elevation" />
|
||||
<attr name="darkTintColor" format="color"/>
|
||||
<attr name="darkTintColor" format="color" />
|
||||
</declare-styleable>
|
||||
|
||||
<declare-styleable name="RecyclerViewFastScroller">
|
||||
|
||||
@@ -248,4 +248,9 @@
|
||||
<!-- Onboarding bottomsheet related -->
|
||||
<dimen name="bottom_sheet_edu_padding">24dp</dimen>
|
||||
|
||||
<!-- Search related -->
|
||||
<dimen name="settings_hero_title_size">16sp</dimen>
|
||||
<dimen name="settings_hero_subtitle_size">15sp</dimen>
|
||||
<dimen name="settings_hero_inline_button_size">12sp</dimen>
|
||||
|
||||
</resources>
|
||||
|
||||
@@ -75,8 +75,6 @@ public class AllAppsGridAdapter extends
|
||||
|
||||
public static final int VIEW_TYPE_SEARCH_CORPUS_TITLE = 1 << 5;
|
||||
|
||||
public static final int VIEW_TYPE_SEARCH_HERO_APP = 1 << 6;
|
||||
|
||||
public static final int VIEW_TYPE_SEARCH_ROW_WITH_BUTTON = 1 << 7;
|
||||
|
||||
public static final int VIEW_TYPE_SEARCH_ROW = 1 << 8;
|
||||
@@ -178,7 +176,6 @@ public class AllAppsGridAdapter extends
|
||||
|
||||
boolean isCountedForAccessibility() {
|
||||
return viewType == VIEW_TYPE_ICON
|
||||
|| viewType == VIEW_TYPE_SEARCH_HERO_APP
|
||||
|| viewType == VIEW_TYPE_SEARCH_ROW_WITH_BUTTON
|
||||
|| viewType == VIEW_TYPE_SEARCH_SLICE
|
||||
|| viewType == VIEW_TYPE_SEARCH_ROW
|
||||
@@ -411,9 +408,6 @@ public class AllAppsGridAdapter extends
|
||||
case VIEW_TYPE_SEARCH_CORPUS_TITLE:
|
||||
return new ViewHolder(
|
||||
mLayoutInflater.inflate(R.layout.search_section_title, parent, false));
|
||||
case VIEW_TYPE_SEARCH_HERO_APP:
|
||||
return new ViewHolder(mLayoutInflater.inflate(
|
||||
R.layout.search_result_hero_app, parent, false));
|
||||
case VIEW_TYPE_SEARCH_ROW_WITH_BUTTON:
|
||||
return new ViewHolder(mLayoutInflater.inflate(
|
||||
R.layout.search_result_play_item, parent, false));
|
||||
@@ -478,7 +472,6 @@ public class AllAppsGridAdapter extends
|
||||
break;
|
||||
case VIEW_TYPE_SEARCH_CORPUS_TITLE:
|
||||
case VIEW_TYPE_SEARCH_ROW_WITH_BUTTON:
|
||||
case VIEW_TYPE_SEARCH_HERO_APP:
|
||||
case VIEW_TYPE_SEARCH_ROW:
|
||||
case VIEW_TYPE_SEARCH_ICON:
|
||||
case VIEW_TYPE_SEARCH_ICON_ROW:
|
||||
|
||||
@@ -96,6 +96,8 @@ public class ItemClickHandler {
|
||||
if (v instanceof PendingAppWidgetHostView) {
|
||||
onClickPendingWidget((PendingAppWidgetHostView) v, launcher);
|
||||
}
|
||||
} else if (tag instanceof RemoteActionItemInfo) {
|
||||
onClickRemoteAction(launcher, (RemoteActionItemInfo) tag);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,209 +0,0 @@
|
||||
/*
|
||||
* 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.LauncherSettings.Favorites.CONTAINER_ALL_APPS;
|
||||
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
|
||||
import static com.android.launcher3.util.Executors.MODEL_EXECUTOR;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.pm.ShortcutInfo;
|
||||
import android.graphics.Point;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Pair;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.LinearLayout;
|
||||
|
||||
import com.android.launcher3.BubbleTextView;
|
||||
import com.android.launcher3.DeviceProfile;
|
||||
import com.android.launcher3.DragSource;
|
||||
import com.android.launcher3.DropTarget;
|
||||
import com.android.launcher3.Launcher;
|
||||
import com.android.launcher3.LauncherAppState;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.allapps.AllAppsStore;
|
||||
import com.android.launcher3.allapps.search.AllAppsSearchBarController.SearchTargetHandler;
|
||||
import com.android.launcher3.allapps.search.SearchEventTracker;
|
||||
import com.android.launcher3.dragndrop.DragOptions;
|
||||
import com.android.launcher3.dragndrop.DraggableView;
|
||||
import com.android.launcher3.graphics.DragPreviewProvider;
|
||||
import com.android.launcher3.model.data.AppInfo;
|
||||
import com.android.launcher3.model.data.ItemInfo;
|
||||
import com.android.launcher3.model.data.ItemInfoWithIcon;
|
||||
import com.android.launcher3.model.data.WorkspaceItemInfo;
|
||||
import com.android.launcher3.shortcuts.ShortcutDragPreviewProvider;
|
||||
import com.android.launcher3.touch.ItemLongClickListener;
|
||||
import com.android.launcher3.util.ComponentKey;
|
||||
import com.android.systemui.plugins.shared.SearchTarget;
|
||||
import com.android.systemui.plugins.shared.SearchTargetEvent;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* A view representing a high confidence app search result that includes shortcuts
|
||||
* TODO (sfufa@) consolidate this with SearchResultIconRow
|
||||
*/
|
||||
public class HeroSearchResultView extends LinearLayout implements DragSource, SearchTargetHandler {
|
||||
|
||||
public static final String TARGET_TYPE_HERO_APP = "hero_app";
|
||||
|
||||
public static final int MAX_SHORTCUTS_COUNT = 2;
|
||||
|
||||
private SearchTarget mSearchTarget;
|
||||
private BubbleTextView mBubbleTextView;
|
||||
private View mIconView;
|
||||
private BubbleTextView[] mDeepShortcutTextViews = new BubbleTextView[2];
|
||||
|
||||
|
||||
public HeroSearchResultView(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
public HeroSearchResultView(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
}
|
||||
|
||||
public HeroSearchResultView(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onFinishInflate() {
|
||||
super.onFinishInflate();
|
||||
Launcher launcher = Launcher.getLauncher(getContext());
|
||||
DeviceProfile grid = launcher.getDeviceProfile();
|
||||
mIconView = findViewById(R.id.icon);
|
||||
ViewGroup.LayoutParams iconParams = mIconView.getLayoutParams();
|
||||
iconParams.height = grid.allAppsIconSizePx;
|
||||
iconParams.width = grid.allAppsIconSizePx;
|
||||
|
||||
|
||||
mBubbleTextView = findViewById(R.id.bubble_text);
|
||||
mBubbleTextView.setOnClickListener(view -> {
|
||||
handleSelection(SearchTargetEvent.SELECT);
|
||||
launcher.getItemOnClickListener().onClick(view);
|
||||
});
|
||||
mBubbleTextView.setOnLongClickListener(new HeroItemDragHandler(getContext(), this));
|
||||
|
||||
|
||||
mDeepShortcutTextViews[0] = findViewById(R.id.shortcut_0);
|
||||
mDeepShortcutTextViews[1] = findViewById(R.id.shortcut_1);
|
||||
for (BubbleTextView bubbleTextView : mDeepShortcutTextViews) {
|
||||
bubbleTextView.setLayoutParams(
|
||||
new LinearLayout.LayoutParams(grid.allAppsIconSizePx,
|
||||
grid.allAppsIconSizePx));
|
||||
bubbleTextView.setOnClickListener(view -> {
|
||||
WorkspaceItemInfo itemInfo = (WorkspaceItemInfo) bubbleTextView.getTag();
|
||||
SearchTargetEvent event = new SearchTargetEvent.Builder(mSearchTarget,
|
||||
SearchTargetEvent.CHILD_SELECT).setShortcutPosition(itemInfo.rank).build();
|
||||
SearchEventTracker.getInstance(getContext()).notifySearchTargetEvent(event);
|
||||
launcher.getItemOnClickListener().onClick(view);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applySearchTarget(SearchTarget searchTarget) {
|
||||
mSearchTarget = searchTarget;
|
||||
AllAppsStore apps = Launcher.getLauncher(getContext()).getAppsView().getAppsStore();
|
||||
AppInfo appInfo = apps.getApp(new ComponentKey(searchTarget.getComponentName(),
|
||||
searchTarget.getUserHandle()));
|
||||
List<ShortcutInfo> infos = mSearchTarget.getShortcutInfos();
|
||||
|
||||
ArrayList<Pair<ShortcutInfo, ItemInfoWithIcon>> shortcuts = new ArrayList<>();
|
||||
for (int i = 0; infos != null && i < infos.size() && i < MAX_SHORTCUTS_COUNT; i++) {
|
||||
ShortcutInfo shortcutInfo = infos.get(i);
|
||||
ItemInfoWithIcon si = new WorkspaceItemInfo(shortcutInfo, getContext());
|
||||
si.rank = i;
|
||||
shortcuts.add(new Pair<>(shortcutInfo, si));
|
||||
}
|
||||
|
||||
mBubbleTextView.applyFromApplicationInfo(appInfo);
|
||||
mIconView.setBackground(mBubbleTextView.getIcon());
|
||||
mIconView.setTag(appInfo);
|
||||
LauncherAppState appState = LauncherAppState.getInstance(getContext());
|
||||
for (int i = 0; i < mDeepShortcutTextViews.length; i++) {
|
||||
BubbleTextView shortcutView = mDeepShortcutTextViews[i];
|
||||
mDeepShortcutTextViews[i].setVisibility(shortcuts.size() > i ? VISIBLE : GONE);
|
||||
if (i < shortcuts.size()) {
|
||||
Pair<ShortcutInfo, ItemInfoWithIcon> p = shortcuts.get(i);
|
||||
//apply ItemInfo and prepare view
|
||||
shortcutView.applyFromWorkspaceItem((WorkspaceItemInfo) p.second);
|
||||
MODEL_EXECUTOR.execute(() -> {
|
||||
// load unbadged shortcut in background and update view when icon ready
|
||||
appState.getIconCache().getUnbadgedShortcutIcon(p.second, p.first);
|
||||
MAIN_EXECUTOR.post(() -> shortcutView.reapplyItemInfo(p.second));
|
||||
});
|
||||
}
|
||||
}
|
||||
SearchEventTracker.INSTANCE.get(getContext()).registerWeakHandler(searchTarget, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDropCompleted(View target, DropTarget.DragObject d, boolean success) {
|
||||
mBubbleTextView.setVisibility(VISIBLE);
|
||||
mBubbleTextView.setIconVisible(true);
|
||||
}
|
||||
|
||||
private void setWillDrawIcon(boolean willDraw) {
|
||||
mIconView.setVisibility(willDraw ? View.VISIBLE : View.INVISIBLE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Drag and drop handler for popup items in Launcher activity
|
||||
*/
|
||||
public static class HeroItemDragHandler implements OnLongClickListener {
|
||||
private final Launcher mLauncher;
|
||||
private final HeroSearchResultView mContainer;
|
||||
|
||||
HeroItemDragHandler(Context context, HeroSearchResultView container) {
|
||||
mLauncher = Launcher.getLauncher(context);
|
||||
mContainer = container;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onLongClick(View v) {
|
||||
if (!ItemLongClickListener.canStartDrag(mLauncher)) return false;
|
||||
mContainer.setWillDrawIcon(false);
|
||||
|
||||
DraggableView draggableView = DraggableView.ofType(DraggableView.DRAGGABLE_ICON);
|
||||
WorkspaceItemInfo itemInfo = new WorkspaceItemInfo((AppInfo) v.getTag());
|
||||
itemInfo.container = CONTAINER_ALL_APPS;
|
||||
DragPreviewProvider previewProvider = new ShortcutDragPreviewProvider(
|
||||
mContainer.mIconView, new Point());
|
||||
mLauncher.getWorkspace().beginDragShared(mContainer.mBubbleTextView,
|
||||
draggableView, mContainer, itemInfo, previewProvider, new DragOptions());
|
||||
|
||||
SearchTargetEvent event = new SearchTargetEvent.Builder(mContainer.mSearchTarget,
|
||||
SearchTargetEvent.LONG_PRESS).build();
|
||||
SearchEventTracker.INSTANCE.get(mLauncher).notifySearchTargetEvent(event);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleSelection(int eventType) {
|
||||
ItemInfo itemInfo = (ItemInfo) mBubbleTextView.getTag();
|
||||
if (itemInfo == null) return;
|
||||
Launcher launcher = Launcher.getLauncher(getContext());
|
||||
launcher.startActivitySafely(this, itemInfo.getIntent(), itemInfo);
|
||||
|
||||
SearchEventTracker.INSTANCE.get(getContext()).notifySearchTargetEvent(
|
||||
new SearchTargetEvent.Builder(mSearchTarget, eventType).build());
|
||||
}
|
||||
}
|
||||
@@ -15,16 +15,35 @@
|
||||
*/
|
||||
package com.android.launcher3.views;
|
||||
|
||||
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
|
||||
import static com.android.launcher3.util.Executors.MODEL_EXECUTOR;
|
||||
import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
|
||||
|
||||
import android.app.RemoteAction;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.pm.ShortcutInfo;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Build;
|
||||
import android.os.UserHandle;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import androidx.annotation.UiThread;
|
||||
|
||||
import com.android.launcher3.BubbleTextView;
|
||||
import com.android.launcher3.Launcher;
|
||||
import com.android.launcher3.LauncherAppState;
|
||||
import com.android.launcher3.allapps.AllAppsStore;
|
||||
import com.android.launcher3.allapps.search.AllAppsSearchBarController;
|
||||
import com.android.launcher3.allapps.search.SearchEventTracker;
|
||||
import com.android.launcher3.icons.BitmapInfo;
|
||||
import com.android.launcher3.icons.LauncherIcons;
|
||||
import com.android.launcher3.model.data.AppInfo;
|
||||
import com.android.launcher3.model.data.ItemInfoWithIcon;
|
||||
import com.android.launcher3.model.data.RemoteActionItemInfo;
|
||||
import com.android.launcher3.model.data.WorkspaceItemInfo;
|
||||
import com.android.launcher3.touch.ItemLongClickListener;
|
||||
import com.android.launcher3.util.ComponentKey;
|
||||
import com.android.systemui.plugins.shared.SearchTarget;
|
||||
@@ -39,6 +58,17 @@ public class SearchResultIcon extends BubbleTextView implements
|
||||
|
||||
|
||||
public static final String TARGET_TYPE_APP = "app";
|
||||
public static final String TARGET_TYPE_HERO_APP = "hero_app";
|
||||
public static final String TARGET_TYPE_SHORTCUT = "shortcut";
|
||||
public static final String TARGET_TYPE_REMOTE_ACTION = "remote_action";
|
||||
public static final String TARGET_TYPE_SUGGEST = "suggest";
|
||||
|
||||
public static final String REMOTE_ACTION_SHOULD_START = "should_start_for_result";
|
||||
public static final String REMOTE_ACTION_TOKEN = "action_token";
|
||||
|
||||
|
||||
private static final String[] LONG_PRESS_SUPPORTED_TYPES =
|
||||
new String[]{TARGET_TYPE_APP, TARGET_TYPE_SHORTCUT, TARGET_TYPE_HERO_APP};
|
||||
|
||||
private final Launcher mLauncher;
|
||||
|
||||
@@ -64,26 +94,96 @@ public class SearchResultIcon extends BubbleTextView implements
|
||||
setOnFocusChangeListener(mLauncher.getFocusHandler());
|
||||
setOnClickListener(this);
|
||||
setOnLongClickListener(this);
|
||||
getLayoutParams().height = mLauncher.getDeviceProfile().allAppsCellHeightPx;
|
||||
setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
|
||||
mLauncher.getDeviceProfile().allAppsCellHeightPx));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applySearchTarget(SearchTarget searchTarget) {
|
||||
mSearchTarget = searchTarget;
|
||||
AllAppsStore appsStore = mLauncher.getAppsView().getAppsStore();
|
||||
SearchEventTracker.getInstance(getContext()).registerWeakHandler(mSearchTarget, this);
|
||||
if (searchTarget.getItemType().equals(TARGET_TYPE_APP)) {
|
||||
AppInfo appInfo = appsStore.getApp(new ComponentKey(searchTarget.getComponentName(),
|
||||
searchTarget.getUserHandle()));
|
||||
applyFromApplicationInfo(appInfo);
|
||||
switch (searchTarget.getItemType()) {
|
||||
case TARGET_TYPE_APP:
|
||||
case TARGET_TYPE_HERO_APP:
|
||||
prepareUsingApp(searchTarget.getComponentName(), searchTarget.getUserHandle());
|
||||
break;
|
||||
case TARGET_TYPE_SHORTCUT:
|
||||
prepareUsingShortcutInfo(searchTarget.getShortcutInfos().get(0));
|
||||
break;
|
||||
case TARGET_TYPE_REMOTE_ACTION:
|
||||
case TARGET_TYPE_SUGGEST:
|
||||
prepareUsingRemoteAction(searchTarget.getRemoteAction(),
|
||||
searchTarget.getExtras().getString(REMOTE_ACTION_TOKEN),
|
||||
searchTarget.getExtras().getBoolean(REMOTE_ACTION_SHOULD_START),
|
||||
searchTarget.getItemType().equals(TARGET_TYPE_REMOTE_ACTION));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void prepareUsingApp(ComponentName componentName, UserHandle userHandle) {
|
||||
AllAppsStore appsStore = mLauncher.getAppsView().getAppsStore();
|
||||
AppInfo appInfo = appsStore.getApp(new ComponentKey(componentName, userHandle));
|
||||
applyFromApplicationInfo(appInfo);
|
||||
}
|
||||
|
||||
|
||||
private void prepareUsingShortcutInfo(ShortcutInfo shortcutInfo) {
|
||||
WorkspaceItemInfo workspaceItemInfo = new WorkspaceItemInfo(shortcutInfo, getContext());
|
||||
applyFromWorkspaceItem(workspaceItemInfo);
|
||||
LauncherAppState launcherAppState = LauncherAppState.getInstance(getContext());
|
||||
MODEL_EXECUTOR.execute(() -> {
|
||||
launcherAppState.getIconCache().getShortcutIcon(workspaceItemInfo, shortcutInfo);
|
||||
reapplyItemInfoAsync(workspaceItemInfo);
|
||||
});
|
||||
}
|
||||
|
||||
private void prepareUsingRemoteAction(RemoteAction remoteAction, String token, boolean start,
|
||||
boolean useIconToBadge) {
|
||||
RemoteActionItemInfo itemInfo = new RemoteActionItemInfo(remoteAction, token, start);
|
||||
|
||||
applyFromRemoteActionInfo(itemInfo);
|
||||
if (!loadIconFromResource()) {
|
||||
UI_HELPER_EXECUTOR.post(() -> {
|
||||
// If the Drawable from the remote action is not AdaptiveBitmap, styling will not
|
||||
// work.
|
||||
try (LauncherIcons li = LauncherIcons.obtain(getContext())) {
|
||||
Drawable d = itemInfo.getRemoteAction().getIcon().loadDrawable(getContext());
|
||||
BitmapInfo bitmap = li.createBadgedIconBitmap(d, itemInfo.user,
|
||||
Build.VERSION.SDK_INT);
|
||||
|
||||
if (useIconToBadge) {
|
||||
BitmapInfo placeholder = li.createIconBitmap(
|
||||
itemInfo.getRemoteAction().getTitle().toString().substring(0, 1),
|
||||
bitmap.color);
|
||||
itemInfo.bitmap = li.badgeBitmap(placeholder.icon, bitmap);
|
||||
} else {
|
||||
itemInfo.bitmap = bitmap;
|
||||
}
|
||||
reapplyItemInfoAsync(itemInfo);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@UiThread
|
||||
void reapplyItemInfoAsync(ItemInfoWithIcon itemInfoWithIcon) {
|
||||
MAIN_EXECUTOR.post(() -> reapplyItemInfo(itemInfoWithIcon));
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void handleSelection(int eventType) {
|
||||
mLauncher.getItemOnClickListener().onClick(this);
|
||||
SearchEventTracker.INSTANCE.get(mLauncher).notifySearchTargetEvent(
|
||||
new SearchTargetEvent.Builder(mSearchTarget, eventType).build());
|
||||
reportEvent(eventType);
|
||||
}
|
||||
|
||||
private void reportEvent(int eventType) {
|
||||
SearchTargetEvent.Builder b = new SearchTargetEvent.Builder(mSearchTarget, eventType);
|
||||
if (mSearchTarget.getItemType().equals(TARGET_TYPE_SHORTCUT)) {
|
||||
b.setShortcutPosition(0);
|
||||
}
|
||||
SearchEventTracker.INSTANCE.get(mLauncher).notifySearchTargetEvent(b.build());
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -93,8 +193,22 @@ public class SearchResultIcon extends BubbleTextView implements
|
||||
|
||||
@Override
|
||||
public boolean onLongClick(View view) {
|
||||
SearchEventTracker.INSTANCE.get(mLauncher).notifySearchTargetEvent(
|
||||
new SearchTargetEvent.Builder(mSearchTarget, SearchTargetEvent.LONG_PRESS).build());
|
||||
if (!supportsLongPress(mSearchTarget.getItemType())) {
|
||||
return false;
|
||||
}
|
||||
reportEvent(SearchTargetEvent.LONG_PRESS);
|
||||
return ItemLongClickListener.INSTANCE_ALL_APPS.onLongClick(view);
|
||||
|
||||
}
|
||||
|
||||
private boolean supportsLongPress(String type) {
|
||||
for (String t : LONG_PRESS_SUPPORTED_TYPES) {
|
||||
if (t.equals(type)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
protected boolean loadIconFromResource() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,188 +17,173 @@ package com.android.launcher3.views;
|
||||
|
||||
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
|
||||
import static com.android.launcher3.util.Executors.MODEL_EXECUTOR;
|
||||
import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
|
||||
|
||||
import android.app.RemoteAction;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.pm.ShortcutInfo;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Build;
|
||||
import android.os.UserHandle;
|
||||
import android.util.AttributeSet;
|
||||
import android.widget.EditText;
|
||||
import android.util.Pair;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.android.launcher3.BubbleTextView;
|
||||
import com.android.launcher3.Launcher;
|
||||
import com.android.launcher3.LauncherAppState;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.allapps.search.AllAppsSearchBarController;
|
||||
import com.android.launcher3.allapps.search.SearchEventTracker;
|
||||
import com.android.launcher3.icons.BitmapInfo;
|
||||
import com.android.launcher3.icons.LauncherIcons;
|
||||
import com.android.launcher3.model.data.ItemInfo;
|
||||
import com.android.launcher3.model.data.ItemInfoWithIcon;
|
||||
import com.android.launcher3.model.data.RemoteActionItemInfo;
|
||||
import com.android.launcher3.model.data.PackageItemInfo;
|
||||
import com.android.launcher3.model.data.WorkspaceItemInfo;
|
||||
import com.android.launcher3.touch.ItemClickHandler;
|
||||
import com.android.launcher3.util.Themes;
|
||||
import com.android.systemui.plugins.shared.SearchTarget;
|
||||
import com.android.systemui.plugins.shared.SearchTargetEvent;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* A view representing a stand alone shortcut search result
|
||||
* A full width representation of {@link SearchResultIcon} with a secondary label and inline
|
||||
* shortcuts
|
||||
*/
|
||||
public class SearchResultIconRow extends DoubleShadowBubbleTextView implements
|
||||
AllAppsSearchBarController.SearchTargetHandler {
|
||||
public class SearchResultIconRow extends LinearLayout implements
|
||||
AllAppsSearchBarController.SearchTargetHandler, View.OnClickListener,
|
||||
View.OnLongClickListener {
|
||||
public static final int MAX_SHORTCUTS_COUNT = 2;
|
||||
|
||||
|
||||
public static final String TARGET_TYPE_REMOTE_ACTION = "remote_action";
|
||||
public static final String TARGET_TYPE_SUGGEST = "suggest";
|
||||
public static final String TARGET_TYPE_SHORTCUT = "shortcut";
|
||||
|
||||
|
||||
public static final String REMOTE_ACTION_SHOULD_START = "should_start_for_result";
|
||||
public static final String REMOTE_ACTION_TOKEN = "action_token";
|
||||
|
||||
private final boolean mMatchesInset;
|
||||
private final Launcher mLauncher;
|
||||
private final LauncherAppState mLauncherAppState;
|
||||
private SearchResultIcon mResultIcon;
|
||||
private TextView mTitleView;
|
||||
private TextView mDescriptionView;
|
||||
private BubbleTextView[] mShortcutViews = new BubbleTextView[2];
|
||||
|
||||
private SearchTarget mSearchTarget;
|
||||
private PackageItemInfo mProviderInfo;
|
||||
|
||||
@Nullable private Drawable mCustomIcon;
|
||||
|
||||
public SearchResultIconRow(@NonNull Context context) {
|
||||
public SearchResultIconRow(Context context) {
|
||||
this(context, null, 0);
|
||||
}
|
||||
|
||||
public SearchResultIconRow(@NonNull Context context,
|
||||
public SearchResultIconRow(Context context,
|
||||
@Nullable AttributeSet attrs) {
|
||||
this(context, attrs, 0);
|
||||
}
|
||||
|
||||
public SearchResultIconRow(@NonNull Context context, @Nullable AttributeSet attrs,
|
||||
int defStyleAttr) {
|
||||
public SearchResultIconRow(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
TypedArray a = context.obtainStyledAttributes(attrs,
|
||||
R.styleable.SearchResultIconRow, defStyleAttr, 0);
|
||||
mMatchesInset = a.getBoolean(R.styleable.SearchResultIconRow_matchTextInsetWithQuery,
|
||||
false);
|
||||
|
||||
int customIconResId = a.getResourceId(R.styleable.SearchResultIconRow_customIcon, 0);
|
||||
|
||||
if (customIconResId != 0) {
|
||||
mCustomIcon = Launcher.getLauncher(context).getDrawable(customIconResId);
|
||||
}
|
||||
|
||||
a.recycle();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void onAttachedToWindow() {
|
||||
super.onAttachedToWindow();
|
||||
Launcher launcher = Launcher.getLauncher(getContext());
|
||||
if (mMatchesInset && launcher.getAppsView() != null && getParent() != null) {
|
||||
EditText editText = launcher.getAppsView().getSearchUiManager().getEditText();
|
||||
if (editText != null) {
|
||||
int counterOffset = getIconSize() + getCompoundDrawablePadding() / 2;
|
||||
setPadding(editText.getLeft() - counterOffset, getPaddingTop(),
|
||||
getPaddingRight(), getPaddingBottom());
|
||||
}
|
||||
}
|
||||
mLauncher = Launcher.getLauncher(getContext());
|
||||
mLauncherAppState = LauncherAppState.getInstance(getContext());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void drawFocusHighlight(Canvas canvas) {
|
||||
mHighlightPaint.setColor(mHighlightColor);
|
||||
float r = Themes.getDialogCornerRadius(getContext());
|
||||
canvas.drawRoundRect(0, 0, getWidth(), getHeight(), r, r, mHighlightPaint);
|
||||
}
|
||||
protected void onFinishInflate() {
|
||||
super.onFinishInflate();
|
||||
int iconSize = mLauncher.getDeviceProfile().allAppsIconSizePx;
|
||||
|
||||
mResultIcon = findViewById(R.id.icon);
|
||||
mTitleView = findViewById(R.id.title);
|
||||
mDescriptionView = findViewById(R.id.desc);
|
||||
mShortcutViews[0] = findViewById(R.id.shortcut_0);
|
||||
mShortcutViews[1] = findViewById(R.id.shortcut_1);
|
||||
mResultIcon.getLayoutParams().height = iconSize;
|
||||
mResultIcon.getLayoutParams().width = iconSize;
|
||||
for (BubbleTextView bubbleTextView : mShortcutViews) {
|
||||
ViewGroup.LayoutParams lp = bubbleTextView.getLayoutParams();
|
||||
lp.width = iconSize;
|
||||
bubbleTextView.setOnClickListener(view -> {
|
||||
WorkspaceItemInfo itemInfo = (WorkspaceItemInfo) bubbleTextView.getTag();
|
||||
SearchTargetEvent event = new SearchTargetEvent.Builder(mSearchTarget,
|
||||
SearchTargetEvent.CHILD_SELECT).setShortcutPosition(itemInfo.rank).build();
|
||||
SearchEventTracker.getInstance(getContext()).notifySearchTargetEvent(event);
|
||||
mLauncher.getItemOnClickListener().onClick(view);
|
||||
});
|
||||
}
|
||||
setOnClickListener(this);
|
||||
setOnLongClickListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applySearchTarget(SearchTarget searchTarget) {
|
||||
mSearchTarget = searchTarget;
|
||||
String type = searchTarget.getItemType();
|
||||
if (type.equals(TARGET_TYPE_REMOTE_ACTION) || type.equals(TARGET_TYPE_SUGGEST)) {
|
||||
prepareUsingRemoteAction(searchTarget.getRemoteAction(),
|
||||
searchTarget.getExtras().getString(REMOTE_ACTION_TOKEN),
|
||||
searchTarget.getExtras().getBoolean(REMOTE_ACTION_SHOULD_START),
|
||||
type.equals(TARGET_TYPE_REMOTE_ACTION));
|
||||
mResultIcon.applySearchTarget(searchTarget);
|
||||
mResultIcon.setTextVisibility(false);
|
||||
mTitleView.setText(mResultIcon.getText());
|
||||
String itemType = searchTarget.getItemType();
|
||||
boolean showDesc = itemType.equals(SearchResultIcon.TARGET_TYPE_SHORTCUT);
|
||||
mDescriptionView.setVisibility(showDesc ? VISIBLE : GONE);
|
||||
|
||||
} else if (type.equals(TARGET_TYPE_SHORTCUT)) {
|
||||
prepareUsingShortcutInfo(searchTarget.getShortcutInfos().get(0));
|
||||
if (itemType.equals(SearchResultIcon.TARGET_TYPE_SHORTCUT)) {
|
||||
ShortcutInfo shortcutInfo = searchTarget.getShortcutInfos().get(0);
|
||||
setProviderDetails(new ComponentName(shortcutInfo.getPackage(), ""),
|
||||
shortcutInfo.getUserHandle());
|
||||
} else if (itemType.equals(SearchResultIcon.TARGET_TYPE_HERO_APP)) {
|
||||
showInlineShortcuts(mSearchTarget.getShortcutInfos());
|
||||
}
|
||||
if (!itemType.equals(SearchResultIcon.TARGET_TYPE_HERO_APP)) {
|
||||
showInlineShortcuts(new ArrayList<>());
|
||||
}
|
||||
setOnClickListener(v -> handleSelection(SearchTargetEvent.SELECT));
|
||||
SearchEventTracker.INSTANCE.get(getContext()).registerWeakHandler(searchTarget, this);
|
||||
}
|
||||
|
||||
private void prepareUsingShortcutInfo(ShortcutInfo shortcutInfo) {
|
||||
WorkspaceItemInfo workspaceItemInfo = new WorkspaceItemInfo(shortcutInfo, getContext());
|
||||
applyFromWorkspaceItem(workspaceItemInfo);
|
||||
LauncherAppState launcherAppState = LauncherAppState.getInstance(getContext());
|
||||
if (!loadIconFromResource()) {
|
||||
MODEL_EXECUTOR.execute(() -> {
|
||||
launcherAppState.getIconCache().getShortcutIcon(workspaceItemInfo, shortcutInfo);
|
||||
reapplyItemInfoAsync(workspaceItemInfo);
|
||||
private void showInlineShortcuts(List<ShortcutInfo> infos) {
|
||||
if (infos == null) return;
|
||||
ArrayList<Pair<ShortcutInfo, ItemInfoWithIcon>> shortcuts = new ArrayList<>();
|
||||
for (int i = 0; infos != null && i < infos.size() && i < MAX_SHORTCUTS_COUNT; i++) {
|
||||
ShortcutInfo shortcutInfo = infos.get(i);
|
||||
ItemInfoWithIcon si = new WorkspaceItemInfo(shortcutInfo, getContext());
|
||||
si.rank = i;
|
||||
shortcuts.add(new Pair<>(shortcutInfo, si));
|
||||
}
|
||||
|
||||
for (int i = 0; i < mShortcutViews.length; i++) {
|
||||
BubbleTextView shortcutView = mShortcutViews[i];
|
||||
mShortcutViews[i].setVisibility(shortcuts.size() > i ? VISIBLE : GONE);
|
||||
if (i < shortcuts.size()) {
|
||||
Pair<ShortcutInfo, ItemInfoWithIcon> p = shortcuts.get(i);
|
||||
//apply ItemInfo and prepare view
|
||||
shortcutView.applyFromWorkspaceItem((WorkspaceItemInfo) p.second);
|
||||
MODEL_EXECUTOR.execute(() -> {
|
||||
// load unbadged shortcut in background and update view when icon ready
|
||||
mLauncherAppState.getIconCache().getUnbadgedShortcutIcon(p.second, p.first);
|
||||
MAIN_EXECUTOR.post(() -> shortcutView.reapplyItemInfo(p.second));
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void setProviderDetails(ComponentName componentName, UserHandle userHandle) {
|
||||
PackageItemInfo packageItemInfo = new PackageItemInfo(componentName.getPackageName());
|
||||
if (mProviderInfo == packageItemInfo) return;
|
||||
MODEL_EXECUTOR.post(() -> {
|
||||
packageItemInfo.user = userHandle;
|
||||
mLauncherAppState.getIconCache().getTitleAndIconForApp(packageItemInfo, true);
|
||||
MAIN_EXECUTOR.post(() -> {
|
||||
mDescriptionView.setText(packageItemInfo.title);
|
||||
mProviderInfo = packageItemInfo;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void prepareUsingRemoteAction(RemoteAction remoteAction, String token, boolean start,
|
||||
boolean useIconToBadge) {
|
||||
RemoteActionItemInfo itemInfo = new RemoteActionItemInfo(remoteAction, token, start);
|
||||
|
||||
applyFromRemoteActionInfo(itemInfo);
|
||||
if (itemInfo.isEscapeHatch() || !loadIconFromResource()) {
|
||||
UI_HELPER_EXECUTOR.post(() -> {
|
||||
// If the Drawable from the remote action is not AdaptiveBitmap, styling will not
|
||||
// work.
|
||||
try (LauncherIcons li = LauncherIcons.obtain(getContext())) {
|
||||
Drawable d = itemInfo.getRemoteAction().getIcon().loadDrawable(getContext());
|
||||
BitmapInfo bitmap = li.createBadgedIconBitmap(d, itemInfo.user,
|
||||
Build.VERSION.SDK_INT);
|
||||
|
||||
if (useIconToBadge) {
|
||||
BitmapInfo placeholder = li.createIconBitmap(
|
||||
itemInfo.getRemoteAction().getTitle().toString().substring(0, 1),
|
||||
bitmap.color);
|
||||
itemInfo.bitmap = li.badgeBitmap(placeholder.icon, bitmap);
|
||||
} else {
|
||||
itemInfo.bitmap = bitmap;
|
||||
}
|
||||
reapplyItemInfoAsync(itemInfo);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private boolean loadIconFromResource() {
|
||||
if (mCustomIcon == null) return false;
|
||||
setIcon(mCustomIcon);
|
||||
return true;
|
||||
}
|
||||
|
||||
void reapplyItemInfoAsync(ItemInfoWithIcon itemInfoWithIcon) {
|
||||
MAIN_EXECUTOR.post(() -> {
|
||||
reapplyItemInfo(itemInfoWithIcon);
|
||||
mCustomIcon = getIcon();
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleSelection(int eventType) {
|
||||
ItemInfo itemInfo = (ItemInfo) getTag();
|
||||
Launcher launcher = Launcher.getLauncher(getContext());
|
||||
if (itemInfo instanceof WorkspaceItemInfo) {
|
||||
ItemClickHandler.onClickAppShortcut(this, (WorkspaceItemInfo) itemInfo, launcher);
|
||||
} else {
|
||||
ItemClickHandler.onClickRemoteAction(launcher, (RemoteActionItemInfo) itemInfo);
|
||||
}
|
||||
SearchEventTracker.INSTANCE.get(getContext()).notifySearchTargetEvent(
|
||||
new SearchTargetEvent.Builder(mSearchTarget, eventType).build());
|
||||
mResultIcon.handleSelection(eventType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
mResultIcon.performClick();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onLongClick(View view) {
|
||||
mResultIcon.performLongClick();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
62
src/com/android/launcher3/views/SearchResultSuggestion.java
Normal file
62
src/com/android/launcher3/views/SearchResultSuggestion.java
Normal file
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* 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 android.content.Context;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import com.android.launcher3.R;
|
||||
|
||||
/**
|
||||
* {@link SearchResultIconRow} with custom drawable resource
|
||||
*/
|
||||
public class SearchResultSuggestion extends SearchResultIcon {
|
||||
|
||||
private final Drawable mCustomIcon;
|
||||
|
||||
public SearchResultSuggestion(Context context) {
|
||||
this(context, null, 0);
|
||||
}
|
||||
|
||||
public SearchResultSuggestion(Context context, AttributeSet attrs) {
|
||||
this(context, attrs, 0);
|
||||
}
|
||||
|
||||
public SearchResultSuggestion(Context context, AttributeSet attrs, int defStyle) {
|
||||
super(context, attrs, defStyle);
|
||||
|
||||
TypedArray a = context.obtainStyledAttributes(attrs,
|
||||
R.styleable.SearchResultSuggestion, defStyle, 0);
|
||||
mCustomIcon = a.getDrawable(R.styleable.SearchResultSuggestion_customIcon);
|
||||
a.recycle();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onFinishInflate() {
|
||||
super.onFinishInflate();
|
||||
ViewGroup.LayoutParams lp = getLayoutParams();
|
||||
lp.height = BaseDragLayer.LayoutParams.WRAP_CONTENT;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean loadIconFromResource() {
|
||||
setIcon(mCustomIcon);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -15,8 +15,9 @@
|
||||
*/
|
||||
package com.android.launcher3.views;
|
||||
|
||||
import static com.android.launcher3.views.SearchResultIconRow.REMOTE_ACTION_SHOULD_START;
|
||||
import static com.android.launcher3.views.SearchResultIconRow.REMOTE_ACTION_TOKEN;
|
||||
|
||||
import static com.android.launcher3.views.SearchResultIcon.REMOTE_ACTION_SHOULD_START;
|
||||
import static com.android.launcher3.views.SearchResultIcon.REMOTE_ACTION_TOKEN;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
|
||||
Reference in New Issue
Block a user