Merge "Thumbnail/Suggest view type support remote action" into ub-launcher3-master
This commit is contained in:
commit
00524e7b86
|
@ -0,0 +1,38 @@
|
||||||
|
<?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.SearchResultSuggestRow xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
style="@style/TextHeadline"
|
||||||
|
android:id="@+id/section_title"
|
||||||
|
android:background="?android:attr/selectableItemBackground"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:padding="4dp"
|
||||||
|
android:minHeight="48dp"
|
||||||
|
android:textColor="?android:attr/textColorPrimary"
|
||||||
|
android:textSize="14sp">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/title"
|
||||||
|
style="@style/TextTitle"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:paddingStart="8dp"
|
||||||
|
android:layout_marginBottom="4dp"
|
||||||
|
android:textColor="?android:attr/textColorPrimary"
|
||||||
|
android:textSize="14sp" />
|
||||||
|
|
||||||
|
</com.android.launcher3.views.SearchResultSuggestRow>
|
|
@ -98,6 +98,8 @@ public class AllAppsGridAdapter extends
|
||||||
|
|
||||||
public static final int VIEW_TYPE_SEARCH_THUMBNAIL = 1 << 12;
|
public static final int VIEW_TYPE_SEARCH_THUMBNAIL = 1 << 12;
|
||||||
|
|
||||||
|
public static final int VIEW_TYPE_SEARCH_SUGGEST = 1 << 13;
|
||||||
|
|
||||||
// Common view type masks
|
// Common view type masks
|
||||||
public static final int VIEW_TYPE_MASK_DIVIDER = VIEW_TYPE_ALL_APPS_DIVIDER;
|
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;
|
||||||
|
@ -189,7 +191,8 @@ public class AllAppsGridAdapter extends
|
||||||
|| viewType == VIEW_TYPE_SEARCH_ROW
|
|| viewType == VIEW_TYPE_SEARCH_ROW
|
||||||
|| viewType == VIEW_TYPE_SEARCH_PEOPLE
|
|| viewType == VIEW_TYPE_SEARCH_PEOPLE
|
||||||
|| viewType == VIEW_TYPE_SEARCH_THUMBNAIL
|
|| viewType == VIEW_TYPE_SEARCH_THUMBNAIL
|
||||||
|| viewType == VIEW_TYPE_SEARCH_ICON_ROW;
|
|| viewType == VIEW_TYPE_SEARCH_ICON_ROW
|
||||||
|
|| viewType == VIEW_TYPE_SEARCH_SUGGEST;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -467,6 +470,9 @@ public class AllAppsGridAdapter extends
|
||||||
case VIEW_TYPE_SEARCH_THUMBNAIL:
|
case VIEW_TYPE_SEARCH_THUMBNAIL:
|
||||||
return new ViewHolder(mLayoutInflater.inflate(
|
return new ViewHolder(mLayoutInflater.inflate(
|
||||||
R.layout.search_result_thumbnail, parent, false));
|
R.layout.search_result_thumbnail, parent, false));
|
||||||
|
case VIEW_TYPE_SEARCH_SUGGEST:
|
||||||
|
return new ViewHolder(mLayoutInflater.inflate(
|
||||||
|
R.layout.search_result_suggest, parent, false));
|
||||||
default:
|
default:
|
||||||
throw new RuntimeException("Unexpected view type");
|
throw new RuntimeException("Unexpected view type");
|
||||||
}
|
}
|
||||||
|
@ -554,6 +560,7 @@ public class AllAppsGridAdapter extends
|
||||||
case VIEW_TYPE_SEARCH_ICON_ROW:
|
case VIEW_TYPE_SEARCH_ICON_ROW:
|
||||||
case VIEW_TYPE_SEARCH_PEOPLE:
|
case VIEW_TYPE_SEARCH_PEOPLE:
|
||||||
case VIEW_TYPE_SEARCH_THUMBNAIL:
|
case VIEW_TYPE_SEARCH_THUMBNAIL:
|
||||||
|
case VIEW_TYPE_SEARCH_SUGGEST:
|
||||||
AdapterItemWithPayload item =
|
AdapterItemWithPayload item =
|
||||||
(AdapterItemWithPayload) mApps.getAdapterItems().get(position);
|
(AdapterItemWithPayload) mApps.getAdapterItems().get(position);
|
||||||
PayloadResultHandler payloadResultView = (PayloadResultHandler) holder.itemView;
|
PayloadResultHandler payloadResultView = (PayloadResultHandler) holder.itemView;
|
||||||
|
|
|
@ -0,0 +1,131 @@
|
||||||
|
/*
|
||||||
|
* 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.systemui.plugins.shared.SearchTarget.ItemType.SUGGEST;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.text.TextUtils;
|
||||||
|
import android.util.AttributeSet;
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.LinearLayout;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
|
import com.android.launcher3.Launcher;
|
||||||
|
import com.android.launcher3.R;
|
||||||
|
import com.android.launcher3.allapps.AllAppsGridAdapter.AdapterItemWithPayload;
|
||||||
|
import com.android.launcher3.allapps.search.AllAppsSearchBarController;
|
||||||
|
import com.android.launcher3.model.data.ItemInfo;
|
||||||
|
import com.android.launcher3.model.data.RemoteActionItemInfo;
|
||||||
|
import com.android.launcher3.touch.ItemClickHandler;
|
||||||
|
import com.android.systemui.plugins.AllAppsSearchPlugin;
|
||||||
|
import com.android.systemui.plugins.shared.SearchTarget;
|
||||||
|
import com.android.systemui.plugins.shared.SearchTargetEvent;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A view representing a fallback search suggestion row.
|
||||||
|
*/
|
||||||
|
public class SearchResultSuggestRow extends LinearLayout implements
|
||||||
|
View.OnClickListener, AllAppsSearchBarController.PayloadResultHandler<SearchTarget> {
|
||||||
|
|
||||||
|
private final Object[] mTargetInfo = createTargetInfo();
|
||||||
|
private AllAppsSearchPlugin mPlugin;
|
||||||
|
private AdapterItemWithPayload<SearchTarget> mAdapterItem;
|
||||||
|
private TextView mTitle;
|
||||||
|
|
||||||
|
|
||||||
|
public SearchResultSuggestRow(@NonNull Context context) {
|
||||||
|
super(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
public SearchResultSuggestRow(@NonNull Context context,
|
||||||
|
@Nullable AttributeSet attrs) {
|
||||||
|
super(context, attrs);
|
||||||
|
}
|
||||||
|
|
||||||
|
public SearchResultSuggestRow(@NonNull Context context, @Nullable AttributeSet attrs,
|
||||||
|
int defStyleAttr) {
|
||||||
|
super(context, attrs, defStyleAttr);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onFinishInflate() {
|
||||||
|
super.onFinishInflate();
|
||||||
|
mTitle = findViewById(R.id.title);
|
||||||
|
setOnClickListener(this);
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void applyAdapterInfo(AdapterItemWithPayload<SearchTarget> adapterItemWithPayload) {
|
||||||
|
mAdapterItem = adapterItemWithPayload;
|
||||||
|
SearchTarget payload = adapterItemWithPayload.getPayload();
|
||||||
|
mPlugin = adapterItemWithPayload.getPlugin();
|
||||||
|
|
||||||
|
if (payload.mRemoteAction != null) {
|
||||||
|
RemoteActionItemInfo itemInfo = new RemoteActionItemInfo(payload.mRemoteAction,
|
||||||
|
payload.bundle.getString(SearchTarget.REMOTE_ACTION_TOKEN),
|
||||||
|
payload.bundle.getBoolean(SearchTarget.REMOTE_ACTION_SHOULD_START));
|
||||||
|
setTag(itemInfo);
|
||||||
|
}
|
||||||
|
showIfAvailable(mTitle, payload.mRemoteAction.getTitle().toString());
|
||||||
|
setOnClickListener(v -> handleSelection(SearchTargetEvent.SELECT));
|
||||||
|
adapterItemWithPayload.setSelectionHandler(this::handleSelection);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object[] getTargetInfo() {
|
||||||
|
return mTargetInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleSelection(int eventType) {
|
||||||
|
ItemInfo itemInfo = (ItemInfo) getTag();
|
||||||
|
Launcher launcher = Launcher.getLauncher(getContext());
|
||||||
|
if (itemInfo instanceof RemoteActionItemInfo) return;
|
||||||
|
|
||||||
|
RemoteActionItemInfo remoteItemInfo = (RemoteActionItemInfo) itemInfo;
|
||||||
|
ItemClickHandler.onClickRemoteAction(launcher, remoteItemInfo);
|
||||||
|
SearchTargetEvent searchTargetEvent = getSearchTargetEvent(SUGGEST, eventType);
|
||||||
|
searchTargetEvent.bundle = new Bundle();
|
||||||
|
searchTargetEvent.remoteAction = remoteItemInfo.getRemoteAction();
|
||||||
|
searchTargetEvent.bundle.putBoolean(SearchTarget.REMOTE_ACTION_SHOULD_START,
|
||||||
|
remoteItemInfo.shouldStartInLauncher());
|
||||||
|
searchTargetEvent.bundle.putString(SearchTarget.REMOTE_ACTION_TOKEN,
|
||||||
|
remoteItemInfo.getToken());
|
||||||
|
|
||||||
|
if (mPlugin != null) {
|
||||||
|
mPlugin.notifySearchTargetEvent(searchTargetEvent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onClick(View view) {
|
||||||
|
handleSelection(SearchTargetEvent.SELECT);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void showIfAvailable(TextView view, @Nullable String string) {
|
||||||
|
System.out.println("Plugin suggest string:" + string);
|
||||||
|
if (TextUtils.isEmpty(string)) {
|
||||||
|
view.setVisibility(GONE);
|
||||||
|
} else {
|
||||||
|
System.out.println("Plugin suggest string:" + string);
|
||||||
|
view.setVisibility(VISIBLE);
|
||||||
|
view.setText(string);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -18,8 +18,8 @@ package com.android.launcher3.views;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.graphics.Bitmap;
|
import android.graphics.Bitmap;
|
||||||
|
import android.graphics.drawable.BitmapDrawable;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.Bundle;
|
|
||||||
import android.util.AttributeSet;
|
import android.util.AttributeSet;
|
||||||
|
|
||||||
import androidx.core.graphics.drawable.RoundedBitmapDrawable;
|
import androidx.core.graphics.drawable.RoundedBitmapDrawable;
|
||||||
|
@ -28,6 +28,10 @@ import androidx.core.graphics.drawable.RoundedBitmapDrawableFactory;
|
||||||
import com.android.launcher3.Launcher;
|
import com.android.launcher3.Launcher;
|
||||||
import com.android.launcher3.allapps.AllAppsGridAdapter.AdapterItemWithPayload;
|
import com.android.launcher3.allapps.AllAppsGridAdapter.AdapterItemWithPayload;
|
||||||
import com.android.launcher3.allapps.search.AllAppsSearchBarController;
|
import com.android.launcher3.allapps.search.AllAppsSearchBarController;
|
||||||
|
import com.android.launcher3.model.data.ItemInfo;
|
||||||
|
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.launcher3.util.Themes;
|
||||||
import com.android.systemui.plugins.AllAppsSearchPlugin;
|
import com.android.systemui.plugins.AllAppsSearchPlugin;
|
||||||
import com.android.systemui.plugins.shared.SearchTarget;
|
import com.android.systemui.plugins.shared.SearchTarget;
|
||||||
|
@ -37,10 +41,9 @@ import com.android.systemui.plugins.shared.SearchTargetEvent;
|
||||||
* A view representing a high confidence app search result that includes shortcuts
|
* A view representing a high confidence app search result that includes shortcuts
|
||||||
*/
|
*/
|
||||||
public class ThumbnailSearchResultView extends androidx.appcompat.widget.AppCompatImageView
|
public class ThumbnailSearchResultView extends androidx.appcompat.widget.AppCompatImageView
|
||||||
implements AllAppsSearchBarController.PayloadResultHandler<Bundle> {
|
implements AllAppsSearchBarController.PayloadResultHandler<SearchTarget> {
|
||||||
|
|
||||||
private final Object[] mTargetInfo = createTargetInfo();
|
private final Object[] mTargetInfo = createTargetInfo();
|
||||||
Intent mIntent;
|
|
||||||
AllAppsSearchPlugin mPlugin;
|
AllAppsSearchPlugin mPlugin;
|
||||||
int mPosition;
|
int mPosition;
|
||||||
|
|
||||||
|
@ -58,26 +61,48 @@ public class ThumbnailSearchResultView extends androidx.appcompat.widget.AppComp
|
||||||
|
|
||||||
private void handleSelection(int eventType) {
|
private void handleSelection(int eventType) {
|
||||||
Launcher launcher = Launcher.getLauncher(getContext());
|
Launcher launcher = Launcher.getLauncher(getContext());
|
||||||
launcher.startActivitySafely(this, mIntent, null);
|
ItemInfo itemInfo = (ItemInfo) getTag();
|
||||||
|
if (itemInfo instanceof RemoteActionItemInfo) {
|
||||||
|
RemoteActionItemInfo remoteItemInfo = (RemoteActionItemInfo) itemInfo;
|
||||||
|
ItemClickHandler.onClickRemoteAction(launcher, remoteItemInfo);
|
||||||
|
} else {
|
||||||
|
ItemClickHandler.onClickAppShortcut(this, (WorkspaceItemInfo) itemInfo, launcher);
|
||||||
|
}
|
||||||
|
if (mPlugin != null) {
|
||||||
SearchTargetEvent event = getSearchTargetEvent(
|
SearchTargetEvent event = getSearchTargetEvent(
|
||||||
SearchTarget.ItemType.SCREENSHOT, eventType);
|
SearchTarget.ItemType.SCREENSHOT, eventType);
|
||||||
if (mPlugin != null) {
|
|
||||||
mPlugin.notifySearchTargetEvent(event);
|
mPlugin.notifySearchTargetEvent(event);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void applyAdapterInfo(AdapterItemWithPayload<Bundle> adapterItem) {
|
public void applyAdapterInfo(AdapterItemWithPayload<SearchTarget> adapterItem) {
|
||||||
|
Launcher launcher = Launcher.getLauncher(getContext());
|
||||||
mPosition = adapterItem.position;
|
mPosition = adapterItem.position;
|
||||||
RoundedBitmapDrawable drawable = RoundedBitmapDrawableFactory.create(null,
|
|
||||||
(Bitmap) adapterItem.getPayload().getParcelable("bitmap"));
|
SearchTarget target = adapterItem.getPayload();
|
||||||
drawable.setCornerRadius(Themes.getDialogCornerRadius(getContext()));
|
Bitmap bitmap;
|
||||||
setImageDrawable(drawable);
|
if (target.mRemoteAction != null) {
|
||||||
mIntent = new Intent(Intent.ACTION_VIEW)
|
RemoteActionItemInfo itemInfo = new RemoteActionItemInfo(target.mRemoteAction,
|
||||||
.setData(Uri.parse(adapterItem.getPayload().getString("uri")))
|
target.bundle.getString(SearchTarget.REMOTE_ACTION_TOKEN),
|
||||||
|
target.bundle.getBoolean(SearchTarget.REMOTE_ACTION_SHOULD_START));
|
||||||
|
ItemClickHandler.onClickRemoteAction(launcher, itemInfo);
|
||||||
|
bitmap = ((BitmapDrawable) target.mRemoteAction.getIcon()
|
||||||
|
.loadDrawable(getContext())).getBitmap();
|
||||||
|
setTag(itemInfo);
|
||||||
|
} else {
|
||||||
|
bitmap = (Bitmap) target.bundle.getParcelable("bitmap");
|
||||||
|
WorkspaceItemInfo itemInfo = new WorkspaceItemInfo();
|
||||||
|
itemInfo.intent = new Intent(Intent.ACTION_VIEW)
|
||||||
|
.setData(Uri.parse(target.bundle.getString("uri")))
|
||||||
.setType("image/*")
|
.setType("image/*")
|
||||||
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||||
|
setTag(itemInfo);
|
||||||
|
}
|
||||||
|
RoundedBitmapDrawable drawable = RoundedBitmapDrawableFactory.create(null, bitmap);
|
||||||
|
drawable.setCornerRadius(Themes.getDialogCornerRadius(getContext()));
|
||||||
|
setImageDrawable(drawable);
|
||||||
|
setOnClickListener(v -> handleSelection(SearchTargetEvent.SELECT));
|
||||||
mPlugin = adapterItem.getPlugin();
|
mPlugin = adapterItem.getPlugin();
|
||||||
adapterItem.setSelectionHandler(this::handleSelection);
|
adapterItem.setSelectionHandler(this::handleSelection);
|
||||||
}
|
}
|
||||||
|
|
|
@ -80,7 +80,12 @@ public class SearchTarget implements Comparable<SearchTarget> {
|
||||||
* N number of 1x1 ratio thumbnail is rendered.
|
* N number of 1x1 ratio thumbnail is rendered.
|
||||||
* (current N = 3)
|
* (current N = 3)
|
||||||
*/
|
*/
|
||||||
THUMBNAIL(8);
|
THUMBNAIL(8),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fallback search icon and relevant text is rendered.
|
||||||
|
*/
|
||||||
|
SUGGEST(9);
|
||||||
|
|
||||||
private final int mId;
|
private final int mId;
|
||||||
|
|
||||||
|
@ -102,7 +107,8 @@ public class SearchTarget implements Comparable<SearchTarget> {
|
||||||
SHORTCUT(5, "Shortcuts", ViewType.SHORTCUT),
|
SHORTCUT(5, "Shortcuts", ViewType.SHORTCUT),
|
||||||
PEOPLE(6, "People", ViewType.PEOPLE),
|
PEOPLE(6, "People", ViewType.PEOPLE),
|
||||||
SCREENSHOT(7, "Screenshots", ViewType.THUMBNAIL),
|
SCREENSHOT(7, "Screenshots", ViewType.THUMBNAIL),
|
||||||
REMOTE_ACTION(8, "Remote Actions", ViewType.SHORTCUT);
|
REMOTE_ACTION(8, "Remote Actions", ViewType.SHORTCUT),
|
||||||
|
SUGGEST(9, "Fallback Search", ViewType.SUGGEST);
|
||||||
|
|
||||||
private final int mId;
|
private final int mId;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue