Show settings icon at start of settings results
Bug: 170792963 Test: Manual Screenshot: https://screenshot.googleplex.com/MVBtDZGtQ3aChwU Change-Id: I16a28a7bd9e3129b40102e020cd7c0111e6fe29b
This commit is contained in:
parent
d15915f5fd
commit
984e0d0a63
|
@ -40,13 +40,13 @@
|
|||
android:gravity="start|center_vertical"
|
||||
android:textAlignment="viewStart"
|
||||
android:textColor="?android:attr/textColorPrimary"
|
||||
android:textSize="@dimen/settings_hero_title_size" />
|
||||
android:textSize="@dimen/search_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:textSize="@dimen/search_hero_subtitle_size"
|
||||
android:layout_height="wrap_content" />
|
||||
</LinearLayout>
|
||||
|
||||
|
@ -57,7 +57,7 @@
|
|||
android:layout_height="match_parent"
|
||||
android:gravity="start|center_vertical"
|
||||
launcher:iconDisplay="shortcut_popup"
|
||||
android:textSize="@dimen/settings_hero_subtitle_size"
|
||||
android:textSize="@dimen/search_hero_subtitle_size"
|
||||
launcher:iconSizeOverride="@dimen/deep_shortcut_icon_size"
|
||||
launcher:layoutHorizontal="false" />
|
||||
|
||||
|
@ -67,7 +67,7 @@
|
|||
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"
|
||||
android:textSize="@dimen/search_hero_inline_button_size"
|
||||
launcher:iconSizeOverride="@dimen/deep_shortcut_icon_size"
|
||||
launcher:layoutHorizontal="false" />
|
||||
|
||||
|
|
|
@ -18,40 +18,42 @@
|
|||
android:background="?android:attr/selectableItemBackground"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:orientation="horizontal"
|
||||
android:gravity="center_vertical"
|
||||
android:padding="4dp"
|
||||
android:minHeight="48dp"
|
||||
android:textColor="?android:attr/textColorPrimary"
|
||||
android:textSize="14sp">
|
||||
android:padding="@dimen/dynamic_grid_cell_padding_x"
|
||||
android:textColor="?android:attr/textColorPrimary">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/title"
|
||||
style="@style/TextTitle"
|
||||
android:layout_width="wrap_content"
|
||||
<View
|
||||
android:layout_width="@dimen/search_settings_icon_size"
|
||||
android:src="@drawable/ic_setting"
|
||||
android:id="@+id/icon"
|
||||
android:layout_height="@dimen/search_settings_icon_size" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="0dp"
|
||||
android:orientation="vertical"
|
||||
android:paddingRight="@dimen/dynamic_grid_cell_padding_x"
|
||||
android:paddingLeft="@dimen/dynamic_grid_cell_padding_x"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="4dp"
|
||||
android:textColor="?android:attr/textColorPrimary"
|
||||
android:textSize="16sp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/description"
|
||||
style="@style/TextTitle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:visibility="gone"
|
||||
android:textColor="?android:attr/textColorPrimary"
|
||||
android:textSize="14sp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/breadcrumbs"
|
||||
style="@style/TextTitle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:visibility="gone"
|
||||
android:alpha=".7"
|
||||
android:textColor="?android:attr/textColorSecondary"
|
||||
android:textSize="14sp" />
|
||||
android:layout_weight="1">
|
||||
|
||||
|
||||
<TextView
|
||||
android:id="@+id/title"
|
||||
style="@style/TextTitle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="@dimen/search_line_spacing"
|
||||
android:textColor="?android:attr/textColorPrimary"
|
||||
android:textSize="@dimen/search_hero_title_size" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/breadcrumbs"
|
||||
style="@style/TextTitle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:visibility="gone"
|
||||
android:textColor="?android:attr/textColorSecondary"
|
||||
android:textSize="@dimen/search_hero_subtitle_size" />
|
||||
</LinearLayout>
|
||||
</com.android.launcher3.views.SearchSettingsRowView>
|
|
@ -1,5 +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 Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
@ -13,7 +12,29 @@
|
|||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
<androidx.slice.widget.SliceView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<com.android.launcher3.views.SearchResultSettingsSlice xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:paddingHorizontal="@dimen/dynamic_grid_cell_padding_x"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingHorizontal="4dp" />
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<FrameLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:paddingTop="@dimen/search_settings_icon_vertical_offset"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<View
|
||||
android:layout_width="@dimen/search_settings_icon_size"
|
||||
android:src="@drawable/ic_setting"
|
||||
android:id="@+id/icon"
|
||||
android:layout_height="@dimen/search_settings_icon_size" />
|
||||
</FrameLayout>
|
||||
|
||||
<androidx.slice.widget.SliceView
|
||||
android:id="@+id/slice"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:layout_marginStart="@dimen/dynamic_grid_cell_padding_x"
|
||||
android:layout_width="0dp" />
|
||||
|
||||
</com.android.launcher3.views.SearchResultSettingsSlice>
|
||||
|
||||
|
|
|
@ -249,8 +249,11 @@
|
|||
<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>
|
||||
<dimen name="search_hero_title_size">16sp</dimen>
|
||||
<dimen name="search_hero_subtitle_size">15sp</dimen>
|
||||
<dimen name="search_hero_inline_button_size">12sp</dimen>
|
||||
<dimen name="search_settings_icon_size">36dp</dimen>
|
||||
<dimen name="search_settings_icon_vertical_offset">16dp</dimen>
|
||||
<dimen name="search_line_spacing">4dp</dimen>
|
||||
|
||||
</resources>
|
||||
|
|
|
@ -37,7 +37,6 @@ import androidx.core.view.accessibility.AccessibilityNodeInfoCompat;
|
|||
import androidx.core.view.accessibility.AccessibilityRecordCompat;
|
||||
import androidx.recyclerview.widget.GridLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import androidx.slice.widget.SliceView;
|
||||
|
||||
import com.android.launcher3.BaseDraggingActivity;
|
||||
import com.android.launcher3.BubbleTextView;
|
||||
|
@ -47,7 +46,6 @@ 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.SearchSliceWrapper;
|
||||
import com.android.systemui.plugins.shared.SearchTarget;
|
||||
|
||||
import java.util.List;
|
||||
|
@ -461,17 +459,10 @@ public class AllAppsGridAdapter extends
|
|||
} else {
|
||||
searchView.setVisibility(View.GONE);
|
||||
}
|
||||
break;
|
||||
case VIEW_TYPE_SEARCH_SLICE:
|
||||
SliceView sliceView = (SliceView) holder.itemView;
|
||||
SearchAdapterItem slicePayload = (SearchAdapterItem) mApps.getAdapterItems().get(
|
||||
position);
|
||||
SearchTarget searchTarget = slicePayload.getSearchTarget();
|
||||
sliceView.setTag(new SearchSliceWrapper(mLauncher, sliceView, searchTarget));
|
||||
|
||||
break;
|
||||
case VIEW_TYPE_SEARCH_CORPUS_TITLE:
|
||||
case VIEW_TYPE_SEARCH_ROW_WITH_BUTTON:
|
||||
case VIEW_TYPE_SEARCH_SLICE:
|
||||
case VIEW_TYPE_SEARCH_ROW:
|
||||
case VIEW_TYPE_SEARCH_ICON:
|
||||
case VIEW_TYPE_SEARCH_ICON_ROW:
|
||||
|
@ -496,13 +487,6 @@ public class AllAppsGridAdapter extends
|
|||
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();
|
||||
}
|
||||
sliceView.setTag(null);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -17,9 +17,13 @@ package com.android.launcher3.views;
|
|||
|
||||
import android.content.Context;
|
||||
import android.net.Uri;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.widget.LinearLayout;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.lifecycle.LiveData;
|
||||
import androidx.slice.Slice;
|
||||
import androidx.slice.SliceItem;
|
||||
|
@ -28,55 +32,98 @@ import androidx.slice.widget.SliceLiveData;
|
|||
import androidx.slice.widget.SliceView;
|
||||
|
||||
import com.android.launcher3.Launcher;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.allapps.search.AllAppsSearchBarController;
|
||||
import com.android.launcher3.allapps.search.SearchEventTracker;
|
||||
import com.android.systemui.plugins.shared.SearchTarget;
|
||||
import com.android.systemui.plugins.shared.SearchTargetEvent;
|
||||
|
||||
/**
|
||||
* A Wrapper class for {@link SliceView} search results
|
||||
* A slice view wrapper with settings app icon at start
|
||||
*/
|
||||
public class SearchSliceWrapper implements SliceView.OnSliceActionListener {
|
||||
public class SearchResultSettingsSlice extends LinearLayout implements
|
||||
AllAppsSearchBarController.SearchTargetHandler, SliceView.OnSliceActionListener {
|
||||
|
||||
|
||||
public static final String TARGET_TYPE_SLICE = "settings_slice";
|
||||
|
||||
private static final String TAG = "SearchSliceController";
|
||||
private static final String URI_EXTRA_KEY = "slice_uri";
|
||||
|
||||
|
||||
private final Launcher mLauncher;
|
||||
private final SearchTarget mSearchTarget;
|
||||
private final SliceView mSliceView;
|
||||
private SliceView mSliceView;
|
||||
private View mIcon;
|
||||
private LiveData<Slice> mSliceLiveData;
|
||||
private SearchTarget mSearchTarget;
|
||||
private Launcher mLauncher;
|
||||
|
||||
public SearchSliceWrapper(Context context, SliceView sliceView, SearchTarget searchTarget) {
|
||||
mLauncher = Launcher.getLauncher(context);
|
||||
public SearchResultSettingsSlice(Context context) {
|
||||
this(context, null, 0);
|
||||
}
|
||||
|
||||
public SearchResultSettingsSlice(Context context,
|
||||
@Nullable AttributeSet attrs) {
|
||||
this(context, attrs, 0);
|
||||
}
|
||||
|
||||
public SearchResultSettingsSlice(Context context, @Nullable AttributeSet attrs,
|
||||
int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
mLauncher = Launcher.getLauncher(getContext());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onFinishInflate() {
|
||||
super.onFinishInflate();
|
||||
mSliceView = findViewById(R.id.slice);
|
||||
mIcon = findViewById(R.id.icon);
|
||||
SearchSettingsRowView.applySettingsIcon(mLauncher, mIcon);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applySearchTarget(SearchTarget searchTarget) {
|
||||
reset();
|
||||
mSearchTarget = searchTarget;
|
||||
mSliceView = sliceView;
|
||||
sliceView.setOnSliceActionListener(this);
|
||||
try {
|
||||
mSliceLiveData = SliceLiveData.fromUri(mLauncher, getSliceUri());
|
||||
mSliceLiveData.observe((Launcher) mLauncher, sliceView);
|
||||
mSliceLiveData.observe(mLauncher, mSliceView);
|
||||
} catch (Exception ex) {
|
||||
Log.e(TAG, "unable to bind slice", ex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregisters event handlers and removes lifecycle observer
|
||||
*/
|
||||
public void destroy() {
|
||||
mSliceView.setOnSliceActionListener(null);
|
||||
mSliceLiveData.removeObservers(mLauncher);
|
||||
@Override
|
||||
protected void onAttachedToWindow() {
|
||||
super.onAttachedToWindow();
|
||||
mSliceView.setOnSliceActionListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSliceAction(@NonNull EventInfo info, @NonNull SliceItem item) {
|
||||
protected void onDetachedFromWindow() {
|
||||
super.onDetachedFromWindow();
|
||||
reset();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleSelection(int eventType) {
|
||||
SearchEventTracker.INSTANCE.get(mLauncher).notifySearchTargetEvent(
|
||||
new SearchTargetEvent.Builder(mSearchTarget,
|
||||
SearchTargetEvent.CHILD_SELECT).build());
|
||||
}
|
||||
|
||||
private void reset() {
|
||||
mSliceView.setOnSliceActionListener(null);
|
||||
if (mSliceLiveData != null) {
|
||||
mSliceLiveData.removeObservers(mLauncher);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSliceAction(@NonNull EventInfo eventInfo, @NonNull SliceItem sliceItem) {
|
||||
handleSelection(SearchTargetEvent.CHILD_SELECT);
|
||||
}
|
||||
|
||||
private Uri getSliceUri() {
|
||||
return mSearchTarget.getExtras().getParcelable(URI_EXTRA_KEY);
|
||||
}
|
||||
|
||||
}
|
|
@ -15,8 +15,14 @@
|
|||
*/
|
||||
package com.android.launcher3.views;
|
||||
|
||||
import static com.android.launcher3.FastBitmapDrawable.newIcon;
|
||||
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.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.ResolveInfo;
|
||||
import android.os.Bundle;
|
||||
import android.text.TextUtils;
|
||||
import android.util.AttributeSet;
|
||||
|
@ -27,38 +33,41 @@ import android.widget.TextView;
|
|||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.android.launcher3.FastBitmapDrawable;
|
||||
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.model.data.PackageItemInfo;
|
||||
import com.android.systemui.plugins.shared.SearchTarget;
|
||||
import com.android.systemui.plugins.shared.SearchTargetEvent;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* A row of tappable TextViews with a breadcrumb for settings search.
|
||||
* A row of clickable TextViews with a breadcrumb for settings search.
|
||||
*/
|
||||
public class SearchSettingsRowView extends LinearLayout implements
|
||||
View.OnClickListener, AllAppsSearchBarController.SearchTargetHandler {
|
||||
|
||||
public static final String TARGET_TYPE_SETTINGS_ROW = "settings_row";
|
||||
|
||||
|
||||
private View mIconView;
|
||||
private TextView mTitleView;
|
||||
private TextView mDescriptionView;
|
||||
private TextView mBreadcrumbsView;
|
||||
private Intent mIntent;
|
||||
private SearchTarget mSearchTarget;
|
||||
|
||||
|
||||
public SearchSettingsRowView(@NonNull Context context) {
|
||||
super(context);
|
||||
this(context, null, 0);
|
||||
}
|
||||
|
||||
public SearchSettingsRowView(@NonNull Context context,
|
||||
@Nullable AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
this(context, attrs, 0);
|
||||
}
|
||||
|
||||
public SearchSettingsRowView(@NonNull Context context, @Nullable AttributeSet attrs,
|
||||
|
@ -69,10 +78,11 @@ public class SearchSettingsRowView extends LinearLayout implements
|
|||
@Override
|
||||
protected void onFinishInflate() {
|
||||
super.onFinishInflate();
|
||||
mIconView = findViewById(R.id.icon);
|
||||
mTitleView = findViewById(R.id.title);
|
||||
mDescriptionView = findViewById(R.id.description);
|
||||
mBreadcrumbsView = findViewById(R.id.breadcrumbs);
|
||||
setOnClickListener(this);
|
||||
applySettingsIcon(Launcher.getLauncher(getContext()), mIconView);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -81,6 +91,7 @@ public class SearchSettingsRowView extends LinearLayout implements
|
|||
Bundle bundle = searchTarget.getExtras();
|
||||
mIntent = bundle.getParcelable("intent");
|
||||
showIfAvailable(mTitleView, bundle.getString("title"));
|
||||
mIconView.setContentDescription(bundle.getString("title"));
|
||||
ArrayList<String> breadcrumbs = bundle.getStringArrayList("breadcrumbs");
|
||||
//TODO: implement RTL friendly breadcrumbs view
|
||||
showIfAvailable(mBreadcrumbsView, breadcrumbs != null
|
||||
|
@ -113,4 +124,30 @@ public class SearchSettingsRowView extends LinearLayout implements
|
|||
SearchEventTracker.INSTANCE.get(getContext()).notifySearchTargetEvent(
|
||||
new SearchTargetEvent.Builder(mSearchTarget, eventType).build());
|
||||
}
|
||||
|
||||
/**
|
||||
* Requests settings app icon from {@link com.android.launcher3.icons.IconCache} and applies
|
||||
* to to view
|
||||
*/
|
||||
public static void applySettingsIcon(Launcher launcher, View view) {
|
||||
LauncherAppState appState = LauncherAppState.getInstance(launcher);
|
||||
MODEL_EXECUTOR.post(() -> {
|
||||
PackageItemInfo packageItemInfo = new PackageItemInfo(getSettingsPackageName(launcher));
|
||||
appState.getIconCache().getTitleAndIconForApp(packageItemInfo, false);
|
||||
MAIN_EXECUTOR.post(() -> {
|
||||
FastBitmapDrawable iconDrawable = newIcon(appState.getContext(), packageItemInfo);
|
||||
view.setBackground(iconDrawable);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
private static String getSettingsPackageName(Launcher launcher) {
|
||||
Intent intent = new Intent(android.provider.Settings.ACTION_SETTINGS);
|
||||
List<ResolveInfo> resolveInfos = launcher.getPackageManager().queryIntentActivities(intent,
|
||||
PackageManager.MATCH_DEFAULT_ONLY);
|
||||
if (resolveInfos.size() == 0) {
|
||||
return "";
|
||||
}
|
||||
return resolveInfos.get(0).activityInfo.packageName;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue