Merge "Widget cell improvement" into ub-launcher3-burnaby
diff --git a/WallpaperPicker/src/com/android/launcher3/WallpaperCropActivity.java b/WallpaperPicker/src/com/android/launcher3/WallpaperCropActivity.java
index affad0f..ee0d8b0 100644
--- a/WallpaperPicker/src/com/android/launcher3/WallpaperCropActivity.java
+++ b/WallpaperPicker/src/com/android/launcher3/WallpaperCropActivity.java
@@ -131,7 +131,7 @@
// Load image in background
final BitmapRegionTileSource.UriBitmapSource bitmapSource =
- new BitmapRegionTileSource.UriBitmapSource(getContext(), imageUri, 1024);
+ new BitmapRegionTileSource.UriBitmapSource(getContext(), imageUri);
mSetWallpaperButton.setEnabled(false);
Runnable onLoad = new Runnable() {
public void run() {
diff --git a/WallpaperPicker/src/com/android/launcher3/WallpaperPickerActivity.java b/WallpaperPicker/src/com/android/launcher3/WallpaperPickerActivity.java
index 1ba5b4b..72cb194 100644
--- a/WallpaperPicker/src/com/android/launcher3/WallpaperPickerActivity.java
+++ b/WallpaperPicker/src/com/android/launcher3/WallpaperPickerActivity.java
@@ -21,7 +21,6 @@
import android.app.ActionBar;
import android.app.Activity;
import android.app.WallpaperManager;
-import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
@@ -144,8 +143,7 @@
public void onClick(final WallpaperPickerActivity a) {
a.setWallpaperButtonEnabled(false);
final BitmapRegionTileSource.UriBitmapSource bitmapSource =
- new BitmapRegionTileSource.UriBitmapSource(
- a.getContext(), mUri, BitmapRegionTileSource.MAX_PREVIEW_SIZE);
+ new BitmapRegionTileSource.UriBitmapSource(a.getContext(), mUri);
a.setCropViewTileSource(bitmapSource, true, false, null, new Runnable() {
@Override
@@ -199,8 +197,7 @@
public void onClick(final WallpaperPickerActivity a) {
a.setWallpaperButtonEnabled(false);
BitmapRegionTileSource.UriBitmapSource bitmapSource =
- new BitmapRegionTileSource.UriBitmapSource(a.getContext(),
- Uri.fromFile(mFile), 1024);
+ new BitmapRegionTileSource.UriBitmapSource(a.getContext(), Uri.fromFile(mFile));
a.setCropViewTileSource(bitmapSource, false, true, null, new Runnable() {
@Override
@@ -236,8 +233,7 @@
public void onClick(final WallpaperPickerActivity a) {
a.setWallpaperButtonEnabled(false);
BitmapRegionTileSource.ResourceBitmapSource bitmapSource =
- new BitmapRegionTileSource.ResourceBitmapSource(
- mResources, mResId, BitmapRegionTileSource.MAX_PREVIEW_SIZE);
+ new BitmapRegionTileSource.ResourceBitmapSource(mResources, mResId);
a.setCropViewTileSource(bitmapSource, false, false, new CropViewScaleProvider() {
@Override
diff --git a/WallpaperPicker/src/com/android/photos/BitmapRegionTileSource.java b/WallpaperPicker/src/com/android/photos/BitmapRegionTileSource.java
index 15f97e5..2d496a5 100644
--- a/WallpaperPicker/src/com/android/photos/BitmapRegionTileSource.java
+++ b/WallpaperPicker/src/com/android/photos/BitmapRegionTileSource.java
@@ -26,6 +26,7 @@
import android.graphics.Paint;
import android.graphics.Rect;
import android.net.Uri;
+import android.opengl.GLUtils;
import android.os.Build;
import android.util.Log;
@@ -149,18 +150,15 @@
private static final int GL_SIZE_LIMIT = 2048;
// This must be no larger than half the size of the GL_SIZE_LIMIT
// due to decodePreview being allowed to be up to 2x the size of the target
- public static final int MAX_PREVIEW_SIZE = GL_SIZE_LIMIT / 2;
+ private static final int MAX_PREVIEW_SIZE = GL_SIZE_LIMIT / 2;
public static abstract class BitmapSource {
private SimpleBitmapRegionDecoder mDecoder;
private Bitmap mPreview;
- private final int mPreviewSize;
private int mRotation;
public enum State { NOT_LOADED, LOADED, ERROR_LOADING };
private State mState = State.NOT_LOADED;
- public BitmapSource(int previewSize) {
- mPreviewSize = Math.min(previewSize, MAX_PREVIEW_SIZE);
- }
+
public boolean loadInBackground(InBitmapProvider bitmapProvider) {
ExifInterface ei = new ExifInterface();
if (readExif(ei)) {
@@ -176,36 +174,44 @@
} else {
int width = mDecoder.getWidth();
int height = mDecoder.getHeight();
- if (mPreviewSize != 0) {
- BitmapFactory.Options opts = new BitmapFactory.Options();
- opts.inPreferredConfig = Bitmap.Config.ARGB_8888;
- opts.inPreferQualityOverSpeed = true;
- float scale = (float) mPreviewSize / Math.max(width, height);
- opts.inSampleSize = BitmapUtils.computeSampleSizeLarger(scale);
- opts.inJustDecodeBounds = false;
- opts.inMutable = true;
+ BitmapFactory.Options opts = new BitmapFactory.Options();
+ opts.inPreferredConfig = Bitmap.Config.ARGB_8888;
+ opts.inPreferQualityOverSpeed = true;
- if (bitmapProvider != null) {
- int expectedPixles = (width / opts.inSampleSize) * (height / opts.inSampleSize);
- Bitmap reusableBitmap = bitmapProvider.forPixelCount(expectedPixles);
- if (reusableBitmap != null) {
- // Try loading with reusable bitmap
- opts.inBitmap = reusableBitmap;
- try {
- mPreview = loadPreviewBitmap(opts);
- } catch (IllegalArgumentException e) {
- Log.d(TAG, "Unable to reusage bitmap", e);
- opts.inBitmap = null;
- mPreview = null;
- }
+ float scale = (float) MAX_PREVIEW_SIZE / Math.max(width, height);
+ opts.inSampleSize = BitmapUtils.computeSampleSizeLarger(scale);
+ opts.inJustDecodeBounds = false;
+ opts.inMutable = true;
+
+ if (bitmapProvider != null) {
+ int expectedPixles = (width / opts.inSampleSize) * (height / opts.inSampleSize);
+ Bitmap reusableBitmap = bitmapProvider.forPixelCount(expectedPixles);
+ if (reusableBitmap != null) {
+ // Try loading with reusable bitmap
+ opts.inBitmap = reusableBitmap;
+ try {
+ mPreview = loadPreviewBitmap(opts);
+ } catch (IllegalArgumentException e) {
+ Log.d(TAG, "Unable to reusage bitmap", e);
+ opts.inBitmap = null;
+ mPreview = null;
}
}
- if (mPreview == null) {
- mPreview = loadPreviewBitmap(opts);
- }
}
- mState = State.LOADED;
+ if (mPreview == null) {
+ mPreview = loadPreviewBitmap(opts);
+ }
+
+ // Verify that the bitmap can be used on GL surface
+ try {
+ GLUtils.getInternalFormat(mPreview);
+ GLUtils.getType(mPreview);
+ mState = State.LOADED;
+ } catch (IllegalArgumentException e) {
+ Log.d(TAG, "Image cannot be rendered on a GL surface", e);
+ mState = State.ERROR_LOADING;
+ }
return true;
}
}
@@ -237,8 +243,7 @@
public static class FilePathBitmapSource extends BitmapSource {
private String mPath;
- public FilePathBitmapSource(String path, int previewSize) {
- super(previewSize);
+ public FilePathBitmapSource(String path) {
mPath = path;
}
@Override
@@ -272,8 +277,7 @@
public static class UriBitmapSource extends BitmapSource {
private Context mContext;
private Uri mUri;
- public UriBitmapSource(Context context, Uri uri, int previewSize) {
- super(previewSize);
+ public UriBitmapSource(Context context, Uri uri) {
mContext = context;
mUri = uri;
}
@@ -337,8 +341,7 @@
public static class ResourceBitmapSource extends BitmapSource {
private Resources mRes;
private int mResId;
- public ResourceBitmapSource(Resources res, int resId, int previewSize) {
- super(previewSize);
+ public ResourceBitmapSource(Resources res, int resId) {
mRes = res;
mResId = resId;
}
diff --git a/res/drawable-hdpi/bg_appwidget_error.9.png b/res/drawable-hdpi/bg_appwidget_error.9.png
deleted file mode 100644
index 4da3195..0000000
--- a/res/drawable-hdpi/bg_appwidget_error.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-mdpi/bg_appwidget_error.9.png b/res/drawable-mdpi/bg_appwidget_error.9.png
deleted file mode 100644
index 493c0d4..0000000
--- a/res/drawable-mdpi/bg_appwidget_error.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xhdpi/bg_appwidget_error.9.png b/res/drawable-xhdpi/bg_appwidget_error.9.png
deleted file mode 100644
index b792cc8..0000000
--- a/res/drawable-xhdpi/bg_appwidget_error.9.png
+++ /dev/null
Binary files differ
diff --git a/res/layout/appwidget_error.xml b/res/layout/appwidget_error.xml
index 03d4ae4..708ece4 100644
--- a/res/layout/appwidget_error.xml
+++ b/res/layout/appwidget_error.xml
@@ -15,15 +15,12 @@
-->
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:paddingTop="10dip"
- android:paddingBottom="10dip"
- android:paddingLeft="20dip"
- android:paddingRight="20dip"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
android:gravity="center"
- android:background="@drawable/bg_appwidget_error"
+ android:elevation="2dp"
+ android:background="@drawable/quantum_panel_dark"
android:textAppearance="?android:attr/textAppearanceMediumInverse"
- android:textColor="@color/appwidget_error_color"
+ android:textColor="@color/widgets_view_item_text_color"
android:text="@string/gadget_error_text"
/>
diff --git a/res/values/colors.xml b/res/values/colors.xml
index 0ba55f3..1e89615 100644
--- a/res/values/colors.xml
+++ b/res/values/colors.xml
@@ -27,8 +27,6 @@
<color name="focused_background">#80c6c5c5</color>
- <color name="appwidget_error_color">#FCCC</color>
-
<color name="workspace_icon_text_color">#FFF</color>
<color name="quantum_panel_text_color">#FF666666</color>
diff --git a/src/com/android/launcher3/AppsContainerRecyclerView.java b/src/com/android/launcher3/AppsContainerRecyclerView.java
index 5b1da4b..31942b3 100644
--- a/src/com/android/launcher3/AppsContainerRecyclerView.java
+++ b/src/com/android/launcher3/AppsContainerRecyclerView.java
@@ -122,30 +122,20 @@
mApps = apps;
}
- @Override
- public void setAdapter(Adapter adapter) {
- // Register a change listener to update the scroll position state whenever the data set
- // changes.
- adapter.registerAdapterDataObserver(new AdapterDataObserver() {
- @Override
- public void onChanged() {
- post(new Runnable() {
- @Override
- public void run() {
- refreshCurScrollPosition();
- }
- });
- }
- });
- super.setAdapter(adapter);
- }
-
/**
* Sets the number of apps per row in this recycler view.
*/
public void setNumAppsPerRow(int numAppsPerRow, int numPredictedAppsPerRow) {
mNumAppsPerRow = numAppsPerRow;
mNumPredictedAppsPerRow = numPredictedAppsPerRow;
+
+ DeviceProfile grid = LauncherAppState.getInstance().getDynamicGrid().getDeviceProfile();
+ RecyclerView.RecycledViewPool pool = getRecycledViewPool();
+ int approxRows = (int) Math.ceil(grid.availableHeightPx / grid.allAppsIconSizePx);
+ pool.setMaxRecycledViews(AppsGridAdapter.PREDICTION_BAR_SPACER_TYPE, 1);
+ pool.setMaxRecycledViews(AppsGridAdapter.EMPTY_VIEW_TYPE, 1);
+ pool.setMaxRecycledViews(AppsGridAdapter.ICON_VIEW_TYPE, approxRows * mNumAppsPerRow);
+ pool.setMaxRecycledViews(AppsGridAdapter.SECTION_BREAK_VIEW_TYPE, approxRows);
}
public void updateBackgroundPadding(Drawable background) {
@@ -186,7 +176,20 @@
*/
public void scrollToTop() {
scrollToPosition(0);
- updateScrollY(0);
+ }
+
+ /**
+ * Returns the current scroll position.
+ */
+ public int getScrollPosition() {
+ List<AlphabeticalAppsList.AdapterItem> items = mApps.getAdapterItems();
+ getCurScrollState(mScrollPosState, items);
+ if (mScrollPosState.rowIndex != -1) {
+ int predictionBarHeight = mApps.getPredictedApps().isEmpty() ? 0 : mPredictionBarHeight;
+ return getPaddingTop() + (mScrollPosState.rowIndex * mScrollPosState.rowHeight) +
+ predictionBarHeight - mScrollPosState.rowTopOffset;
+ }
+ return 0;
}
@Override
@@ -357,7 +360,6 @@
if (touchFraction <= predictionBarFraction) {
// Scroll to the top of the view, where the prediction bar is
layoutManager.scrollToPositionWithOffset(0, 0);
- updateScrollY(0);
return "";
}
}
@@ -376,9 +378,6 @@
lastScrollSection = scrollSection;
}
- // We need to workaround the RecyclerView to get the right scroll position
- refreshCurScrollPosition();
-
// Scroll to the view at the position, anchored at the top of the screen. We call the scroll
// method on the LayoutManager directly since it is not exposed by RecyclerView.
layoutManager.scrollToPositionWithOffset(lastScrollSection.appItem.position, 0);
@@ -402,7 +401,6 @@
int x;
int y;
int predictionBarHeight = mApps.getPredictedApps().isEmpty() ? 0 : mPredictionBarHeight;
- boolean isRtl = Utilities.isRtl(getResources());
int rowCount = getNumRows();
getCurScrollState(mScrollPosState, items);
if (mScrollPosState.rowIndex != -1) {
@@ -413,7 +411,7 @@
(int) (height / ((float) totalScrollHeight / height)));
// Calculate the position and size of the scroll bar
- if (isRtl) {
+ if (Utilities.isRtl(getResources())) {
x = mBackgroundPadding.left;
} else {
x = getWidth() - mBackgroundPadding.right - mScrollbarWidth;
@@ -442,11 +440,10 @@
if (mFastScrollAlpha > 0f && !mFastScrollSectionName.isEmpty()) {
int x;
int y;
- boolean isRtl = Utilities.isRtl(getResources());
// Calculate the position for the fast scroller popup
Rect bgBounds = mFastScrollerBg.getBounds();
- if (isRtl) {
+ if (Utilities.isRtl(getResources())) {
x = mBackgroundPadding.left + getScrollBarSize();
} else {
x = getWidth() - getPaddingRight() - getScrollBarSize() - bgBounds.width();
@@ -492,20 +489,6 @@
}
/**
- * Forces a refresh of the scroll position to any scroll listener.
- */
- private void refreshCurScrollPosition() {
- List<AlphabeticalAppsList.AdapterItem> items = mApps.getAdapterItems();
- getCurScrollState(mScrollPosState, items);
- if (mScrollPosState.rowIndex != -1) {
- int predictionBarHeight = mApps.getPredictedApps().isEmpty() ? 0 : mPredictionBarHeight;
- int scrollY = getPaddingTop() + (mScrollPosState.rowIndex * mScrollPosState.rowHeight) +
- predictionBarHeight - mScrollPosState.rowTopOffset;
- updateScrollY(scrollY);
- }
- }
-
- /**
* Returns the current scroll state.
*/
private void getCurScrollState(ScrollPositionState stateOut,
diff --git a/src/com/android/launcher3/AppsContainerView.java b/src/com/android/launcher3/AppsContainerView.java
index 8709101..5ccb6c6 100644
--- a/src/com/android/launcher3/AppsContainerView.java
+++ b/src/com/android/launcher3/AppsContainerView.java
@@ -35,6 +35,7 @@
import android.view.View;
import android.view.ViewConfiguration;
import android.view.ViewGroup;
+import android.view.ViewTreeObserver;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputMethodManager;
import android.widget.FrameLayout;
@@ -47,12 +48,97 @@
/**
+ * Interface for controlling the header elevation in response to RecyclerView scroll.
+ */
+interface HeaderElevationController {
+ void onScroll(int scrollY);
+ void disable();
+}
+
+/**
+ * Implementation of the header elevation mechanism for pre-L devices. It simulates elevation
+ * by drawing a gradient under the header bar.
+ */
+final class HeaderElevationControllerV16 implements HeaderElevationController {
+
+ private final View mShadow;
+
+ private final float mScrollToElevation;
+
+ public HeaderElevationControllerV16(View header) {
+ Resources res = header.getContext().getResources();
+ mScrollToElevation = res.getDimension(R.dimen.all_apps_header_scroll_to_elevation);
+
+ mShadow = new View(header.getContext());
+ mShadow.setBackground(new GradientDrawable(
+ GradientDrawable.Orientation.TOP_BOTTOM, new int[] {0x44000000, 0x00000000}));
+ mShadow.setAlpha(0);
+
+ FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(
+ FrameLayout.LayoutParams.MATCH_PARENT,
+ res.getDimensionPixelSize(R.dimen.all_apps_header_shadow_height));
+ lp.topMargin = ((FrameLayout.LayoutParams) header.getLayoutParams()).height;
+
+ ((ViewGroup) header.getParent()).addView(mShadow, lp);
+ }
+
+ @Override
+ public void onScroll(int scrollY) {
+ float elevationPct = (float) Math.min(scrollY, mScrollToElevation) /
+ mScrollToElevation;
+ mShadow.setAlpha(elevationPct);
+ }
+
+ @Override
+ public void disable() {
+ ViewGroup parent = (ViewGroup) mShadow.getParent();
+ if (parent != null) {
+ parent.removeView(mShadow);
+ }
+ }
+}
+
+/**
+ * Implementation of the header elevation mechanism for L+ devices, which makes use of the native
+ * view elevation.
+ */
+@TargetApi(Build.VERSION_CODES.LOLLIPOP)
+final class HeaderElevationControllerVL implements HeaderElevationController {
+
+ private final View mHeader;
+ private final float mMaxElevation;
+ private final float mScrollToElevation;
+
+ public HeaderElevationControllerVL(View header) {
+ mHeader = header;
+
+ Resources res = header.getContext().getResources();
+ mMaxElevation = res.getDimension(R.dimen.all_apps_header_max_elevation);
+ mScrollToElevation = res.getDimension(R.dimen.all_apps_header_scroll_to_elevation);
+ }
+
+ @Override
+ public void onScroll(int scrollY) {
+ float elevationPct = (float) Math.min(scrollY, mScrollToElevation) /
+ mScrollToElevation;
+ float newElevation = mMaxElevation * elevationPct;
+ if (Float.compare(mHeader.getElevation(), newElevation) != 0) {
+ mHeader.setElevation(newElevation);
+ }
+ }
+
+ @Override
+ public void disable() { }
+}
+
+/**
* The all apps view container.
*/
public class AppsContainerView extends BaseContainerView implements DragSource, Insettable,
TextWatcher, TextView.OnEditorActionListener, LauncherTransitionable,
AlphabeticalAppsList.FilterChangedCallback, AppsGridAdapter.PredictionBarSpacerCallbacks,
- View.OnTouchListener, View.OnClickListener, View.OnLongClickListener {
+ View.OnTouchListener, View.OnClickListener, View.OnLongClickListener,
+ ViewTreeObserver.OnPreDrawListener {
public static final boolean GRID_MERGE_SECTIONS = true;
@@ -96,8 +182,7 @@
// Normal container insets
private int mContainerInset;
private int mPredictionBarHeight;
- // RecyclerView scroll position
- @Thunk int mRecyclerViewScrollY;
+ private int mLastRecyclerViewScrollPos = -1;
private CheckLongPressHelper mPredictionIconCheckForLongPress;
private View mPredictionIconUnderTouch;
@@ -266,14 +351,6 @@
mAppsRecyclerView.setLayoutManager(mLayoutManager);
mAppsRecyclerView.setAdapter(mAdapter);
mAppsRecyclerView.setHasFixedSize(true);
- mAppsRecyclerView.setOnScrollListenerProxy(
- new BaseContainerRecyclerView.OnScrollToListener() {
- @Override
- public void onScrolledTo(int x, int y) {
- mRecyclerViewScrollY = y;
- onRecyclerViewScrolled();
- }
- });
if (mItemDecoration != null) {
mAppsRecyclerView.addItemDecoration(mItemDecoration);
}
@@ -283,9 +360,7 @@
@Override
public void onBindPredictionBar() {
- if (!updatePredictionBarVisibility()) {
- return;
- }
+ updatePredictionBarVisibility();
List<AppInfo> predictedApps = mApps.getPredictedApps();
int childCount = mPredictionBarView.getChildCount();
@@ -401,6 +476,12 @@
}
@Override
+ public boolean onPreDraw() {
+ synchronizeToRecyclerViewScrollPosition(mAppsRecyclerView.getScrollPosition());
+ return true;
+ }
+
+ @Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
return handleTouchEvent(ev);
}
@@ -600,7 +681,11 @@
@Override
public void onLauncherTransitionPrepare(Launcher l, boolean animated, boolean toWorkspace) {
- // Do nothing
+ // Register for a pre-draw listener to synchronize the recycler view scroll to other views
+ // in this container
+ if (!toWorkspace) {
+ getViewTreeObserver().addOnPreDrawListener(this);
+ }
}
@Override
@@ -620,18 +705,26 @@
hideSearchField(false, false);
}
}
+ if (toWorkspace) {
+ getViewTreeObserver().removeOnPreDrawListener(this);
+ mLastRecyclerViewScrollPos = -1;
+ }
}
/**
* Updates the container when the recycler view is scrolled.
*/
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
- private void onRecyclerViewScrolled() {
- if (DYNAMIC_HEADER_ELEVATION) {
- mElevationController.onScroll(mRecyclerViewScrollY);
- }
+ private void synchronizeToRecyclerViewScrollPosition(int scrollY) {
+ if (mLastRecyclerViewScrollPos != scrollY) {
+ mLastRecyclerViewScrollPos = scrollY;
+ if (DYNAMIC_HEADER_ELEVATION) {
+ mElevationController.onScroll(scrollY);
+ }
- mPredictionBarView.setTranslationY(-mRecyclerViewScrollY + mAppsRecyclerView.getPaddingTop());
+ // Scroll the prediction bar with the contents of the recycler view
+ mPredictionBarView.setTranslationY(-scrollY + mAppsRecyclerView.getPaddingTop());
+ }
}
@Override
@@ -686,6 +779,19 @@
}
}
break;
+ case MotionEvent.ACTION_MOVE:
+ if (mPredictionIconUnderTouch != null) {
+ float dist = (float) Math.hypot(x - mPredictionIconTouchDownPos.x,
+ y - mPredictionIconTouchDownPos.y);
+ if (dist > ViewConfiguration.get(getContext()).getScaledTouchSlop()) {
+ if (mPredictionIconCheckForLongPress != null) {
+ mPredictionIconCheckForLongPress.cancelLongPress();
+ }
+ mPredictionIconCheckForLongPress = null;
+ mPredictionIconUnderTouch = null;
+ }
+ }
+ break;
case MotionEvent.ACTION_UP:
if (mBoundsCheckLastTouchDownPos.x > -1) {
ViewConfiguration viewConfig = ViewConfiguration.get(getContext());
@@ -728,8 +834,19 @@
* Returns the predicted app in the prediction bar given a set of local coordinates.
*/
private View findPredictedAppAtCoordinate(int x, int y) {
- int[] coord = {x, y};
Rect hitRect = new Rect();
+
+ // Ensure we aren't hitting the search bar
+ int[] coord = {x, y};
+ Utilities.mapCoordInSelfToDescendent(mHeaderView, this, coord);
+ mHeaderView.getHitRect(hitRect);
+ if (hitRect.contains(coord[0], coord[1])) {
+ return null;
+ }
+
+ // Check against the children of the prediction bar
+ coord[0] = x;
+ coord[1] = y;
Utilities.mapCoordInSelfToDescendent(mPredictionBarView, this, coord);
for (int i = 0; i < mPredictionBarView.getChildCount(); i++) {
View child = mPredictionBarView.getChildAt(i);
@@ -843,79 +960,4 @@
private InputMethodManager getInputMethodManager() {
return (InputMethodManager) getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
}
-
- private static interface HeaderElevationController {
-
- public void onScroll(int scrollY);
-
- public void disable();
- }
-
- private static final class HeaderElevationControllerV16 implements HeaderElevationController {
-
- private final View mShadow;
-
- private final float mScrollToElevation;
-
- public HeaderElevationControllerV16(View header) {
- Resources res = header.getContext().getResources();
- mScrollToElevation = res.getDimension(R.dimen.all_apps_header_scroll_to_elevation);
-
- mShadow = new View(header.getContext());
- mShadow.setBackground(new GradientDrawable(
- GradientDrawable.Orientation.TOP_BOTTOM, new int[] {0x44000000, 0x00000000}));
- mShadow.setAlpha(0);
-
- FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(
- LayoutParams.MATCH_PARENT,
- res.getDimensionPixelSize(R.dimen.all_apps_header_shadow_height));
- lp.topMargin = ((FrameLayout.LayoutParams) header.getLayoutParams()).height;
-
- ((ViewGroup) header.getParent()).addView(mShadow, lp);
- }
-
- @Override
- public void onScroll(int scrollY) {
- float elevationPct = (float) Math.min(scrollY, mScrollToElevation) /
- mScrollToElevation;
- mShadow.setAlpha(elevationPct);
- }
-
- @Override
- public void disable() {
- ViewGroup parent = (ViewGroup) mShadow.getParent();
- if (parent != null) {
- parent.removeView(mShadow);
- }
- }
- }
-
- @TargetApi(Build.VERSION_CODES.LOLLIPOP)
- private static final class HeaderElevationControllerVL implements HeaderElevationController {
-
- private final View mHeader;
- private final float mMaxElevation;
- private final float mScrollToElevation;
-
- public HeaderElevationControllerVL(View header) {
- mHeader = header;
-
- Resources res = header.getContext().getResources();
- mMaxElevation = res.getDimension(R.dimen.all_apps_header_max_elevation);
- mScrollToElevation = res.getDimension(R.dimen.all_apps_header_scroll_to_elevation);
- }
-
- @Override
- public void onScroll(int scrollY) {
- float elevationPct = (float) Math.min(scrollY, mScrollToElevation) /
- mScrollToElevation;
- float newElevation = mMaxElevation * elevationPct;
- if (Float.compare(mHeader.getElevation(), newElevation) != 0) {
- mHeader.setElevation(newElevation);
- }
- }
-
- @Override
- public void disable() { }
- }
}
diff --git a/src/com/android/launcher3/BaseContainerRecyclerView.java b/src/com/android/launcher3/BaseContainerRecyclerView.java
index 59e20ca..e52d887 100644
--- a/src/com/android/launcher3/BaseContainerRecyclerView.java
+++ b/src/com/android/launcher3/BaseContainerRecyclerView.java
@@ -29,20 +29,11 @@
public class BaseContainerRecyclerView extends RecyclerView
implements RecyclerView.OnItemTouchListener {
- /**
- * Listener to get notified when the absolute scroll changes.
- */
- public interface OnScrollToListener {
- void onScrolledTo(int x, int y);
- }
-
private static final int SCROLL_DELTA_THRESHOLD_DP = 4;
/** Keeps the last known scrolling delta/velocity along y-axis. */
@Thunk int mDy = 0;
- @Thunk int mScrollY;
private float mDeltaThreshold;
- private OnScrollToListener mScrollToListener;
public BaseContainerRecyclerView(Context context) {
this(context, null);
@@ -68,20 +59,9 @@
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
mDy = dy;
- mScrollY += dy;
- if (mScrollToListener != null) {
- mScrollToListener.onScrolledTo(0, mScrollY);
- }
}
}
- /**
- * Sets an additional scroll listener, only needed for LMR1 version of the support lib.
- */
- public void setOnScrollListenerProxy(OnScrollToListener listener) {
- mScrollToListener = listener;
- }
-
@Override
protected void onFinishInflate() {
super.onFinishInflate();
@@ -106,17 +86,6 @@
}
/**
- * Updates the scroll position, used to workaround a RecyclerView issue with scrolling to
- * position.
- */
- protected void updateScrollY(int scrollY) {
- mScrollY = scrollY;
- if (mScrollToListener != null) {
- mScrollToListener.onScrolledTo(0, mScrollY);
- }
- }
-
- /**
* Returns whether this {@link MotionEvent} should trigger the scroll to be stopped.
*/
protected boolean shouldStopScroll(MotionEvent ev) {
diff --git a/src/com/android/launcher3/BubbleTextView.java b/src/com/android/launcher3/BubbleTextView.java
index 5dc3b12..d39e139 100644
--- a/src/com/android/launcher3/BubbleTextView.java
+++ b/src/com/android/launcher3/BubbleTextView.java
@@ -28,6 +28,7 @@
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.util.AttributeSet;
+import android.util.Log;
import android.util.SparseArray;
import android.util.TypedValue;
import android.view.KeyEvent;
@@ -76,6 +77,7 @@
private boolean mStayPressed;
private boolean mIgnorePressedStateChange;
+ private boolean mDisableRelayout = false;
private IconLoadRequest mIconLoadRequest;
@@ -464,12 +466,20 @@
return icon;
}
+ @Override
+ public void requestLayout() {
+ if (!mDisableRelayout) {
+ super.requestLayout();
+ }
+ }
+
/**
* Applies the item info if it is same as what the view is pointing to currently.
*/
public void reapplyItemInfo(final ItemInfo info) {
if (getTag() == info) {
mIconLoadRequest = null;
+ mDisableRelayout = true;
if (info instanceof AppInfo) {
applyFromApplicationInfo((AppInfo) info);
} else if (info instanceof ShortcutInfo) {
@@ -478,6 +488,7 @@
} else if (info instanceof PackageItemInfo) {
applyFromPackageItemInfo((PackageItemInfo) info);
}
+ mDisableRelayout = false;
}
}
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index a828b1a..51ba2df 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -134,7 +134,7 @@
View.OnTouchListener, PageSwitchListener, LauncherProviderChangeListener,
LauncherStateTransitionAnimation.Callbacks {
static final String TAG = "Launcher";
- static final boolean LOGD = true;
+ static final boolean LOGD = false;
// Temporary flag
static final boolean DISABLE_ALL_APPS_SEARCH_INTEGRATION = true;
@@ -185,10 +185,6 @@
private static final String RUNTIME_STATE_PENDING_ADD_CELL_X = "launcher.add_cell_x";
// Type: int
private static final String RUNTIME_STATE_PENDING_ADD_CELL_Y = "launcher.add_cell_y";
- // Type: boolean
- private static final String RUNTIME_STATE_PENDING_FOLDER_RENAME = "launcher.rename_folder";
- // Type: long
- private static final String RUNTIME_STATE_PENDING_FOLDER_RENAME_ID = "launcher.rename_folder_id";
// Type: int
private static final String RUNTIME_STATE_PENDING_ADD_SPAN_X = "launcher.add_span_x";
// Type: int
@@ -261,8 +257,6 @@
private int[] mTmpAddItemCellCoordinates = new int[2];
- private FolderInfo mFolderInfo;
-
private Hotseat mHotseat;
private ViewGroup mOverviewPanel;
@@ -480,11 +474,11 @@
if (DISABLE_SYNCHRONOUS_BINDING_CURRENT_PAGE) {
// If the user leaves launcher, then we should just load items asynchronously when
// they return.
- mModel.startLoader(true, PagedView.INVALID_RESTORE_PAGE);
+ mModel.startLoader(PagedView.INVALID_RESTORE_PAGE);
} else {
// We only load the page synchronously if the user rotates (or triggers a
// configuration change) while launcher is in the foreground
- mModel.startLoader(true, mWorkspace.getRestorePage());
+ mModel.startLoader(mWorkspace.getRestorePage());
}
}
@@ -1051,7 +1045,7 @@
mPaused = false;
if (mRestoring || mOnResumeNeedsLoad) {
setWorkspaceLoading(true);
- mModel.startLoader(true, PagedView.INVALID_RESTORE_PAGE);
+ mModel.startLoader(PagedView.INVALID_RESTORE_PAGE);
mRestoring = false;
mOnResumeNeedsLoad = false;
}
@@ -1385,13 +1379,6 @@
mRestoring = true;
}
- boolean renameFolder = savedState.getBoolean(RUNTIME_STATE_PENDING_FOLDER_RENAME, false);
- if (renameFolder) {
- long id = savedState.getLong(RUNTIME_STATE_PENDING_FOLDER_RENAME_ID);
- mFolderInfo = mModel.getFolderById(this, sFolders, id);
- mRestoring = true;
- }
-
mItemIdToViewId = (HashMap<Integer, Integer>)
savedState.getSerializable(RUNTIME_STATE_VIEW_IDS);
}
@@ -1703,11 +1690,11 @@
updateAutoAdvanceState();
} else if (ENABLE_DEBUG_INTENTS && DebugIntents.DELETE_DATABASE.equals(action)) {
mModel.resetLoadedState(false, true);
- mModel.startLoader(false, PagedView.INVALID_RESTORE_PAGE,
+ mModel.startLoader(PagedView.INVALID_RESTORE_PAGE,
LauncherModel.LOADER_FLAG_CLEAR_WORKSPACE);
} else if (ENABLE_DEBUG_INTENTS && DebugIntents.MIGRATE_DATABASE.equals(action)) {
mModel.resetLoadedState(false, true);
- mModel.startLoader(false, PagedView.INVALID_RESTORE_PAGE,
+ mModel.startLoader(PagedView.INVALID_RESTORE_PAGE,
LauncherModel.LOADER_FLAG_CLEAR_WORKSPACE
| LauncherModel.LOADER_FLAG_MIGRATE_SHORTCUTS);
}
@@ -2035,11 +2022,6 @@
outState.putInt(RUNTIME_STATE_PENDING_ADD_WIDGET_ID, mPendingAddWidgetId);
}
- if (mFolderInfo != null && mWaitingForResult) {
- outState.putBoolean(RUNTIME_STATE_PENDING_FOLDER_RENAME, true);
- outState.putLong(RUNTIME_STATE_PENDING_FOLDER_RENAME_ID, mFolderInfo.id);
- }
-
// Save the current widgets tray?
// TODO(hyunyoungs)
outState.putSerializable(RUNTIME_STATE_VIEW_IDS, mItemIdToViewId);
@@ -3431,7 +3413,7 @@
* Shows the widgets view.
*/
void showWidgetsView(boolean animated, boolean resetPageToZero) {
- Log.d(TAG, "showWidgetsView:" + animated + " resetPageToZero:" + resetPageToZero);
+ if (LOGD) Log.d(TAG, "showWidgetsView:" + animated + " resetPageToZero:" + resetPageToZero);
if (resetPageToZero) {
mWidgetsView.scrollToTop();
}
@@ -3497,8 +3479,7 @@
}
public void enterSpringLoadedDragMode() {
- Log.d(TAG, String.format("enterSpringLoadedDragMode [mState=%s",
- mState.name()));
+ if (LOGD) Log.d(TAG, String.format("enterSpringLoadedDragMode [mState=%s", mState.name()));
if (mState == State.WORKSPACE || mState == State.APPS_SPRING_LOADED ||
mState == State.WIDGETS_SPRING_LOADED) {
return;
@@ -3693,7 +3674,7 @@
*/
private boolean waitUntilResume(Runnable run, boolean deletePreviousRunnables) {
if (mPaused) {
- Log.i(TAG, "Deferring update until onResume");
+ if (LOGD) Log.d(TAG, "Deferring update until onResume");
if (deletePreviousRunnables) {
while (mBindOnResumeCallbacks.remove(run)) {
}
@@ -3729,7 +3710,7 @@
*/
public boolean setLoadOnResume() {
if (mPaused) {
- Log.i(TAG, "setLoadOnResume");
+ if (LOGD) Log.d(TAG, "setLoadOnResume");
mOnResumeNeedsLoad = true;
return true;
} else {
diff --git a/src/com/android/launcher3/LauncherAppState.java b/src/com/android/launcher3/LauncherAppState.java
index d51df32..bde54c3 100644
--- a/src/com/android/launcher3/LauncherAppState.java
+++ b/src/com/android/launcher3/LauncherAppState.java
@@ -33,11 +33,9 @@
import com.android.launcher3.compat.LauncherAppsCompat;
import com.android.launcher3.compat.PackageInstallerCompat;
-import com.android.launcher3.compat.PackageInstallerCompat.PackageInstallInfo;
import com.android.launcher3.util.Thunk;
import java.lang.ref.WeakReference;
-import java.util.ArrayList;
public class LauncherAppState implements DeviceProfile.DeviceProfileCallbacks {
diff --git a/src/com/android/launcher3/LauncherClings.java b/src/com/android/launcher3/LauncherClings.java
index 63d3ebc..c13752c 100644
--- a/src/com/android/launcher3/LauncherClings.java
+++ b/src/com/android/launcher3/LauncherClings.java
@@ -71,7 +71,7 @@
// Copy the shortcuts from the old database
LauncherModel model = mLauncher.getModel();
model.resetLoadedState(false, true);
- model.startLoader(false, PagedView.INVALID_RESTORE_PAGE,
+ model.startLoader(PagedView.INVALID_RESTORE_PAGE,
LauncherModel.LOADER_FLAG_CLEAR_WORKSPACE
| LauncherModel.LOADER_FLAG_MIGRATE_SHORTCUTS);
// Set the flag to skip the folder cling
diff --git a/src/com/android/launcher3/LauncherModel.java b/src/com/android/launcher3/LauncherModel.java
index c56022e..0b3049c 100644
--- a/src/com/android/launcher3/LauncherModel.java
+++ b/src/com/android/launcher3/LauncherModel.java
@@ -1346,40 +1346,32 @@
}
}
if (runLoader) {
- startLoader(false, PagedView.INVALID_RESTORE_PAGE);
+ startLoader(PagedView.INVALID_RESTORE_PAGE);
}
}
- // If there is already a loader task running, tell it to stop.
- // returns true if isLaunching() was true on the old task
- private boolean stopLoaderLocked() {
- boolean isLaunching = false;
+ /**
+ * If there is already a loader task running, tell it to stop.
+ */
+ private void stopLoaderLocked() {
LoaderTask oldTask = mLoaderTask;
if (oldTask != null) {
- if (oldTask.isLaunching()) {
- isLaunching = true;
- }
oldTask.stopLocked();
}
- return isLaunching;
}
public boolean isCurrentCallbacks(Callbacks callbacks) {
return (mCallbacks != null && mCallbacks.get() == callbacks);
}
- public void startLoader(boolean isLaunching, int synchronousBindPage) {
- startLoader(isLaunching, synchronousBindPage, LOADER_FLAG_NONE);
+ public void startLoader(int synchronousBindPage) {
+ startLoader(synchronousBindPage, LOADER_FLAG_NONE);
}
- public void startLoader(boolean isLaunching, int synchronousBindPage, int loadFlags) {
+ public void startLoader(int synchronousBindPage, int loadFlags) {
// Enable queue before starting loader. It will get disabled in Launcher#finishBindingItems
InstallShortcutReceiver.enableInstallQueue();
synchronized (mLock) {
- if (DEBUG_LOADERS) {
- Log.d(TAG, "startLoader isLaunching=" + isLaunching);
- }
-
// Clear any deferred bind-runnables from the synchronized load process
// We must do this before any loading/binding is scheduled below.
synchronized (mDeferredBindRunnables) {
@@ -1389,11 +1381,10 @@
// Don't bother to start the thread if we know it's not going to do anything
if (mCallbacks != null && mCallbacks.get() != null) {
// If there is already one running, tell it to stop.
- // also, don't downgrade isLaunching if we're already running
- isLaunching = isLaunching || stopLoaderLocked();
- mLoaderTask = new LoaderTask(mApp.getContext(), isLaunching, loadFlags);
+ stopLoaderLocked();
+ mLoaderTask = new LoaderTask(mApp.getContext(), loadFlags);
if (synchronousBindPage != PagedView.INVALID_RESTORE_PAGE
- && mAllAppsLoaded && mWorkspaceLoaded) {
+ && mAllAppsLoaded && mWorkspaceLoaded && !mIsLoaderTaskRunning) {
mLoaderTask.runBindSynchronousPage(synchronousBindPage);
} else {
sWorkerThread.setPriority(Thread.NORM_PRIORITY);
@@ -1484,22 +1475,16 @@
*/
private class LoaderTask implements Runnable {
private Context mContext;
- private boolean mIsLaunching;
@Thunk boolean mIsLoadingAndBindingWorkspace;
private boolean mStopped;
@Thunk boolean mLoadAndBindStepFinished;
private int mFlags;
- LoaderTask(Context context, boolean isLaunching, int flags) {
+ LoaderTask(Context context, int flags) {
mContext = context;
- mIsLaunching = isLaunching;
mFlags = flags;
}
- boolean isLaunching() {
- return mIsLaunching;
- }
-
boolean isLoadingWorkspace() {
return mIsLoadingAndBindingWorkspace;
}
@@ -1600,20 +1585,15 @@
public void run() {
synchronized (mLock) {
+ if (mStopped) {
+ return;
+ }
mIsLoaderTaskRunning = true;
}
// Optimize for end-user experience: if the Launcher is up and // running with the
// All Apps interface in the foreground, load All Apps first. Otherwise, load the
// workspace first (default).
keep_running: {
- // Elevate priority when Home launches for the first time to avoid
- // starving at boot time. Staring at a blank home is not cool.
- synchronized (mLock) {
- if (DEBUG_LOADERS) Log.d(TAG, "Setting thread priority to " +
- (mIsLaunching ? "DEFAULT" : "BACKGROUND"));
- android.os.Process.setThreadPriority(mIsLaunching
- ? Process.THREAD_PRIORITY_DEFAULT : Process.THREAD_PRIORITY_BACKGROUND);
- }
if (DEBUG_LOADERS) Log.d(TAG, "step 1: loading workspace");
loadAndBindWorkspace();
@@ -1621,24 +1601,11 @@
break keep_running;
}
- // Whew! Hard work done. Slow us down, and wait until the UI thread has
- // settled down.
- synchronized (mLock) {
- if (mIsLaunching) {
- if (DEBUG_LOADERS) Log.d(TAG, "Setting thread priority to BACKGROUND");
- android.os.Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
- }
- }
waitForIdle();
// second step
if (DEBUG_LOADERS) Log.d(TAG, "step 2: loading all apps");
loadAndBindAllApps();
-
- // Restore the default thread priority after we are done loading items
- synchronized (mLock) {
- android.os.Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT);
- }
}
// Clear out this reference, otherwise we end up holding it until all of the
@@ -2783,6 +2750,11 @@
}
if (!mAllAppsLoaded) {
loadAllApps();
+ synchronized (LoaderTask.this) {
+ if (mStopped) {
+ return;
+ }
+ }
updateAllAppsIconsCache();
synchronized (LoaderTask.this) {
if (mStopped) {
@@ -2974,7 +2946,6 @@
public void dumpState() {
synchronized (sBgLock) {
Log.d(TAG, "mLoaderTask.mContext=" + mContext);
- Log.d(TAG, "mLoaderTask.mIsLaunching=" + mIsLaunching);
Log.d(TAG, "mLoaderTask.mStopped=" + mStopped);
Log.d(TAG, "mLoaderTask.mLoadAndBindStepFinished=" + mLoadAndBindStepFinished);
Log.d(TAG, "mItems size=" + sBgWorkspaceItems.size());