diff options
author | Michael Jurka <mikejurka@google.com> | 2013-08-27 15:48:58 +0200 |
---|---|---|
committer | Michael Jurka <mikejurka@google.com> | 2013-08-29 18:14:29 +0200 |
commit | fe09cb7fe3ec1ab3e7aabd2d0415de61df31c4db (patch) | |
tree | 4c14f71b68779fc152bf3b7615cc829ec3355e60 /src | |
parent | 4caf298a2c9d861d69f5a47b747ada911b125b6d (diff) | |
download | android_packages_apps_Trebuchet-fe09cb7fe3ec1ab3e7aabd2d0415de61df31c4db.tar.gz android_packages_apps_Trebuchet-fe09cb7fe3ec1ab3e7aabd2d0415de61df31c4db.tar.bz2 android_packages_apps_Trebuchet-fe09cb7fe3ec1ab3e7aabd2d0415de61df31c4db.zip |
Improve wallpaper cropping
- Add support for tablets
- Add support for parallax with user-cropped images
- Improve behavior in landscape
Change-Id: I50c4bba59b03d26d595a086a9ea425894f341705
Diffstat (limited to 'src')
-rw-r--r-- | src/com/android/launcher3/CropView.java | 20 | ||||
-rw-r--r-- | src/com/android/launcher3/WallpaperCropActivity.java | 35 | ||||
-rw-r--r-- | src/com/android/launcher3/WallpaperPickerActivity.java | 158 | ||||
-rw-r--r-- | src/com/android/launcher3/Workspace.java | 75 |
4 files changed, 206 insertions, 82 deletions
diff --git a/src/com/android/launcher3/CropView.java b/src/com/android/launcher3/CropView.java index f9046432e..25ab5cdad 100644 --- a/src/com/android/launcher3/CropView.java +++ b/src/com/android/launcher3/CropView.java @@ -17,6 +17,7 @@ package com.android.launcher3; import android.content.Context; +import android.graphics.Point; import android.graphics.RectF; import android.util.AttributeSet; import android.view.MotionEvent; @@ -79,17 +80,30 @@ public class CropView extends TiledImageView implements OnScaleGestureListener { return new RectF(cropLeft, cropTop, cropRight, cropBottom); } + public Point getSourceDimensions() { + return new Point(mRenderer.source.getImageWidth(), mRenderer.source.getImageHeight()); + } + public void setTileSource(TileSource source, Runnable isReadyCallback) { super.setTileSource(source, isReadyCallback); - updateMinScale(getWidth(), getHeight(), source); + updateMinScale(getWidth(), getHeight(), source, true); } protected void onSizeChanged(int w, int h, int oldw, int oldh) { - updateMinScale(w, h, mRenderer.source); + updateMinScale(w, h, mRenderer.source, false); } - private void updateMinScale(int w, int h, TileSource source) { + public void setScale(float scale) { synchronized (mLock) { + mRenderer.scale = scale; + } + } + + private void updateMinScale(int w, int h, TileSource source, boolean resetScale) { + synchronized (mLock) { + if (resetScale) { + mRenderer.scale = 1; + } if (source != null) { mMinScale = Math.max(w / (float) source.getImageWidth(), h / (float) source.getImageHeight()); diff --git a/src/com/android/launcher3/WallpaperCropActivity.java b/src/com/android/launcher3/WallpaperCropActivity.java index 2978c850a..b08750683 100644 --- a/src/com/android/launcher3/WallpaperCropActivity.java +++ b/src/com/android/launcher3/WallpaperCropActivity.java @@ -62,6 +62,7 @@ public class WallpaperCropActivity extends Activity { protected class BitmapCropTask extends AsyncTask<Void, Void, Boolean> { Uri mInUri = null; + int mInResId = 0; InputStream mInStream; RectF mCropBounds = null; int mOutWidth, mOutHeight; @@ -71,9 +72,10 @@ public class WallpaperCropActivity extends Activity { boolean mSetWallpaper; boolean mSaveCroppedBitmap; Bitmap mCroppedBitmap; + Runnable mOnEndRunnable; public BitmapCropTask(Uri inUri, RectF cropBounds, int outWidth, int outHeight, - boolean setWallpaper, boolean saveCroppedBitmap) { + boolean setWallpaper, boolean saveCroppedBitmap, Runnable onEndRunnable) { mInUri = inUri; mCropBounds = cropBounds; mOutWidth = outWidth; @@ -81,17 +83,35 @@ public class WallpaperCropActivity extends Activity { mWPManager = WallpaperManager.getInstance(getApplicationContext()); mSetWallpaper = setWallpaper; mSaveCroppedBitmap = saveCroppedBitmap; + mOnEndRunnable = onEndRunnable; + } + + public BitmapCropTask(int inResId, RectF cropBounds, int outWidth, int outHeight, + boolean setWallpaper, boolean saveCroppedBitmap, Runnable onEndRunnable) { + mInResId = inResId; + mCropBounds = cropBounds; + mOutWidth = outWidth; + mOutHeight = outHeight; + mWPManager = WallpaperManager.getInstance(getApplicationContext()); + mSetWallpaper = setWallpaper; + mSaveCroppedBitmap = saveCroppedBitmap; + mOnEndRunnable = onEndRunnable; } // Helper to setup input stream private void regenerateInputStream() { - if (mInUri == null) { - Log.w(LOGTAG, "cannot read original file, no input URI given"); + if (mInUri == null && mInResId == 0) { + Log.w(LOGTAG, "cannot read original file, no input URI or resource ID given"); } else { Utils.closeSilently(mInStream); try { - mInStream = new BufferedInputStream( - getContentResolver().openInputStream(mInUri)); + if (mInUri != null) { + mInStream = new BufferedInputStream( + getContentResolver().openInputStream(mInUri)); + } else { + mInStream = new BufferedInputStream( + getResources().openRawResource(mInResId)); + } } catch (FileNotFoundException e) { Log.w(LOGTAG, "cannot read file: " + mInUri.toString(), e); } @@ -227,13 +247,15 @@ public class WallpaperCropActivity extends Activity { try { mWPManager.setStream(new ByteArrayInputStream(tmpOut .toByteArray())); - updateWallpaperDimensions(mOutWidth, mOutHeight); } catch (IOException e) { Log.w(LOGTAG, "cannot write stream to wallpaper", e); failure = true; } } } + if (mOnEndRunnable != null) { + mOnEndRunnable.run(); + } } else { Log.w(LOGTAG, "cannot compress bitmap"); failure = true; @@ -266,6 +288,7 @@ public class WallpaperCropActivity extends Activity { editor.remove(WALLPAPER_HEIGHT_KEY); } editor.commit(); + WallpaperPickerActivity.suggestWallpaperDimension(getResources(), sp, getWindowManager(), WallpaperManager.getInstance(this)); } diff --git a/src/com/android/launcher3/WallpaperPickerActivity.java b/src/com/android/launcher3/WallpaperPickerActivity.java index a1c74d2b2..2d8dd765c 100644 --- a/src/com/android/launcher3/WallpaperPickerActivity.java +++ b/src/com/android/launcher3/WallpaperPickerActivity.java @@ -20,7 +20,6 @@ import android.app.ActionBar; import android.app.Activity; import android.app.WallpaperManager; import android.content.ComponentName; -import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; import android.content.pm.ActivityInfo; @@ -35,6 +34,7 @@ import android.graphics.drawable.LevelListDrawable; import android.net.Uri; import android.os.Bundle; import android.util.Log; +import android.view.Display; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuItem; @@ -53,7 +53,6 @@ import android.widget.TextView; import com.android.photos.BitmapRegionTileSource; -import java.io.IOException; import java.util.ArrayList; import java.util.List; @@ -99,14 +98,35 @@ public class WallpaperPickerActivity extends WallpaperCropActivity { meta.mGalleryImageUri, 1024, 0), null); mCropView.setTouchEnabled(true); } else { - mCropView.setTileSource(new BitmapRegionTileSource(WallpaperPickerActivity.this, - meta.mWallpaperResId, 1024, 0), null); + BitmapRegionTileSource source = new BitmapRegionTileSource( + WallpaperPickerActivity.this, meta.mWallpaperResId, 1024, 0); + mCropView.setTileSource(source, null); + Point wallpaperSize = getDefaultWallpaperSize(getResources(), getWindowManager()); + RectF crop = getMaxCropRect(source.getImageWidth(), source.getImageHeight(), + wallpaperSize.x, wallpaperSize.y); + mCropView.setScale(wallpaperSize.x / crop.width()); mCropView.setTouchEnabled(false); - mCropView.moveToUpperLeft(); } } }; + private RectF getMaxCropRect(int inWidth, int inHeight, int outWidth, int outHeight) { + RectF cropRect = new RectF(); + // Get a crop rect that will fit this + if (inWidth / (float) inHeight > outWidth / (float) outHeight) { + cropRect.top = 0; + cropRect.bottom = inHeight; + cropRect.left = (inWidth - (outWidth / (float) outHeight) * inHeight) / 2; + cropRect.right = inWidth - cropRect.left; + } else { + cropRect.left = 0; + cropRect.right = inWidth; + cropRect.top = (inHeight - (outHeight / (float) outWidth) * inWidth) / 2; + cropRect.bottom = inHeight - cropRect.top; + } + return cropRect; + } + protected void onActivityResult(int requestCode, int resultCode, Intent data) { if (requestCode == IMAGE_PICK && resultCode == RESULT_OK) { Uri uri = data.getData(); @@ -124,22 +144,11 @@ public class WallpaperPickerActivity extends WallpaperCropActivity { int width = res.getDimensionPixelSize(R.dimen.wallpaperThumbnailWidth); int height = res.getDimensionPixelSize(R.dimen.wallpaperThumbnailHeight); - BitmapCropTask cropTask = new BitmapCropTask(uri, null, width, height, false, true); + BitmapCropTask cropTask = + new BitmapCropTask(uri, null, width, height, false, true, null); Point bounds = cropTask.getImageBounds(); - RectF cropRect = new RectF(); - // Get a crop rect that will fit this - if (bounds.x / (float) bounds.y > width / (float) height) { - cropRect.top = 0; - cropRect.bottom = bounds.y; - cropRect.left = (bounds.x - (width / (float) height) * bounds.y) / 2; - cropRect.right = bounds.x - cropRect.left; - } else { - cropRect.left = 0; - cropRect.right = bounds.x; - cropRect.top = (bounds.y - (height / (float) width) * bounds.x) / 2; - cropRect.bottom = bounds.y - cropRect.top; - } + RectF cropRect = getMaxCropRect(bounds.x, bounds.y, width, height); cropTask.setCropBounds(cropRect); if (cropTask.cropBitmap()) { @@ -154,6 +163,7 @@ public class WallpaperPickerActivity extends WallpaperCropActivity { ThumbnailMetaData meta = new ThumbnailMetaData(); meta.mGalleryImageUri = uri; pickedImageThumbnail.setTag(meta); + pickedImageThumbnail.setOnClickListener(mThumbnailOnClickListener); mThumbnailOnClickListener.onClick(pickedImageThumbnail); } else if (requestCode == PICK_WALLPAPER_THIRD_PARTY_ACTIVITY) { // No result code is returned; just return @@ -209,38 +219,84 @@ public class WallpaperPickerActivity extends WallpaperCropActivity { new View.OnClickListener() { @Override public void onClick(View v) { - ThumbnailMetaData meta = (ThumbnailMetaData) mSelectedThumb.getTag(); if (meta.mLaunchesGallery) { // shouldn't be selected, but do nothing } else if (meta.mGalleryImageUri != null) { // Get the crop // TODO: get outwidth/outheight more robustly? - BitmapCropTask cropTask = new BitmapCropTask(meta.mGalleryImageUri, - mCropView.getCrop(), mCropView.getWidth(), mCropView.getHeight(), - true, false); + Point inSize = mCropView.getSourceDimensions(); + + Point minDims = new Point(); + Point maxDims = new Point(); + Display d = getWindowManager().getDefaultDisplay(); + d.getCurrentSizeRange(minDims, maxDims); + Point displaySize = new Point(); + d.getSize(displaySize); + + // Get the crop + RectF cropRect = mCropView.getCrop(); + + float cropScale = displaySize.x / (float) cropRect.width(); + if (displaySize.x < displaySize.y) { // PORTRAIT + // Save the leftmost position for portrait mode + // Extend the crop all the way to the right, for parallax + float extraSpaceToRight = inSize.x - cropRect.right; + cropRect.right = inSize.x; + // Add some space to the left for the landscape case + //float extraLandscapeWidth = maxDims.x - cropRect.width(); + //float shiftLeft = Math.min( + // Math.min(extraSpaceToRight, cropRect.left), + // extraLandscapeWidth / 2); + //cropRect.left -= shiftLeft; + // Adjust the "leftMost variable now" + //float leftForPortrait = shiftLeft; + } else { // LANDSCAPE + float leftForPortrait = (cropRect.width() - minDims.x) / 2; + cropRect.right = inSize.x; + // TODO: how to actually get the proper portrait height? + // This is not quite right: + float portraitHeight = Math.max(maxDims.x, maxDims.y); + float extraPortraitHeight = portraitHeight - cropRect.height(); + float expandHeight = + Math.min(Math.min(inSize.y - cropRect.bottom, cropRect.top), + extraPortraitHeight / 2); + cropRect.top -= expandHeight; + cropRect.bottom += expandHeight; + } + final int outWidth = (int) Math.ceil(cropRect.width() * cropScale); + final int outHeight = (int) Math.ceil(cropRect.height() * cropScale); + + Runnable onEndCrop = new Runnable() { + public void run() { + updateWallpaperDimensions(outWidth, outHeight); + } + }; + BitmapCropTask cropTask = new BitmapCropTask(meta.mGalleryImageUri, + cropRect, outWidth, outHeight, true, false, onEndCrop); cropTask.execute(); } else if (meta.mWallpaperResId != 0) { - try { - WallpaperManager wm = - WallpaperManager.getInstance(getApplicationContext()); - wm.setResource(meta.mWallpaperResId); - // passing 0 will just revert back to using the default wallpaper - // size (setWallpaperDimension) - updateWallpaperDimensions(0, 0); - String spKey = LauncherAppState.getSharedPreferencesKey(); - SharedPreferences sp = - getSharedPreferences(spKey, Context.MODE_PRIVATE); - SharedPreferences.Editor editor = sp.edit(); - editor.remove(WALLPAPER_WIDTH_KEY); - editor.remove(WALLPAPER_HEIGHT_KEY); - editor.commit(); - setResult(Activity.RESULT_OK); - finish(); - } catch (IOException e) { - Log.e(TAG, "Failed to set wallpaper: " + e); - } + // crop this image and scale it down to the default wallpaper size for + // this device + Point inSize = mCropView.getSourceDimensions(); + Point outSize = getDefaultWallpaperSize(getResources(), + getWindowManager()); + RectF crop = getMaxCropRect( + inSize.x, inSize.y, outSize.x, outSize.y); + Runnable onEndCrop = new Runnable() { + public void run() { + // Passing 0, 0 will cause launcher to revert to using the + // default wallpaper size + updateWallpaperDimensions(0, 0); + } + }; + BitmapCropTask cropTask = new BitmapCropTask(meta.mWallpaperResId, + crop, outSize.x, outSize.y, + true, false, onEndCrop); + cropTask.execute(); + setResult(Activity.RESULT_OK); + finish(); } } }); @@ -371,10 +427,7 @@ public class WallpaperPickerActivity extends WallpaperCropActivity { return x * aspectRatio + y; } - static public void suggestWallpaperDimension(Resources res, - final SharedPreferences sharedPrefs, - WindowManager windowManager, - final WallpaperManager wallpaperManager) { + static private Point getDefaultWallpaperSize(Resources res, WindowManager windowManager) { Point minDims = new Point(); Point maxDims = new Point(); windowManager.getDefaultDisplay().getCurrentSizeRange(minDims, maxDims); @@ -393,11 +446,20 @@ public class WallpaperPickerActivity extends WallpaperCropActivity { defaultWidth = Math.max((int) (minDim * WALLPAPER_SCREENS_SPAN), maxDim); defaultHeight = maxDim; } + return new Point(defaultWidth, defaultHeight); + } + + static public void suggestWallpaperDimension(Resources res, + final SharedPreferences sharedPrefs, + WindowManager windowManager, + final WallpaperManager wallpaperManager) { + final Point defaultWallpaperSize = getDefaultWallpaperSize(res, windowManager); + new Thread("suggestWallpaperDimension") { public void run() { // If we have saved a wallpaper width/height, use that instead - int savedWidth = sharedPrefs.getInt(WALLPAPER_WIDTH_KEY, defaultWidth); - int savedHeight = sharedPrefs.getInt(WALLPAPER_HEIGHT_KEY, defaultHeight); + int savedWidth = sharedPrefs.getInt(WALLPAPER_WIDTH_KEY, defaultWallpaperSize.x); + int savedHeight = sharedPrefs.getInt(WALLPAPER_HEIGHT_KEY, defaultWallpaperSize.y); wallpaperManager.suggestDesiredDimensions(savedWidth, savedHeight); } }.start(); diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java index 05f9e2d7f..b6ef27d6d 100644 --- a/src/com/android/launcher3/Workspace.java +++ b/src/com/android/launcher3/Workspace.java @@ -971,16 +971,7 @@ public class Workspace extends SmoothPagedView } - private float wallpaperOffsetForCurrentScroll() { - // Set wallpaper offset steps (1 / (number of screens - 1)) - mWallpaperManager.setWallpaperOffsetSteps(1.0f / (getChildCount() - 1), 1.0f); - if (mMaxScrollX == 0) { - return 0; - } - // do different behavior if it's alive wallpaper? - return getScrollX() / (float) mMaxScrollX; - } protected void snapToPage(int whichPage, Runnable r) { if (mDelayedSnapToPageRunnable != null) { @@ -998,7 +989,7 @@ public class Workspace extends SmoothPagedView float mFinalOffset = 0.0f; float mCurrentOffset = 0.0f; //long mLastWallpaperOffsetUpdateTime; - boolean mWaitingForCallback; + boolean mWaitingForUpdate; Choreographer mChoreographer; Interpolator mInterpolator; boolean mAnimating; @@ -1014,10 +1005,18 @@ public class Workspace extends SmoothPagedView @Override public void doFrame(long frameTimeNanos) { - mWaitingForCallback = false; - if (computeScrollOffset()) { - mWallpaperManager.setWallpaperOffsets(mWindowToken, - mWallpaperOffset.getCurrX(), 0f); + updateOffset(false); + } + + + private void updateOffset(boolean force) { + if (mWaitingForUpdate || force) { + mWaitingForUpdate = false; + if (computeScrollOffset()) { + mWallpaperManager.setWallpaperOffsets(mWindowToken, + mWallpaperOffset.getCurrX(), 0.5f); + setWallpaperOffsetSteps(); + } } } @@ -1034,13 +1033,38 @@ public class Workspace extends SmoothPagedView mCurrentOffset = mFinalOffset; } + if (Math.abs(mCurrentOffset - mFinalOffset) > 0.0000001f) { + scheduleUpdate(); + } if (Math.abs(oldOffset - mCurrentOffset) > 0.0000001f) { - scheduleCallback(); return true; } return false; } + private float wallpaperOffsetForCurrentScroll() { + if (getChildCount() <= 1) { + return 0; + } + final int lastIndex = isLayoutRtl() ? 0 : getChildCount() - 1; + final int firstIndex = isLayoutRtl() ? getChildCount() - 2 : 1; + int firstPageScrollX = getScrollForPage(firstIndex); + int scrollRange = getScrollForPage(lastIndex) - firstPageScrollX; + if (scrollRange == 0) { + return 0; + } else { + // do different behavior if it's a live wallpaper? + float offset = (getScrollX() - firstPageScrollX) / (float) scrollRange; + return offset; + } + } + + public void syncWithScroll() { + float offset = wallpaperOffsetForCurrentScroll(); + mWallpaperOffset.setFinalX(offset); + updateOffset(true); + } + public float getCurrX() { return mCurrentOffset; } @@ -1055,8 +1079,13 @@ public class Workspace extends SmoothPagedView mAnimationStartTime = System.currentTimeMillis(); } + private void setWallpaperOffsetSteps() { + // Set wallpaper offset steps (1 / (number of screens - 1)) + mWallpaperManager.setWallpaperOffsetSteps(1.0f / (getChildCount() - 1), 1.0f); + } + public void setFinalX(float x) { - scheduleCallback(); + scheduleUpdate(); mFinalOffset = Math.max(0f, Math.min(x, 1.0f)); if (getChildCount() != mNumScreens) { if (mNumScreens > 0) { @@ -1067,10 +1096,10 @@ public class Workspace extends SmoothPagedView } } - private void scheduleCallback() { - if (!mWaitingForCallback) { + private void scheduleUpdate() { + if (!mWaitingForUpdate) { mChoreographer.postFrameCallback(this); - mWaitingForCallback = true; + mWaitingForUpdate = true; } } @@ -1082,11 +1111,7 @@ public class Workspace extends SmoothPagedView @Override public void computeScroll() { super.computeScroll(); - syncWallpaperOffsetWithScroll(); - } - - private void syncWallpaperOffsetWithScroll() { - mWallpaperOffset.setFinalX(wallpaperOffsetForCurrentScroll()); + mWallpaperOffset.syncWithScroll(); } void showOutlines() { @@ -1325,7 +1350,7 @@ public class Workspace extends SmoothPagedView @Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) { if (mFirstLayout && mCurrentPage >= 0 && mCurrentPage < getChildCount()) { - syncWallpaperOffsetWithScroll(); + mWallpaperOffset.syncWithScroll(); mWallpaperOffset.jumpToFinal(); } super.onLayout(changed, left, top, right, bottom); |