Support People search result in launcher
NOTE: this uses PackageManager and should be removed after people<>shortcut mapping in search provider.
Bug: 166337069
Test: Manual
Change-Id: I016ff0d5e6ada1599cce3d75bdcd55347c85193e
diff --git a/res/layout/search_result_people_item.xml b/res/layout/search_result_people_item.xml
new file mode 100644
index 0000000..a505e4a
--- /dev/null
+++ b/res/layout/search_result_people_item.xml
@@ -0,0 +1,62 @@
+<?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.SearchResultPeopleView xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:gravity="center_vertical"
+ android:layout_height="wrap_content"
+ android:padding="8dp"
+ android:orientation="horizontal">
+
+ <View
+ android:id="@+id/icon"
+ android:layout_marginRight="8dp"
+ android:layout_width="@dimen/default_icon_bitmap_size"
+ android:layout_height="@dimen/default_icon_bitmap_size" />
+
+ <TextView
+ android:layout_width="0dp"
+ android:textColor="?android:attr/textColorPrimary"
+ android:id="@+id/title"
+ android:layout_height="wrap_content"
+ android:layout_weight="1" />
+
+ <ImageButton
+ android:id="@+id/provider_0"
+ android:scaleType="fitCenter"
+ android:adjustViewBounds="true"
+ android:layout_margin="5dp"
+ android:background="?android:attr/selectableItemBackground"
+ android:layout_width="@dimen/default_icon_bitmap_size"
+ android:layout_height="@dimen/default_icon_bitmap_size" />
+
+ <ImageButton
+ android:id="@+id/provider_1"
+ android:layout_margin="5dp"
+ android:scaleType="fitCenter"
+ android:adjustViewBounds="true"
+ android:background="?android:attr/selectableItemBackground"
+ android:layout_width="@dimen/default_icon_bitmap_size"
+ android:layout_height="@dimen/default_icon_bitmap_size" />
+
+ <ImageButton
+ android:id="@+id/provider_2"
+ android:layout_margin="5dp"
+ android:scaleType="fitCenter"
+ android:adjustViewBounds="true"
+ android:background="?android:attr/selectableItemBackground"
+ android:layout_width="@dimen/default_icon_bitmap_size"
+ android:layout_height="@dimen/default_icon_bitmap_size" />
+
+</com.android.launcher3.views.SearchResultPeopleView>
\ No newline at end of file
diff --git a/src/com/android/launcher3/allapps/AllAppsGridAdapter.java b/src/com/android/launcher3/allapps/AllAppsGridAdapter.java
index ad6aa63..4e801a7 100644
--- a/src/com/android/launcher3/allapps/AllAppsGridAdapter.java
+++ b/src/com/android/launcher3/allapps/AllAppsGridAdapter.java
@@ -91,6 +91,8 @@
public static final int VIEW_TYPE_SEARCH_SHORTCUT = 1 << 10;
+ public static final int VIEW_TYPE_SEARCH_PEOPLE = 1 << 11;
+
// 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;
@@ -182,6 +184,7 @@
|| viewType == VIEW_TYPE_SEARCH_ROW_WITH_BUTTON
|| viewType == VIEW_TYPE_SEARCH_SLICE
|| viewType == VIEW_TYPE_SEARCH_ROW
+ || viewType == VIEW_TYPE_SEARCH_PEOPLE
|| viewType == VIEW_TYPE_SEARCH_SHORTCUT;
}
}
@@ -432,6 +435,9 @@
case VIEW_TYPE_SEARCH_SHORTCUT:
return new ViewHolder(mLayoutInflater.inflate(
R.layout.search_result_shortcut, parent, false));
+ case VIEW_TYPE_SEARCH_PEOPLE:
+ return new ViewHolder(mLayoutInflater.inflate(
+ R.layout.search_result_people_item, parent, false));
default:
throw new RuntimeException("Unexpected view type");
}
@@ -475,6 +481,7 @@
case VIEW_TYPE_SEARCH_HERO_APP:
case VIEW_TYPE_SEARCH_ROW:
case VIEW_TYPE_SEARCH_SHORTCUT:
+ case VIEW_TYPE_SEARCH_PEOPLE:
PayloadResultHandler payloadResultView = (PayloadResultHandler) holder.itemView;
payloadResultView.applyAdapterInfo(
(AdapterItemWithPayload) mApps.getAdapterItems().get(position));
diff --git a/src/com/android/launcher3/views/SearchResultPeopleView.java b/src/com/android/launcher3/views/SearchResultPeopleView.java
new file mode 100644
index 0000000..d1e34fa
--- /dev/null
+++ b/src/com/android/launcher3/views/SearchResultPeopleView.java
@@ -0,0 +1,156 @@
+/*
+ * 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 android.content.Intent.URI_ALLOW_UNSAFE;
+import static android.content.Intent.URI_ANDROID_APP_SCHEME;
+
+import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
+
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.graphics.Bitmap;
+import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.Drawable;
+import android.net.Uri;
+import android.os.Bundle;
+import android.util.AttributeSet;
+import android.view.View;
+import android.widget.ImageButton;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+import androidx.annotation.Nullable;
+import androidx.core.graphics.drawable.RoundedBitmapDrawable;
+import androidx.core.graphics.drawable.RoundedBitmapDrawableFactory;
+
+import com.android.launcher3.DeviceProfile;
+import com.android.launcher3.Launcher;
+import com.android.launcher3.R;
+import com.android.launcher3.allapps.AllAppsGridAdapter;
+import com.android.launcher3.allapps.search.AllAppsSearchBarController;
+import com.android.launcher3.util.Themes;
+
+import java.net.URISyntaxException;
+import java.util.ArrayList;
+
+/**
+ * A view representing a single people search result in all apps
+ */
+public class SearchResultPeopleView extends LinearLayout implements
+ AllAppsSearchBarController.PayloadResultHandler<Bundle> {
+
+ private final int mIconSize;
+ private final int mButtonSize;
+ private final PackageManager mPackageManager;
+ View mIconView;
+ TextView mTitleView;
+ ImageButton[] mProviderButtons = new ImageButton[3];
+
+ public SearchResultPeopleView(Context context) {
+ this(context, null, 0);
+ }
+
+ public SearchResultPeopleView(Context context,
+ @Nullable AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public SearchResultPeopleView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ DeviceProfile deviceProfile = Launcher.getLauncher(getContext()).getDeviceProfile();
+ mPackageManager = getContext().getPackageManager();
+ mIconSize = deviceProfile.iconSizePx;
+ mButtonSize = (int) (deviceProfile.iconSizePx / 1.5f);
+ }
+
+ @Override
+ protected void onFinishInflate() {
+ super.onFinishInflate();
+ mIconView = findViewById(R.id.icon);
+ mIconView.getLayoutParams().height = mIconSize;
+ mIconView.getLayoutParams().width = mIconSize;
+ mTitleView = findViewById(R.id.title);
+ mProviderButtons[0] = findViewById(R.id.provider_0);
+ mProviderButtons[1] = findViewById(R.id.provider_1);
+ mProviderButtons[2] = findViewById(R.id.provider_2);
+ for (ImageButton button : mProviderButtons) {
+ button.getLayoutParams().width = mButtonSize;
+ button.getLayoutParams().height = mButtonSize;
+ }
+ setOnClickListener(v -> handleSelection());
+ }
+
+ @Override
+ public void applyAdapterInfo(
+ AllAppsGridAdapter.AdapterItemWithPayload<Bundle> adapterItemWithPayload) {
+ Launcher launcher = Launcher.getLauncher(getContext());
+ Bundle payload = adapterItemWithPayload.getPayload();
+ mTitleView.setText(payload.getString("title"));
+ mContactUri = payload.getParcelable("contact_uri");
+ Bitmap icon = payload.getParcelable("icon");
+ if (icon != null) {
+ RoundedBitmapDrawable d = RoundedBitmapDrawableFactory.create(getResources(), icon);
+ float radius = Themes.getDialogCornerRadius(getContext());
+ d.setCornerRadius(radius);
+ d.setBounds(0, 0, mIconSize, mIconSize);
+ BitmapDrawable bitmapDrawable = new BitmapDrawable(getResources(),
+ Bitmap.createScaledBitmap(icon, mIconSize, mIconSize, false));
+ mIconView.setBackground(d);
+ }
+
+ ArrayList<Bundle> providers = payload.getParcelableArrayList("providers");
+ for (int i = 0; i < mProviderButtons.length; i++) {
+ ImageButton button = mProviderButtons[i];
+ if (providers != null && i < providers.size()) {
+ try {
+ Bundle provider = providers.get(i);
+ Intent intent = Intent.parseUri(provider.getString("intent_uri_str"),
+ URI_ANDROID_APP_SCHEME | URI_ALLOW_UNSAFE);
+ String pkg = provider.getString("package_name");
+ button.setOnClickListener(b -> launcher.startActivitySafely(b, intent, null));
+ UI_HELPER_EXECUTOR.post(() -> {
+ try {
+ ApplicationInfo applicationInfo = mPackageManager.getApplicationInfo(
+ pkg, 0);
+ Drawable appIcon = applicationInfo.loadIcon(mPackageManager);
+ button.setImageDrawable(appIcon);
+ } catch (PackageManager.NameNotFoundException ignored) {
+ }
+
+ });
+ } catch (URISyntaxException ex) {
+ button.setVisibility(GONE);
+ }
+ } else {
+ button.setVisibility(GONE);
+ }
+ }
+ adapterItemWithPayload.setSelectionHandler(this::handleSelection);
+ }
+
+ Uri mContactUri;
+
+ private void handleSelection() {
+ if (mContactUri != null) {
+ Launcher launcher = Launcher.getLauncher(getContext());
+ launcher.startActivitySafely(this, new Intent(Intent.ACTION_VIEW, mContactUri).setFlags(
+ Intent.FLAG_ACTIVITY_NEW_TASK), null);
+ }
+ }
+}