Merge "Initial changes to support predicted apps." into ub-launcher3-burnaby
This commit is contained in:
@@ -21,8 +21,8 @@
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="left|center_vertical"
|
||||
android:paddingTop="8dp"
|
||||
android:paddingBottom="8dp"
|
||||
android:paddingTop="@dimen/apps_icon_top_bottom_padding"
|
||||
android:paddingBottom="@dimen/apps_icon_top_bottom_padding"
|
||||
android:focusable="true"
|
||||
android:background="@drawable/focusable_view_bg"
|
||||
launcher:deferShadowGeneration="true" />
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
<?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.
|
||||
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.BubbleTextView
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:launcher="http://schemas.android.com/apk/res-auto"
|
||||
style="@style/WorkspaceIcon.AppsCustomize"
|
||||
android:id="@+id/application_icon"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:focusable="true"
|
||||
android:background="@drawable/focusable_view_bg"
|
||||
launcher:iconPaddingOverride="24dp"
|
||||
launcher:textSizeOverride="16dp"
|
||||
launcher:layoutHorizontal="true"
|
||||
launcher:deferShadowGeneration="true" />
|
||||
@@ -25,7 +25,7 @@
|
||||
<FrameLayout
|
||||
android:id="@+id/header"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="52dp"
|
||||
android:layout_height="@dimen/apps_search_bar_height"
|
||||
android:orientation="horizontal"
|
||||
android:background="@drawable/apps_search_bg">
|
||||
<LinearLayout
|
||||
@@ -39,6 +39,7 @@
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="start|center_vertical"
|
||||
android:layout_marginStart="4dp"
|
||||
android:paddingTop="12dp"
|
||||
android:paddingBottom="12dp"
|
||||
android:contentDescription="@string/all_apps_button_label"
|
||||
@@ -67,6 +68,7 @@
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="end|center_vertical"
|
||||
android:layout_marginEnd="6dp"
|
||||
android:paddingTop="12dp"
|
||||
android:paddingBottom="12dp"
|
||||
android:contentDescription="@string/apps_view_search_bar_hint"
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
<dimen name="apps_grid_view_start_margin">64dp</dimen>
|
||||
<dimen name="apps_view_section_text_size">26sp</dimen>
|
||||
<dimen name="apps_view_row_height">76dp</dimen>
|
||||
<dimen name="apps_icon_top_bottom_padding">12dp</dimen>
|
||||
|
||||
<!-- AppsCustomize -->
|
||||
<dimen name="widget_preview_label_margin_top">8dp</dimen>
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
|
||||
<resources>
|
||||
<dimen name="app_icon_size">72dp</dimen>
|
||||
<dimen name="apps_search_bar_height">56dp</dimen>
|
||||
<dimen name="apps_icon_top_bottom_padding">16dp</dimen>
|
||||
|
||||
<!-- QSB -->
|
||||
<dimen name="toolbar_button_vertical_padding">8dip</dimen>
|
||||
|
||||
@@ -59,6 +59,8 @@
|
||||
<dimen name="apps_view_fast_scroll_scrubber_touch_inset">-16dp</dimen>
|
||||
<dimen name="apps_view_fast_scroll_popup_size">64dp</dimen>
|
||||
<dimen name="apps_view_fast_scroll_text_size">40dp</dimen>
|
||||
<dimen name="apps_search_bar_height">52dp</dimen>
|
||||
<dimen name="apps_icon_top_bottom_padding">8dp</dimen>
|
||||
|
||||
<!-- Note: This needs to match the fixed insets for the search box. -->
|
||||
<dimen name="container_fixed_bounds_inset">8dp</dimen>
|
||||
|
||||
@@ -130,17 +130,21 @@ public class AlphabeticalAppsList {
|
||||
public AppInfo appInfo = null;
|
||||
// The index of this app not including sections
|
||||
public int appIndex = -1;
|
||||
// Whether or not this is a predicted app
|
||||
public boolean isPredictedApp;
|
||||
|
||||
public static AdapterItem asSectionBreak(int pos, SectionInfo section) {
|
||||
AdapterItem item = new AdapterItem();
|
||||
item.position = pos;
|
||||
item.isSectionHeader = true;
|
||||
item.sectionInfo = section;
|
||||
section.sectionBreakItem = item;
|
||||
return item;
|
||||
}
|
||||
|
||||
public static AdapterItem asApp(int pos, SectionInfo section, String sectionName,
|
||||
int sectionAppIndex, AppInfo appInfo, int appIndex) {
|
||||
int sectionAppIndex, AppInfo appInfo, int appIndex,
|
||||
boolean isPredictedApp) {
|
||||
AdapterItem item = new AdapterItem();
|
||||
item.position = pos;
|
||||
item.isSectionHeader = false;
|
||||
@@ -149,6 +153,7 @@ public class AlphabeticalAppsList {
|
||||
item.sectionAppIndex = sectionAppIndex;
|
||||
item.appInfo = appInfo;
|
||||
item.appIndex = appIndex;
|
||||
item.isPredictedApp = isPredictedApp;
|
||||
return item;
|
||||
}
|
||||
}
|
||||
@@ -168,6 +173,7 @@ public class AlphabeticalAppsList {
|
||||
private List<AdapterItem> mSectionedFilteredApps = new ArrayList<>();
|
||||
private List<SectionInfo> mSections = new ArrayList<>();
|
||||
private List<FastScrollSectionInfo> mFastScrollerSections = new ArrayList<>();
|
||||
private List<ComponentName> mPredictedApps = new ArrayList<>();
|
||||
private RecyclerView.Adapter mAdapter;
|
||||
private Filter mFilter;
|
||||
private AlphabeticIndexCompat mIndexer;
|
||||
@@ -251,6 +257,17 @@ public class AlphabeticalAppsList {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the current set of predicted apps. Since this can be called before we get the full set
|
||||
* of applications, we should merge the results only in onAppsUpdated() which is idempotent.
|
||||
*/
|
||||
public void setPredictedApps(List<ComponentName> apps) {
|
||||
mPredictedApps.clear();
|
||||
mPredictedApps.addAll(apps);
|
||||
onAppsUpdated();
|
||||
mAdapter.notifyDataSetChanged();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the current set of apps.
|
||||
*/
|
||||
@@ -336,7 +353,7 @@ public class AlphabeticalAppsList {
|
||||
// Sort the list of apps
|
||||
Collections.sort(mApps, mAppNameComparator.getComparator());
|
||||
|
||||
// Recreate the filtered and sectioned apps (for convenience for the grid layout)
|
||||
// Prepare to update the list of sections, filtered apps, etc.
|
||||
mFilteredApps.clear();
|
||||
mSections.clear();
|
||||
mSectionedFilteredApps.clear();
|
||||
@@ -346,36 +363,62 @@ public class AlphabeticalAppsList {
|
||||
FastScrollSectionInfo lastFastScrollerSectionInfo = null;
|
||||
int position = 0;
|
||||
int appIndex = 0;
|
||||
int numApps = mApps.size();
|
||||
for (AppInfo info : mApps) {
|
||||
String sectionName = mIndexer.computeSectionName(info.title);
|
||||
List<AppInfo> allApps = new ArrayList<>();
|
||||
|
||||
// Add the predicted apps to the combined list
|
||||
int numPredictedApps = 0;
|
||||
if (mPredictedApps != null && !mPredictedApps.isEmpty() && !hasFilter()) {
|
||||
for (ComponentName cn : mPredictedApps) {
|
||||
for (AppInfo info : mApps) {
|
||||
if (cn.equals(info.componentName)) {
|
||||
allApps.add(info);
|
||||
numPredictedApps++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Stop at the number of predicted apps
|
||||
if (numPredictedApps == mNumAppsPerRow) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add all the other apps to the combined list
|
||||
allApps.addAll(mApps);
|
||||
|
||||
// Recreate the filtered and sectioned apps (for convenience for the grid layout) from the
|
||||
// combined list
|
||||
int numApps = allApps.size();
|
||||
for (int i = 0; i < numApps; i++) {
|
||||
boolean isPredictedApp = i < numPredictedApps;
|
||||
AppInfo info = allApps.get(i);
|
||||
String sectionName = isPredictedApp ? "" : mIndexer.computeSectionName(info.title);
|
||||
|
||||
// Check if we want to retain this app
|
||||
if (mFilter != null && !mFilter.retainApp(info, sectionName)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Create a new section if necessary
|
||||
if (lastSectionInfo == null || !sectionName.equals(lastSectionName)) {
|
||||
// Create a new section if the section names do not match
|
||||
if (lastSectionInfo == null ||
|
||||
(!isPredictedApp && !sectionName.equals(lastSectionName))) {
|
||||
lastSectionName = sectionName;
|
||||
lastSectionInfo = new SectionInfo();
|
||||
mSections.add(lastSectionInfo);
|
||||
lastFastScrollerSectionInfo = new FastScrollSectionInfo(sectionName,
|
||||
(float) appIndex / numApps);
|
||||
mSections.add(lastSectionInfo);
|
||||
mFastScrollerSections.add(lastFastScrollerSectionInfo);
|
||||
|
||||
// Create a new section item, this item is used to break the flow of items in the
|
||||
// list
|
||||
AdapterItem sectionItem = AdapterItem.asSectionBreak(position++, lastSectionInfo);
|
||||
// Create a new section item to break the flow of items in the list
|
||||
if (!AppsContainerView.GRID_HIDE_SECTION_HEADERS && !hasFilter()) {
|
||||
lastSectionInfo.sectionBreakItem = sectionItem;
|
||||
AdapterItem sectionItem = AdapterItem.asSectionBreak(position++, lastSectionInfo);
|
||||
mSectionedFilteredApps.add(sectionItem);
|
||||
}
|
||||
}
|
||||
|
||||
// Create an app item
|
||||
AdapterItem appItem = AdapterItem.asApp(position++, lastSectionInfo, sectionName,
|
||||
lastSectionInfo.numApps++, info, appIndex++);
|
||||
lastSectionInfo.numApps++, info, appIndex++, isPredictedApp);
|
||||
if (lastSectionInfo.firstAppItem == null) {
|
||||
lastSectionInfo.firstAppItem = appItem;
|
||||
lastFastScrollerSectionInfo.appItem = appItem;
|
||||
@@ -384,8 +427,8 @@ public class AlphabeticalAppsList {
|
||||
mFilteredApps.add(info);
|
||||
}
|
||||
|
||||
// Go through each section and try and merge some of the sections
|
||||
if (AppsContainerView.GRID_MERGE_SECTIONS && !hasFilter()) {
|
||||
// Go through each section and try and merge some of the sections
|
||||
int minNumAppsPerRow = (int) Math.ceil(mNumAppsPerRow / 2f);
|
||||
int sectionAppCount = 0;
|
||||
for (int i = 0; i < mSections.size(); i++) {
|
||||
|
||||
@@ -229,7 +229,7 @@ public class AppsContainerRecyclerView extends BaseContainerRecyclerView {
|
||||
* Draws the fast scroller popup.
|
||||
*/
|
||||
private void drawFastScrollerPopup(Canvas canvas) {
|
||||
if (mFastScrollAlpha > 0f) {
|
||||
if (mFastScrollAlpha > 0f && !mFastScrollSectionName.isEmpty()) {
|
||||
int x;
|
||||
int y;
|
||||
boolean isRtl = (getResources().getConfiguration().getLayoutDirection() ==
|
||||
@@ -381,16 +381,16 @@ public class AppsContainerRecyclerView extends BaseContainerRecyclerView {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the row index for a given position in the list.
|
||||
* Returns the row index for a app index in the list.
|
||||
*/
|
||||
private int findRowForAppIndex(int position) {
|
||||
private int findRowForAppIndex(int index) {
|
||||
List<AlphabeticalAppsList.SectionInfo> sections = mApps.getSections();
|
||||
int appIndex = 0;
|
||||
int rowCount = 0;
|
||||
for (AlphabeticalAppsList.SectionInfo info : sections) {
|
||||
int numRowsInSection = (int) Math.ceil((float) info.numApps / mNumAppsPerRow);
|
||||
if (appIndex + info.numApps > position) {
|
||||
return rowCount + ((position - appIndex) / mNumAppsPerRow);
|
||||
if (appIndex + info.numApps > index) {
|
||||
return rowCount + ((index - appIndex) / mNumAppsPerRow);
|
||||
}
|
||||
appIndex += info.numApps;
|
||||
rowCount += numRowsInSection;
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
package com.android.launcher3;
|
||||
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Point;
|
||||
@@ -110,6 +111,13 @@ public class AppsContainerView extends BaseContainerView implements DragSource,
|
||||
mApps.setAdapter(mAdapter);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the current set of predicted apps.
|
||||
*/
|
||||
public void setPredictedApps(List<ComponentName> apps) {
|
||||
mApps.setPredictedApps(apps);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the current set of apps.
|
||||
*/
|
||||
|
||||
@@ -35,13 +35,11 @@ class AppsGridAdapter extends RecyclerView.Adapter<AppsGridAdapter.ViewHolder> {
|
||||
*/
|
||||
public static class ViewHolder extends RecyclerView.ViewHolder {
|
||||
public View mContent;
|
||||
public boolean mIsSectionHeader;
|
||||
public boolean mIsEmptyRow;
|
||||
|
||||
public ViewHolder(View v, boolean isSectionHeader, boolean isEmptyRow) {
|
||||
public ViewHolder(View v, boolean isEmptyRow) {
|
||||
super(v);
|
||||
mContent = v;
|
||||
mIsSectionHeader = isSectionHeader;
|
||||
mIsEmptyRow = isEmptyRow;
|
||||
}
|
||||
}
|
||||
@@ -93,13 +91,29 @@ class AppsGridAdapter extends RecyclerView.Adapter<AppsGridAdapter.ViewHolder> {
|
||||
}
|
||||
|
||||
List<AlphabeticalAppsList.AdapterItem> items = mApps.getAdapterItems();
|
||||
boolean hasDrawnPredictedAppDivider = false;
|
||||
int childCount = parent.getChildCount();
|
||||
int lastSectionTop = 0;
|
||||
int lastSectionHeight = 0;
|
||||
for (int i = 0; i < childCount; i++) {
|
||||
View child = parent.getChildAt(i);
|
||||
ViewHolder holder = (ViewHolder) parent.getChildViewHolder(child);
|
||||
if (shouldDrawItemSection(holder, child, i, items)) {
|
||||
if (!isValidHolderAndChild(holder, child, items)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (shouldDrawItemDivider(holder, items) && !hasDrawnPredictedAppDivider) {
|
||||
// Draw the divider under the predicted app
|
||||
DeviceProfile grid = LauncherAppState.getInstance().getDynamicGrid().
|
||||
getDeviceProfile();
|
||||
int top = child.getTop() + child.getHeight();
|
||||
int left = parent.getPaddingLeft();
|
||||
int right = parent.getWidth() - parent.getPaddingRight();
|
||||
int iconInset = (((right - left) / mAppsPerRow) - grid.allAppsIconSizePx) / 2;
|
||||
c.drawLine(left + iconInset, top, right - iconInset, top, mPredictedAppsDividerPaint);
|
||||
hasDrawnPredictedAppDivider = true;
|
||||
|
||||
} else if (shouldDrawItemSection(holder, i, items)) {
|
||||
// At this point, we only draw sections for each section break;
|
||||
int viewTopOffset = (2 * child.getPaddingTop());
|
||||
int pos = holder.getPosition();
|
||||
@@ -186,9 +200,9 @@ class AppsGridAdapter extends RecyclerView.Adapter<AppsGridAdapter.ViewHolder> {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether to draw the section for the given child.
|
||||
* Returns whether we consider this a valid view holder for us to draw a divider or section for.
|
||||
*/
|
||||
private boolean shouldDrawItemSection(ViewHolder holder, View child, int childIndex,
|
||||
private boolean isValidHolderAndChild(ViewHolder holder, View child,
|
||||
List<AlphabeticalAppsList.AdapterItem> items) {
|
||||
// Ensure item is not already removed
|
||||
GridLayoutManager.LayoutParams lp = (GridLayoutManager.LayoutParams)
|
||||
@@ -200,18 +214,44 @@ class AppsGridAdapter extends RecyclerView.Adapter<AppsGridAdapter.ViewHolder> {
|
||||
if (holder == null) {
|
||||
return false;
|
||||
}
|
||||
// Ensure we have a holder position
|
||||
int pos = holder.getPosition();
|
||||
if (pos < 0 || pos >= items.size()) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether to draw the divider for a given child.
|
||||
*/
|
||||
private boolean shouldDrawItemDivider(ViewHolder holder, List<AlphabeticalAppsList.AdapterItem> items) {
|
||||
int pos = holder.getPosition();
|
||||
return items.get(pos).isPredictedApp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether to draw the section for the given child.
|
||||
*/
|
||||
private boolean shouldDrawItemSection(ViewHolder holder, int childIndex,
|
||||
List<AlphabeticalAppsList.AdapterItem> items) {
|
||||
int pos = holder.getPosition();
|
||||
AlphabeticalAppsList.AdapterItem item = items.get(pos);
|
||||
|
||||
// Ensure it's not an empty row
|
||||
if (holder.mIsEmptyRow) {
|
||||
return false;
|
||||
}
|
||||
// Ensure we have a holder position
|
||||
int pos = holder.getPosition();
|
||||
if (pos <= 0 || pos >= items.size()) {
|
||||
// Ensure this is not a section break
|
||||
if (item.isSectionHeader) {
|
||||
return false;
|
||||
}
|
||||
// Ensure this is not a predicted app
|
||||
if (item.isPredictedApp) {
|
||||
return false;
|
||||
}
|
||||
// Draw the section header for the first item in each section
|
||||
return (childIndex == 0) ||
|
||||
(items.get(pos - 1).isSectionHeader && !items.get(pos).isSectionHeader);
|
||||
return (childIndex == 0) || (items.get(pos - 1).isSectionHeader && !item.isSectionHeader);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -232,6 +272,7 @@ class AppsGridAdapter extends RecyclerView.Adapter<AppsGridAdapter.ViewHolder> {
|
||||
@Thunk int mStartMargin;
|
||||
@Thunk int mSectionHeaderOffset;
|
||||
@Thunk Paint mSectionTextPaint;
|
||||
@Thunk Paint mPredictedAppsDividerPaint;
|
||||
|
||||
|
||||
public AppsGridAdapter(Context context, AlphabeticalAppsList apps, int appsPerRow,
|
||||
@@ -254,11 +295,17 @@ class AppsGridAdapter extends RecyclerView.Adapter<AppsGridAdapter.ViewHolder> {
|
||||
mSectionHeaderOffset = res.getDimensionPixelSize(R.dimen.apps_grid_section_y_offset);
|
||||
}
|
||||
mPaddingStart = res.getDimensionPixelSize(R.dimen.apps_container_inset);
|
||||
|
||||
mSectionTextPaint = new Paint();
|
||||
mSectionTextPaint.setTextSize(res.getDimensionPixelSize(
|
||||
R.dimen.apps_view_section_text_size));
|
||||
mSectionTextPaint.setColor(res.getColor(R.color.apps_view_section_text_color));
|
||||
mSectionTextPaint.setAntiAlias(true);
|
||||
|
||||
mPredictedAppsDividerPaint = new Paint();
|
||||
mPredictedAppsDividerPaint.setStrokeWidth(DynamicGrid.pxFromDp(1.5f, res.getDisplayMetrics()));
|
||||
mPredictedAppsDividerPaint.setColor(0x10000000);
|
||||
mPredictedAppsDividerPaint.setAntiAlias(true);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -313,10 +360,9 @@ class AppsGridAdapter extends RecyclerView.Adapter<AppsGridAdapter.ViewHolder> {
|
||||
switch (viewType) {
|
||||
case EMPTY_VIEW_TYPE:
|
||||
return new ViewHolder(mLayoutInflater.inflate(R.layout.apps_empty_view, parent,
|
||||
false), false /* isSectionRow */, true /* isEmptyRow */);
|
||||
false), true /* isEmptyRow */);
|
||||
case SECTION_BREAK_VIEW_TYPE:
|
||||
return new ViewHolder(new View(parent.getContext()), true /* isSectionRow */,
|
||||
false /* isEmptyRow */);
|
||||
return new ViewHolder(new View(parent.getContext()), false /* isEmptyRow */);
|
||||
case ICON_VIEW_TYPE:
|
||||
BubbleTextView icon = (BubbleTextView) mLayoutInflater.inflate(
|
||||
R.layout.apps_grid_row_icon_view, parent, false);
|
||||
@@ -324,7 +370,7 @@ class AppsGridAdapter extends RecyclerView.Adapter<AppsGridAdapter.ViewHolder> {
|
||||
icon.setOnClickListener(mIconClickListener);
|
||||
icon.setOnLongClickListener(mIconLongClickListener);
|
||||
icon.setFocusable(true);
|
||||
return new ViewHolder(icon, false /* isSectionRow */, false /* isEmptyRow */);
|
||||
return new ViewHolder(icon, false /* isEmptyRow */);
|
||||
default:
|
||||
throw new RuntimeException("Unexpected view type");
|
||||
}
|
||||
|
||||
@@ -64,6 +64,7 @@ import android.os.Handler;
|
||||
import android.os.Message;
|
||||
import android.os.StrictMode;
|
||||
import android.os.SystemClock;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.text.Selection;
|
||||
import android.text.SpannableStringBuilder;
|
||||
import android.text.TextUtils;
|
||||
@@ -1018,16 +1019,22 @@ public class Launcher extends Activity
|
||||
if (mOnResumeState == State.WORKSPACE) {
|
||||
showWorkspace(false);
|
||||
} else if (mOnResumeState == State.APPS) {
|
||||
showAppsView(false /* animated */, false /* resetListToTop */);
|
||||
// Don't update the predicted apps if the user is returning to launcher in the apps
|
||||
// view as they may be depending on the UI to be static to switch to another app
|
||||
showAppsView(false /* animated */, false /* resetListToTop */,
|
||||
false /* updatePredictedApps */);
|
||||
} else if (mOnResumeState == State.WIDGETS) {
|
||||
showWidgetsView(false, false);
|
||||
}
|
||||
mOnResumeState = State.NONE;
|
||||
|
||||
// Restore the apps state if we are in all apps
|
||||
if (!Launcher.DISABLE_ALL_APPS_SEARCH_INTEGRATION && mState == State.APPS) {
|
||||
if (mLauncherCallbacks != null) {
|
||||
mLauncherCallbacks.onAllAppsShown();
|
||||
if (!Launcher.DISABLE_ALL_APPS_SEARCH_INTEGRATION) {
|
||||
// Otherwise, notify the callbacks if we are in all apps mode
|
||||
if (mState == State.APPS) {
|
||||
if (mLauncherCallbacks != null) {
|
||||
mLauncherCallbacks.onAllAppsShown();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2619,7 +2626,9 @@ public class Launcher extends Activity
|
||||
if (isAppsViewVisible()) {
|
||||
showWorkspace(true);
|
||||
} else {
|
||||
showAppsView(true /* animated */, false /* resetListToTop */);
|
||||
// Try and refresh the set of predicted apps before we enter launcher
|
||||
showAppsView(true /* animated */, false /* resetListToTop */,
|
||||
true /* updatePredictedApps */);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3397,10 +3406,13 @@ public class Launcher extends Activity
|
||||
/**
|
||||
* Shows the apps view.
|
||||
*/
|
||||
void showAppsView(boolean animated, boolean resetListToTop) {
|
||||
void showAppsView(boolean animated, boolean resetListToTop, boolean updatePredictedApps) {
|
||||
if (resetListToTop) {
|
||||
mAppsView.scrollToTop();
|
||||
}
|
||||
if (updatePredictedApps) {
|
||||
tryAndUpdatePredictedApps();
|
||||
}
|
||||
showAppsOrWidgets(animated, State.APPS);
|
||||
}
|
||||
|
||||
@@ -3509,12 +3521,26 @@ public class Launcher extends Activity
|
||||
|
||||
void exitSpringLoadedDragMode() {
|
||||
if (mState == State.APPS_SPRING_LOADED) {
|
||||
showAppsView(true, false);
|
||||
showAppsView(true /* animated */, false /* resetListToTop */,
|
||||
false /* updatePredictedApps */);
|
||||
} else if (mState == State.WIDGETS_SPRING_LOADED) {
|
||||
showWidgetsView(true, false);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the set of predicted apps if it hasn't been updated since the last time Launcher was
|
||||
* resumed.
|
||||
*/
|
||||
private void tryAndUpdatePredictedApps() {
|
||||
if (mLauncherCallbacks != null) {
|
||||
List<ComponentName> apps = mLauncherCallbacks.getPredictedApps();
|
||||
if (!apps.isEmpty()) {
|
||||
mAppsView.setPredictedApps(apps);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void lockAllApps() {
|
||||
// TODO
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ import android.view.ViewGroup;
|
||||
import java.io.FileDescriptor;
|
||||
import java.io.PrintWriter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* LauncherCallbacks is an interface used to extend the Launcher activity. It includes many hooks
|
||||
@@ -90,6 +91,7 @@ public interface LauncherCallbacks {
|
||||
public boolean overrideWallpaperDimensions();
|
||||
public boolean isLauncherPreinstalled();
|
||||
public boolean overrideAllAppsSearch();
|
||||
public List<ComponentName> getPredictedApps();
|
||||
|
||||
/**
|
||||
* Returning true will immediately result in a call to {@link #setLauncherOverlayView(ViewGroup,
|
||||
|
||||
@@ -15,6 +15,7 @@ import android.view.ViewGroup;
|
||||
import java.io.FileDescriptor;
|
||||
import java.io.PrintWriter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* This class represents a very trivial LauncherExtension. It primarily serves as a simple
|
||||
@@ -258,6 +259,11 @@ public class LauncherExtension extends Launcher {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ComponentName> getPredictedApps() {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLauncherPreinstalled() {
|
||||
return false;
|
||||
|
||||
Reference in New Issue
Block a user