Align fallback result query with result text

screenshot: https://screenshot.googleplex.com/6Daj5vdmz2jmznX
bug: 169438169
test: Manual
Change-Id: Ie621ed3c834aec5e9467607da4f685d05d152183
This commit is contained in:
Samuel Fufa 2020-10-06 18:37:46 -07:00
parent 73ae75474e
commit 4b7f38b8fa
10 changed files with 99 additions and 190 deletions

View File

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?><!-- Copyright (C) 2020 The Android Open Source Project <?xml version="1.0" encoding="utf-8"?><!-- Copyright (C) 2020 The Android Open Source Projectza
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.

View File

@ -67,7 +67,6 @@
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="start|center_vertical" android:layout_gravity="start|center_vertical"
android:background="?android:attr/selectableItemBackground"
android:text="@string/search_action_try_now"> android:text="@string/search_action_try_now">
</Button> </Button>

View File

@ -12,27 +12,24 @@
See the License for the specific language governing permissions and See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
--> -->
<com.android.launcher3.views.SearchResultSuggestRow xmlns:android="http://schemas.android.com/apk/res/android" <com.android.launcher3.views.SearchResultIconRow xmlns:android="http://schemas.android.com/apk/res/android"
style="@style/TextHeadline" xmlns:launcher="http://schemas.android.com/apk/res-auto"
android:id="@+id/section_title" style="@style/BaseIcon"
android:background="?android:attr/selectableItemBackground"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="vertical" android:orientation="horizontal"
android:gravity="center_vertical" android:gravity="start|center_vertical"
android:padding="4dp" android:textAlignment="viewStart"
android:minHeight="48dp"
android:textColor="?android:attr/textColorPrimary" android:textColor="?android:attr/textColorPrimary"
android:textSize="14sp"> android:textSize="16sp"
android:padding="@dimen/dynamic_grid_edge_margin"
launcher:iconDisplay="hero_app"
android:drawableTint="?android:attr/textColorPrimary"
launcher:customIcon="@drawable/ic_allapps_search"
launcher:iconSizeOverride="24dp"
launcher:matchTextInsetWithQuery="true"
launcher:layoutHorizontal="true"
android:drawablePadding="@dimen/dynamic_grid_icon_drawable_padding"
>
<TextView </com.android.launcher3.views.SearchResultIconRow>
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>

View File

@ -18,6 +18,7 @@
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:fontFamily="@style/TextHeadline" android:fontFamily="@style/TextHeadline"
android:textStyle="bold"
android:padding="4dp" android:padding="4dp"
android:textColor="?android:attr/textColorPrimary" android:textColor="?android:attr/textColorPrimary"
android:textSize="14sp" /> android:textSize="14sp" />

View File

@ -69,6 +69,13 @@
<attr name="folderDotColor" /> <attr name="folderDotColor" />
</declare-styleable> </declare-styleable>
<declare-styleable name="SearchResultIconRow">
<attr name="customIcon" format="reference" />
<attr name="matchTextInsetWithQuery" format="boolean" />
</declare-styleable>
<declare-styleable name="ShadowInfo"> <declare-styleable name="ShadowInfo">
<attr name="ambientShadowColor" format="color" /> <attr name="ambientShadowColor" format="color" />
<attr name="ambientShadowBlur" format="dimension" /> <attr name="ambientShadowBlur" format="dimension" />

View File

@ -627,7 +627,7 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver,
/** /**
* Sets the icon for this view based on the layout direction. * Sets the icon for this view based on the layout direction.
*/ */
private void setIcon(Drawable icon) { protected void setIcon(Drawable icon) {
if (mIsIconVisible) { if (mIsIconVisible) {
applyCompoundDrawables(icon); applyCompoundDrawables(icon);
} }

View File

@ -68,16 +68,16 @@ public class AllAppsTransitionController implements StateHandler<LauncherState>,
public static final FloatProperty<AllAppsTransitionController> ALL_APPS_PROGRESS = public static final FloatProperty<AllAppsTransitionController> ALL_APPS_PROGRESS =
new FloatProperty<AllAppsTransitionController>("allAppsProgress") { new FloatProperty<AllAppsTransitionController>("allAppsProgress") {
@Override @Override
public Float get(AllAppsTransitionController controller) { public Float get(AllAppsTransitionController controller) {
return controller.mProgress; return controller.mProgress;
} }
@Override @Override
public void setValue(AllAppsTransitionController controller, float progress) { public void setValue(AllAppsTransitionController controller, float progress) {
controller.setProgress(progress); controller.setProgress(progress);
} }
}; };
private static final int APPS_VIEW_ALPHA_CHANNEL_INDEX = 0; private static final int APPS_VIEW_ALPHA_CHANNEL_INDEX = 0;
@ -133,7 +133,6 @@ public class AllAppsTransitionController implements StateHandler<LauncherState>,
* in xml-based animations which also handle updating the appropriate UI. * in xml-based animations which also handle updating the appropriate UI.
* *
* @param progress value between 0 and 1, 0 shows all apps and 1 shows workspace * @param progress value between 0 and 1, 0 shows all apps and 1 shows workspace
*
* @see #setState(LauncherState) * @see #setState(LauncherState)
* @see #setStateWithAnimation(LauncherState, StateAnimationConfig, PendingAnimation) * @see #setStateWithAnimation(LauncherState, StateAnimationConfig, PendingAnimation)
*/ */
@ -238,7 +237,7 @@ public class AllAppsTransitionController implements StateHandler<LauncherState>,
mInsetController = new AllAppsInsetTransitionController(mShiftRange, mAppsView); mInsetController = new AllAppsInsetTransitionController(mShiftRange, mAppsView);
mLauncher.getSystemUiController().updateUiState(UI_STATE_ALLAPPS, mLauncher.getSystemUiController().updateUiState(UI_STATE_ALLAPPS,
View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_LAYOUT_STABLE); | View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
} }
} }

View File

@ -96,8 +96,6 @@ public class HeroSearchResultView extends LinearLayout implements DragSource,
launcher.getItemOnClickListener().onClick(view); launcher.getItemOnClickListener().onClick(view);
}); });
mBubbleTextView.setOnLongClickListener(new HeroItemDragHandler(getContext(), this)); mBubbleTextView.setOnLongClickListener(new HeroItemDragHandler(getContext(), this));
setLayoutParams(
new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, grid.allAppsCellHeightPx));
mDeepShortcutTextViews[0] = findViewById(R.id.shortcut_0); mDeepShortcutTextViews[0] = findViewById(R.id.shortcut_0);

View File

@ -22,16 +22,19 @@ import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
import android.app.RemoteAction; import android.app.RemoteAction;
import android.content.Context; import android.content.Context;
import android.content.pm.ShortcutInfo; import android.content.pm.ShortcutInfo;
import android.content.res.TypedArray;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
import android.os.Build; import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.widget.EditText;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import com.android.launcher3.Launcher; import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherAppState; import com.android.launcher3.LauncherAppState;
import com.android.launcher3.R;
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.icons.BitmapInfo; import com.android.launcher3.icons.BitmapInfo;
@ -53,25 +56,51 @@ public class SearchResultIconRow extends DoubleShadowBubbleTextView implements
AllAppsSearchBarController.PayloadResultHandler<SearchTarget> { AllAppsSearchBarController.PayloadResultHandler<SearchTarget> {
private final Object[] mTargetInfo = createTargetInfo(); private final Object[] mTargetInfo = createTargetInfo();
private final int mCustomIconResId;
private final boolean mMatchesInset;
private ShortcutInfo mShortcutInfo; private ShortcutInfo mShortcutInfo;
private AllAppsSearchPlugin mPlugin; private AllAppsSearchPlugin mPlugin;
private AdapterItemWithPayload<SearchTarget> mAdapterItem; private AdapterItemWithPayload<SearchTarget> mAdapterItem;
public SearchResultIconRow(@NonNull Context context) { public SearchResultIconRow(@NonNull Context context) {
super(context); this(context, null, 0);
} }
public SearchResultIconRow(@NonNull Context context, public SearchResultIconRow(@NonNull Context context,
@Nullable AttributeSet attrs) { @Nullable AttributeSet attrs) {
super(context, attrs); this(context, attrs, 0);
} }
public SearchResultIconRow(@NonNull Context context, @Nullable AttributeSet attrs, public SearchResultIconRow(@NonNull Context context, @Nullable AttributeSet attrs,
int defStyleAttr) { int defStyleAttr) {
super(context, attrs, defStyleAttr); super(context, attrs, defStyleAttr);
TypedArray a = context.obtainStyledAttributes(attrs,
R.styleable.SearchResultIconRow, defStyleAttr, 0);
mCustomIconResId = a.getResourceId(R.styleable.SearchResultIconRow_customIcon, 0);
mMatchesInset = a.getBoolean(R.styleable.SearchResultIconRow_matchTextInsetWithQuery,
false);
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());
}
}
}
@Override @Override
public void applyAdapterInfo(AdapterItemWithPayload<SearchTarget> adapterItemWithPayload) { public void applyAdapterInfo(AdapterItemWithPayload<SearchTarget> adapterItemWithPayload) {
if (mAdapterItem != null) { if (mAdapterItem != null) {
@ -98,10 +127,12 @@ public class SearchResultIconRow extends DoubleShadowBubbleTextView implements
WorkspaceItemInfo workspaceItemInfo = new WorkspaceItemInfo(mShortcutInfo, getContext()); WorkspaceItemInfo workspaceItemInfo = new WorkspaceItemInfo(mShortcutInfo, getContext());
applyFromWorkspaceItem(workspaceItemInfo); applyFromWorkspaceItem(workspaceItemInfo);
LauncherAppState launcherAppState = LauncherAppState.getInstance(getContext()); LauncherAppState launcherAppState = LauncherAppState.getInstance(getContext());
MODEL_EXECUTOR.execute(() -> { if (!loadIconFromResource()) {
launcherAppState.getIconCache().getShortcutIcon(workspaceItemInfo, mShortcutInfo); MODEL_EXECUTOR.execute(() -> {
reapplyItemInfoAsync(workspaceItemInfo); launcherAppState.getIconCache().getShortcutIcon(workspaceItemInfo, mShortcutInfo);
}); reapplyItemInfoAsync(workspaceItemInfo);
});
}
} }
private void prepareUsingRemoteAction(RemoteAction remoteAction, String token, boolean start, private void prepareUsingRemoteAction(RemoteAction remoteAction, String token, boolean start,
@ -109,27 +140,36 @@ public class SearchResultIconRow extends DoubleShadowBubbleTextView implements
RemoteActionItemInfo itemInfo = new RemoteActionItemInfo(remoteAction, token, start); RemoteActionItemInfo itemInfo = new RemoteActionItemInfo(remoteAction, token, start);
applyFromRemoteActionInfo(itemInfo); applyFromRemoteActionInfo(itemInfo);
UI_HELPER_EXECUTOR.post(() -> { if (!loadIconFromResource()) {
// If the Drawable from the remote action is not AdaptiveBitmap, styling will not work. UI_HELPER_EXECUTOR.post(() -> {
try (LauncherIcons li = LauncherIcons.obtain(getContext())) { // If the Drawable from the remote action is not AdaptiveBitmap, styling will not
Drawable d = itemInfo.getRemoteAction().getIcon().loadDrawable(getContext()); // work.
BitmapInfo bitmap = li.createBadgedIconBitmap(d, itemInfo.user, try (LauncherIcons li = LauncherIcons.obtain(getContext())) {
Build.VERSION.SDK_INT); Drawable d = itemInfo.getRemoteAction().getIcon().loadDrawable(getContext());
BitmapInfo bitmap = li.createBadgedIconBitmap(d, itemInfo.user,
Build.VERSION.SDK_INT);
if (useIconToBadge) { if (useIconToBadge) {
BitmapInfo placeholder = li.createIconBitmap( BitmapInfo placeholder = li.createIconBitmap(
itemInfo.getRemoteAction().getTitle().toString().substring(0, 1), itemInfo.getRemoteAction().getTitle().toString().substring(0, 1),
bitmap.color); bitmap.color);
itemInfo.bitmap = li.badgeBitmap(placeholder.icon, bitmap); itemInfo.bitmap = li.badgeBitmap(placeholder.icon, bitmap);
} else { } else {
itemInfo.bitmap = bitmap; itemInfo.bitmap = bitmap;
}
reapplyItemInfoAsync(itemInfo);
} }
reapplyItemInfoAsync(itemInfo); });
} }
});
} }
private boolean loadIconFromResource() {
if (mCustomIconResId == 0) return false;
setIcon(Launcher.getLauncher(getContext()).getDrawable(mCustomIconResId));
return true;
}
void reapplyItemInfoAsync(ItemInfoWithIcon itemInfoWithIcon) { void reapplyItemInfoAsync(ItemInfoWithIcon itemInfoWithIcon) {
MAIN_EXECUTOR.post(() -> reapplyItemInfo(itemInfoWithIcon)); MAIN_EXECUTOR.post(() -> reapplyItemInfo(itemInfoWithIcon));
} }

View File

@ -1,132 +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.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);
}
}
}