Setup SearchResultIcon for single cell results

SearchResultIcon will be able to render apps, shortcuts and remote actions. It can also handle its own focused state drawing.

Screenshot: https://screenshot.googleplex.com/C3KgjJtLQTBPgaf

Bug: 170752716
Test: Manual
Change-Id: I460a9c128ea3f5814784e342c5d5fa5b7e310882
This commit is contained in:
Samuel Fufa 2020-10-14 10:15:07 -07:00
parent d5bbe6809d
commit 314761a808
13 changed files with 277 additions and 80 deletions

View File

@ -30,6 +30,7 @@
with some minor changed based on the derivative app.
-->
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.CALL_PHONE" />
<uses-permission android:name="android.permission.SET_WALLPAPER" />
<uses-permission android:name="android.permission.SET_WALLPAPER_HINTS" />

View File

@ -1,5 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2015 The Android Open Source Project
<?xml version="1.0" encoding="utf-8"?><!-- Copyright (C) 2015 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.
@ -13,16 +12,10 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
<com.android.launcher3.BubbleTextView
xmlns:android="http://schemas.android.com/apk/res/android"
<com.android.launcher3.BubbleTextView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:launcher="http://schemas.android.com/apk/res-auto"
style="@style/BaseIcon"
style="@style/BaseIcon.AllApps"
android:id="@+id/icon"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:stateListAnimator="@animator/all_apps_fastscroll_icon_anim"
launcher:iconDisplay="all_apps"
launcher:centerVertically="true"
android:paddingLeft="@dimen/dynamic_grid_cell_padding_x"
android:paddingRight="@dimen/dynamic_grid_cell_padding_x" />
launcher:centerVertically="true" />

View File

@ -0,0 +1,20 @@
<?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.views.SearchResultIcon xmlns:launcher="http://schemas.android.com/apk/res-auto"
style="@style/BaseIcon.AllApps"
launcher:iconDisplay="all_apps"
launcher:centerVertically="true" />

View File

@ -223,6 +223,16 @@
<item name="android:lines">1</item>
</style>
<!-- Base theme for AllApps BubbleTextViews -->
<style name="BaseIcon.AllApps" parent="BaseIcon">
<item name="android:layout_width">match_parent</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:stateListAnimator">@animator/all_apps_fastscroll_icon_anim</item>
<item name="android:paddingLeft">@dimen/dynamic_grid_cell_padding_x</item>
<item name="android:paddingRight">@dimen/dynamic_grid_cell_padding_x</item>
</style>
<!-- Icon displayed on the workspace -->
<style name="BaseIcon.Workspace" >
<item name="android:shadowRadius">2.0</item>

View File

@ -17,6 +17,7 @@
package com.android.launcher3;
import static com.android.launcher3.FastBitmapDrawable.newIcon;
import static com.android.launcher3.graphics.IconShape.getShape;
import static com.android.launcher3.graphics.PreloadIconDrawable.newPendingIcon;
import static com.android.launcher3.icons.GraphicsUtils.setColorAlphaBound;
@ -27,15 +28,18 @@ import android.animation.ValueAnimator;
import android.content.Context;
import android.content.res.ColorStateList;
import android.content.res.TypedArray;
import android.graphics.BlurMaskFilter;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PointF;
import android.graphics.PorterDuff.Mode;
import android.graphics.PorterDuffColorFilter;
import android.graphics.Rect;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.os.Process;
import android.text.TextUtils.TruncateAt;
import android.util.AttributeSet;
import android.util.Property;
@ -50,6 +54,8 @@ import androidx.core.graphics.ColorUtils;
import com.android.launcher3.Launcher.OnResumeCallback;
import com.android.launcher3.accessibility.LauncherAccessibilityDelegate;
import com.android.launcher3.allapps.AllAppsSectionDecorator;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.dot.DotInfo;
import com.android.launcher3.dragndrop.DraggableView;
import com.android.launcher3.folder.FolderIcon;
@ -60,6 +66,7 @@ import com.android.launcher3.graphics.PreloadIconDrawable;
import com.android.launcher3.icons.DotRenderer;
import com.android.launcher3.icons.IconCache.IconLoadRequest;
import com.android.launcher3.icons.IconCache.ItemInfoUpdateReceiver;
import com.android.launcher3.icons.LauncherIcons;
import com.android.launcher3.model.data.AppInfo;
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.model.data.ItemInfoWithIcon;
@ -79,7 +86,7 @@ import java.text.NumberFormat;
* too aggressive.
*/
public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver, OnResumeCallback,
IconLabelDotView, DraggableView, Reorderable {
IconLabelDotView, DraggableView, Reorderable, AllAppsSectionDecorator.SelfDecoratingView {
private static final int DISPLAY_WORKSPACE = 0;
private static final int DISPLAY_ALL_APPS = 1;
@ -87,6 +94,8 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver,
private static final int DISPLAY_HERO_APP = 5;
private static final int[] STATE_PRESSED = new int[]{android.R.attr.state_pressed};
private static final float HIGHLIGHT_SCALE = 1.16f;
private final PointF mTranslationForReorderBounce = new PointF(0, 0);
private final PointF mTranslationForReorderPreview = new PointF(0, 0);
@ -95,6 +104,11 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver,
private float mScaleForReorderBounce = 1f;
protected final Paint mHighlightPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
private final Path mHighlightPath = new Path();
protected int mHighlightColor = Color.TRANSPARENT;
private final BlurMaskFilter mHighlightShadowFilter;
private static final Property<BubbleTextView, Float> DOT_SCALE_PROPERTY
= new Property<BubbleTextView, Float>(Float.TYPE, "dotScale") {
@Override
@ -208,6 +222,11 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver,
setEllipsize(TruncateAt.END);
setAccessibilityDelegate(mActivity.getAccessibilityDelegate());
setTextAlpha(1f);
int shadowSize = context.getResources().getDimensionPixelSize(
R.dimen.blur_size_click_shadow);
mHighlightShadowFilter = new BlurMaskFilter(shadowSize, BlurMaskFilter.Blur.INNER);
}
@Override
@ -421,8 +440,38 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver,
@Override
public void onDraw(Canvas canvas) {
if (FeatureFlags.ENABLE_DEVICE_SEARCH.get() && mHighlightColor != Color.TRANSPARENT) {
int count = canvas.save();
drawFocusHighlight(canvas);
canvas.restoreToCount(count);
}
super.onDraw(canvas);
drawDotIfNecessary(canvas);
}
protected void drawFocusHighlight(Canvas canvas) {
boolean isBadged = getTag() instanceof ItemInfo && !Process.myUserHandle().equals(
((ItemInfo) getTag()).user);
float insetScale = (HIGHLIGHT_SCALE - 1) / 2;
canvas.translate(-getIconSize() * insetScale, -insetScale * getIconSize());
float outlineSize = getIconSize() * HIGHLIGHT_SCALE;
mHighlightPath.reset();
mHighlightPaint.reset();
getIconBounds(mDotParams.iconBounds);
getShape().addToPath(mHighlightPath, mDotParams.iconBounds.left, mDotParams.iconBounds.top,
outlineSize / 2);
if (isBadged) {
float borderSize = outlineSize - getIconSize();
float badgeSize = LauncherIcons.getBadgeSizeForIconSize(getIconSize()) + borderSize;
float badgeInset = outlineSize - badgeSize;
getShape().addToPath(mHighlightPath, mDotParams.iconBounds.left + badgeInset,
mDotParams.iconBounds.top + badgeInset, badgeSize / 2);
}
mHighlightPaint.setMaskFilter(mHighlightShadowFilter);
mHighlightPaint.setColor(mDotParams.color);
canvas.drawPath(mHighlightPath, mHighlightPaint);
mHighlightPaint.setMaskFilter(null);
mHighlightPaint.setColor(mHighlightColor);
canvas.drawPath(mHighlightPath, mHighlightPaint);
}
/**
@ -787,10 +836,11 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver,
@Override
public SafeCloseable prepareDrawDragView() {
int highlightColor = mHighlightColor;
mHighlightColor = Color.TRANSPARENT;
resetIconScale();
setForceHideDot(true);
return () -> {
};
return () -> mHighlightColor = highlightColor;
}
private void resetIconScale() {
@ -827,4 +877,17 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver,
});
iconUpdateAnimation.start();
}
@Override
public void decorate(int color) {
mHighlightColor = color;
invalidate();
}
@Override
public void removeDecoration() {
mHighlightColor = Color.TRANSPARENT;
invalidate();
}
}

View File

@ -43,15 +43,12 @@ import com.android.launcher3.BaseDraggingActivity;
import com.android.launcher3.BubbleTextView;
import com.android.launcher3.R;
import com.android.launcher3.allapps.search.AllAppsSearchBarController.SearchTargetHandler;
import com.android.launcher3.allapps.search.SearchEventTracker;
import com.android.launcher3.allapps.search.SearchSectionInfo;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.model.data.AppInfo;
import com.android.launcher3.util.PackageManagerHelper;
import com.android.launcher3.views.HeroSearchResultView;
import com.android.launcher3.views.SearchSliceWrapper;
import com.android.systemui.plugins.shared.SearchTarget;
import com.android.systemui.plugins.shared.SearchTargetEvent;
import java.util.List;
@ -94,9 +91,11 @@ public class AllAppsGridAdapter extends
public static final int VIEW_TYPE_SEARCH_SUGGEST = 1 << 13;
public static final int VIEW_TYPE_SEARCH_ICON = 1 << 14;
// 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;
public static final int VIEW_TYPE_MASK_ICON = VIEW_TYPE_ICON | VIEW_TYPE_SEARCH_ICON;
/**
* ViewHolder for each icon.
@ -186,6 +185,7 @@ public class AllAppsGridAdapter extends
|| viewType == VIEW_TYPE_SEARCH_PEOPLE
|| viewType == VIEW_TYPE_SEARCH_THUMBNAIL
|| viewType == VIEW_TYPE_SEARCH_ICON_ROW
|| viewType == VIEW_TYPE_SEARCH_ICON
|| viewType == VIEW_TYPE_SEARCH_SUGGEST;
}
}
@ -399,11 +399,8 @@ public class AllAppsGridAdapter extends
R.layout.all_apps_icon, parent, false);
icon.setLongPressTimeoutFactor(1f);
icon.setOnFocusChangeListener(mIconFocusListener);
if (!FeatureFlags.ENABLE_DEVICE_SEARCH.get()) {
icon.setOnClickListener(mOnIconClickListener);
icon.setOnLongClickListener(mOnIconLongClickListener);
}
icon.setOnClickListener(mOnIconClickListener);
icon.setOnLongClickListener(mOnIconLongClickListener);
// Ensure the all apps icon height matches the workspace icons in portrait mode.
icon.getLayoutParams().height = mLauncher.getDeviceProfile().allAppsCellHeightPx;
return new ViewHolder(icon);
@ -419,6 +416,9 @@ public class AllAppsGridAdapter extends
case VIEW_TYPE_ALL_APPS_DIVIDER:
return new ViewHolder(mLayoutInflater.inflate(
R.layout.all_apps_divider, parent, false));
case VIEW_TYPE_SEARCH_ICON:
return new ViewHolder(mLayoutInflater.inflate(
R.layout.search_result_icon, parent, false));
case VIEW_TYPE_SEARCH_CORPUS_TITLE:
return new ViewHolder(
mLayoutInflater.inflate(R.layout.search_section_title, parent, false));
@ -453,6 +453,10 @@ public class AllAppsGridAdapter extends
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
if (FeatureFlags.ENABLE_DEVICE_SEARCH.get()
&& holder.itemView instanceof AllAppsSectionDecorator.SelfDecoratingView) {
((AllAppsSectionDecorator.SelfDecoratingView) holder.itemView).removeDecoration();
}
switch (holder.getItemViewType()) {
case VIEW_TYPE_ICON:
AdapterItem adapterItem = mApps.getAdapterItems().get(position);
@ -460,43 +464,6 @@ public class AllAppsGridAdapter extends
BubbleTextView icon = (BubbleTextView) holder.itemView;
icon.reset();
icon.applyFromApplicationInfo(info);
if (!FeatureFlags.ENABLE_DEVICE_SEARCH.get()) {
break;
}
//TODO: replace with custom TopHitBubbleTextView with support for both shortcut
// and apps
if (adapterItem instanceof SearchAdapterItem) {
SearchAdapterItem item = (SearchAdapterItem) adapterItem;
SearchTargetHandler searchTargetHandler = new SearchTargetHandler() {
@Override
public void applySearchTarget(SearchTarget searchTarget) {
// Does nothing
}
@Override
public void handleSelection(int type) {
SearchTargetEvent e = new SearchTargetEvent(SearchTarget.ItemType.APP,
type, item.position, item.getSearchSessionId());
e.bundle = HeroSearchResultView.getAppBundle(info);
SearchEventTracker.INSTANCE.get(mLauncher).notifySearchTargetEvent(e);
}
};
SearchEventTracker.INSTANCE.get(mLauncher).registerWeakHandler(
((SearchAdapterItem) adapterItem).getSearchTarget(),
searchTargetHandler);
icon.setOnClickListener(view -> {
searchTargetHandler.handleSelection(SearchTargetEvent.SELECT);
mOnIconClickListener.onClick(view);
});
icon.setOnLongClickListener(view -> {
searchTargetHandler.handleSelection(SearchTargetEvent.LONG_PRESS);
return mOnIconLongClickListener.onLongClick(view);
});
} else {
icon.setOnClickListener(mOnIconClickListener);
icon.setOnLongClickListener(mOnIconLongClickListener);
}
break;
case VIEW_TYPE_EMPTY_SEARCH:
TextView emptyViewText = (TextView) holder.itemView;
@ -525,6 +492,7 @@ public class AllAppsGridAdapter extends
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:
case VIEW_TYPE_SEARCH_PEOPLE:
case VIEW_TYPE_SEARCH_THUMBNAIL:
@ -544,11 +512,10 @@ public class AllAppsGridAdapter extends
public void onViewRecycled(@NonNull ViewHolder holder) {
super.onViewRecycled(holder);
if (!FeatureFlags.ENABLE_DEVICE_SEARCH.get()) return;
if (holder.itemView instanceof BubbleTextView) {
BubbleTextView icon = (BubbleTextView) holder.itemView;
icon.setOnClickListener(null);
icon.setOnLongClickListener(null);
} else if (holder.itemView instanceof SliceView) {
if (holder.itemView instanceof AllAppsSectionDecorator.SelfDecoratingView) {
((AllAppsSectionDecorator.SelfDecoratingView) holder.itemView).removeDecoration();
}
if (holder.itemView instanceof SliceView) {
SliceView sliceView = (SliceView) holder.itemView;
if (sliceView.getTag() instanceof SearchSliceWrapper) {
((SearchSliceWrapper) sliceView.getTag()).destroy();

View File

@ -54,6 +54,9 @@ public class AllAppsSectionDecorator extends RecyclerView.ItemDecoration {
int i = 0;
while (i < itemCount) {
View view = parent.getChildAt(i);
if (view instanceof SelfDecoratingView) {
((SelfDecoratingView) view).removeDecoration();
}
int position = parent.getChildAdapterPosition(view);
AllAppsGridAdapter.AdapterItem adapterItem = adapterItems.get(position);
if (adapterItem.searchSectionInfo != null) {
@ -93,7 +96,7 @@ public class AllAppsSectionDecorator extends RecyclerView.ItemDecoration {
int index = mAppsView.getApps().getFocusedChildIndex();
AppsGridLayoutManager layoutManager = (AppsGridLayoutManager)
mAppsView.getActiveRecyclerView().getLayoutManager();
if (layoutManager.findFirstVisibleItemPosition() == index
if (layoutManager.findFirstVisibleItemPosition() <= index
&& index < parent.getChildCount()) {
decorationHandler.onFocusDraw(c, parent.getChildAt(index));
}
@ -156,6 +159,10 @@ public class AllAppsSectionDecorator extends RecyclerView.ItemDecoration {
if (view == null) {
return;
}
if (view instanceof SelfDecoratingView) {
((SelfDecoratingView) view).decorate(mFocusColor);
return;
}
mPaint.setColor(mFocusColor);
canvas.drawRoundRect(view.getLeft(), view.getTop(),
view.getRight(), view.getBottom(), mRadius, mRadius, mPaint);
@ -169,4 +176,18 @@ public class AllAppsSectionDecorator extends RecyclerView.ItemDecoration {
}
}
/**
* An interface for a view to draw highlight indicator
*/
public interface SelfDecoratingView {
/**
* Removes decorations drawing if focus is acquired by another view
*/
void removeDecoration();
/**
* Draws highlight indicator on view.
*/
void decorate(int focusColor);
}
}

View File

@ -18,6 +18,8 @@ package com.android.launcher3.allapps;
import static com.android.launcher3.model.data.AppInfo.COMPONENT_KEY_COMPARATOR;
import static com.android.launcher3.model.data.AppInfo.EMPTY_ARRAY;
import android.content.ComponentName;
import android.os.UserHandle;
import android.view.View;
import android.view.ViewGroup;
@ -27,6 +29,7 @@ import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.model.data.PromiseAppInfo;
import com.android.launcher3.util.ComponentKey;
import com.android.launcher3.util.PackageUserKey;
import com.android.systemui.plugins.shared.SearchTarget;
import java.util.ArrayList;
import java.util.Arrays;
@ -86,6 +89,19 @@ public class AllAppsStore {
return index < 0 ? null : mApps[index];
}
/**
* Gets AppInfo from {@link SearchTarget}
* TODO: SearchTarget should have userHandle and ComponentKey members
*/
public AppInfo getAppFromSearchTarget(SearchTarget searchTarget) {
ComponentName cn = searchTarget.bundle.getParcelable("component_name");
UserHandle userHandle = searchTarget.bundle.getParcelable("user_handle");
if (cn == null) {
throw new IllegalStateException("Component name is required for AppInfo");
}
return getApp(new ComponentKey(cn, userHandle));
}
public void enableDeferUpdates(int flag) {
mDeferUpdatesFlags |= flag;
}

View File

@ -15,6 +15,8 @@
*/
package com.android.launcher3.allapps.search;
import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
import android.content.Context;
import androidx.annotation.Nullable;
@ -61,7 +63,7 @@ public class SearchEventTracker {
*/
public void notifySearchTargetEvent(SearchTargetEvent searchTargetEvent) {
if (mPlugin != null) {
mPlugin.notifySearchTargetEvent(searchTargetEvent);
UI_HELPER_EXECUTOR.post(() -> mPlugin.notifySearchTargetEvent(searchTargetEvent));
}
}

View File

@ -19,13 +19,11 @@ import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_ALL_APP
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import static com.android.launcher3.util.Executors.MODEL_EXECUTOR;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ShortcutInfo;
import android.graphics.Point;
import android.os.Bundle;
import android.os.UserHandle;
import android.util.AttributeSet;
import android.util.Pair;
import android.view.View;
@ -51,7 +49,6 @@ 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;
@ -122,7 +119,8 @@ public class HeroSearchResultView extends LinearLayout implements DragSource, Se
@Override
public void applySearchTarget(SearchTarget searchTarget) {
AppInfo appInfo = getAppInfo(searchTarget.bundle);
AllAppsStore apps = Launcher.getLauncher(getContext()).getAppsView().getAppsStore();
AppInfo appInfo = apps.getAppFromSearchTarget(searchTarget);
// TODO: replace this with searchTarget.shortcuts
ArrayList<ShortcutInfo> infos = searchTarget.bundle.getParcelableArrayList(
SHORTCUTS_KEY);
@ -156,13 +154,6 @@ public class HeroSearchResultView extends LinearLayout implements DragSource, Se
SearchEventTracker.INSTANCE.get(getContext()).registerWeakHandler(searchTarget, this);
}
private AppInfo getAppInfo(Bundle bundle) {
AllAppsStore apps = Launcher.getLauncher(getContext()).getAppsView().getAppsStore();
ComponentName cn = bundle.getParcelable("component_name");
UserHandle userHandle = bundle.getParcelable("user_handle");
return (cn != null) ? apps.getApp(new ComponentKey(cn, userHandle)) : null;
}
@Override
public Object[] getTargetInfo() {
return mTargetInfo;

View File

@ -42,7 +42,7 @@ import com.android.launcher3.util.Themes;
*/
public class ScrimView<T extends Launcher> extends View implements Insettable, OnChangeListener {
private static final float SCRIM_ALPHA = .8f;
private static final float SCRIM_ALPHA = .75f;
protected final T mLauncher;
private final WallpaperColorInfo mWallpaperColorInfo;
protected final int mEndScrim;

View File

@ -0,0 +1,103 @@
/*
* 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.util.AttributeSet;
import android.view.View;
import com.android.launcher3.BubbleTextView;
import com.android.launcher3.Launcher;
import com.android.launcher3.allapps.AllAppsStore;
import com.android.launcher3.allapps.search.AllAppsSearchBarController;
import com.android.launcher3.allapps.search.SearchEventTracker;
import com.android.launcher3.model.data.AppInfo;
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.touch.ItemLongClickListener;
import com.android.systemui.plugins.shared.SearchTarget;
import com.android.systemui.plugins.shared.SearchTargetEvent;
/**
* A {@link BubbleTextView} representing a single cell result in AllApps
*/
public class SearchResultIcon extends BubbleTextView implements
AllAppsSearchBarController.SearchTargetHandler, View.OnClickListener,
View.OnLongClickListener {
private final Object[] mTargetInfo = createTargetInfo();
private final Launcher mLauncher;
private SearchTarget mSearchTarget;
public SearchResultIcon(Context context) {
this(context, null, 0);
}
public SearchResultIcon(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public SearchResultIcon(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
mLauncher = Launcher.getLauncher(getContext());
}
@Override
protected void onFinishInflate() {
super.onFinishInflate();
setLongPressTimeoutFactor(1f);
setOnFocusChangeListener(mLauncher.getFocusHandler());
setOnClickListener(this);
setOnLongClickListener(this);
getLayoutParams().height = mLauncher.getDeviceProfile().allAppsCellHeightPx;
}
@Override
public void applySearchTarget(SearchTarget searchTarget) {
mSearchTarget = searchTarget;
AllAppsStore appsStore = mLauncher.getAppsView().getAppsStore();
if (searchTarget.type == SearchTarget.ItemType.APP) {
AppInfo appInfo = appsStore.getAppFromSearchTarget(searchTarget);
applyFromApplicationInfo(appInfo);
}
}
@Override
public Object[] getTargetInfo() {
return mTargetInfo;
}
@Override
public void handleSelection(int eventType) {
SearchTargetEvent event = getSearchTargetEvent(mSearchTarget.type,
eventType);
if (mSearchTarget.type.equals(SearchTarget.ItemType.APP)) {
event.bundle = HeroSearchResultView.getAppBundle((ItemInfo) getTag());
}
SearchEventTracker.INSTANCE.get(mLauncher).notifySearchTargetEvent(event);
}
@Override
public void onClick(View view) {
handleSelection(SearchTargetEvent.SELECT);
mLauncher.getItemOnClickListener().onClick(view);
}
@Override
public boolean onLongClick(View view) {
handleSelection(SearchTargetEvent.LONG_PRESS);
return ItemLongClickListener.INSTANCE_ALL_APPS.onLongClick(view);
}
}

View File

@ -23,6 +23,7 @@ import android.app.RemoteAction;
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.Bundle;
@ -44,6 +45,7 @@ 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.ItemClickHandler;
import com.android.launcher3.util.Themes;
import com.android.systemui.plugins.shared.SearchTarget;
import com.android.systemui.plugins.shared.SearchTarget.ItemType;
import com.android.systemui.plugins.shared.SearchTargetEvent;
@ -97,6 +99,14 @@ public class SearchResultIconRow extends DoubleShadowBubbleTextView implements
}
}
@Override
protected void drawFocusHighlight(Canvas canvas) {
mHighlightPaint.setColor(mHighlightColor);
float r = Themes.getDialogCornerRadius(getContext());
canvas.drawRoundRect(0, 0, getWidth(), getHeight(), r, r, mHighlightPaint);
}
@Override
public void applySearchTarget(SearchTarget searchTarget) {
if (searchTarget.mRemoteAction != null) {