diff options
Diffstat (limited to 'src/com')
-rw-r--r-- | src/com/android/camera/CameraActivity.java | 14 | ||||
-rw-r--r-- | src/com/android/camera/ui/FilmStripView.java | 556 |
2 files changed, 304 insertions, 266 deletions
diff --git a/src/com/android/camera/CameraActivity.java b/src/com/android/camera/CameraActivity.java index 2cff06306..1baa865fd 100644 --- a/src/com/android/camera/CameraActivity.java +++ b/src/com/android/camera/CameraActivity.java @@ -153,7 +153,10 @@ public class CameraActivity extends Activity } @Override public void onServiceDisconnected(ComponentName className) { - mMediaSaveService = null; + if (mMediaSaveService != null) { + mMediaSaveService.setListener(null); + mMediaSaveService = null; + } }}; // close activity when screen turns off @@ -403,15 +406,10 @@ public class CameraActivity extends Activity private void bindMediaSaveService() { Intent intent = new Intent(this, MediaSaveService.class); - startService(intent); // start service before binding it so the - // service won't be killed if we unbind it. bindService(intent, mConnection, Context.BIND_AUTO_CREATE); } private void unbindMediaSaveService() { - if (mMediaSaveService != null) { - mMediaSaveService.setListener(null); - } if (mConnection != null) { unbindService(mConnection); } @@ -570,7 +568,6 @@ public class CameraActivity extends Activity mCurrentModule.init(this, mRootView); mOrientationListener = new MyOrientationEventListener(this); mMainHandler = new Handler(getMainLooper()); - bindMediaSaveService(); if (!mSecureCamera) { mDataAdapter = mWrappedDataAdapter; @@ -637,6 +634,7 @@ public class CameraActivity extends Activity @Override public void onStart() { super.onStart(); + bindMediaSaveService(); mPanoramaViewHelper.onStart(); } @@ -644,11 +642,11 @@ public class CameraActivity extends Activity protected void onStop() { super.onStop(); mPanoramaViewHelper.onStop(); + unbindMediaSaveService(); } @Override public void onDestroy() { - unbindMediaSaveService(); if (mSecureCamera) unregisterReceiver(mScreenOffReceiver); super.onDestroy(); } diff --git a/src/com/android/camera/ui/FilmStripView.java b/src/com/android/camera/ui/FilmStripView.java index c7920c35d..4d37f04c4 100644 --- a/src/com/android/camera/ui/FilmStripView.java +++ b/src/com/android/camera/ui/FilmStripView.java @@ -24,6 +24,7 @@ import android.graphics.Canvas; import android.graphics.Rect; import android.graphics.RectF; import android.util.AttributeSet; +import android.util.Log; import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; @@ -35,16 +36,15 @@ import com.android.camera.CameraActivity; import com.android.camera.data.LocalData; import com.android.camera.ui.FilmStripView.ImageData.PanoramaSupportCallback; import com.android.camera.ui.FilmstripBottomControls.BottomControlsListener; -import com.android.camera.util.CameraUtil; import com.android.camera.util.PhotoSphereHelper.PanoramaViewHelper; import com.android.camera2.R; public class FilmStripView extends ViewGroup implements BottomControlsListener { - @SuppressWarnings("unused") private static final String TAG = "CAM_FilmStripView"; private static final int BUFFER_SIZE = 5; private static final int DURATION_GEOMETRY_ADJUST = 200; + private static final int SNAP_IN_CENTER_TIME_MS = 600; private static final float FILM_STRIP_SCALE = 0.6f; private static final float FULL_SCREEN_SCALE = 1f; // Only check for intercepting touch events within first 500ms @@ -56,11 +56,11 @@ public class FilmStripView extends ViewGroup implements BottomControlsListener { private int mViewGap; private final Rect mDrawArea = new Rect(); - private final int mCurrentInfo = (BUFFER_SIZE - 1) / 2; + private final int mCurrentItem = (BUFFER_SIZE - 1) / 2; private float mScale; private MyController mController; private int mCenterX = -1; - private ViewInfo[] mViewInfo = new ViewInfo[BUFFER_SIZE]; + private ViewItem[] mViewItem = new ViewItem[BUFFER_SIZE]; private Listener mListener; @@ -347,10 +347,6 @@ public class FilmStripView extends ViewGroup implements BottomControlsListener { public boolean isScrolling(); - public void lockAtCurrentView(); - - public void unlockPosition(); - public void gotoCameraFullScreen(); public void gotoFilmStrip(); @@ -361,7 +357,7 @@ public class FilmStripView extends ViewGroup implements BottomControlsListener { /** * A helper class to tract and calculate the view coordination. */ - private static class ViewInfo { + private static class ViewItem { private int mDataID; /** The position of the left of the view in the whole filmstrip. */ private int mLeftPosition; @@ -374,7 +370,7 @@ public class FilmStripView extends ViewGroup implements BottomControlsListener { * @param id The id of the data from {@link DataAdapter}. * @param v The {@code View} representing the data. */ - public ViewInfo(int id, View v) { + public ViewItem(int id, View v) { v.setPivotX(0f); v.setPivotY(0f); mDataID = id; @@ -410,7 +406,7 @@ public class FilmStripView extends ViewGroup implements BottomControlsListener { /** Returns the translation of X regarding the view scale. */ public float getTranslationX(float scale) { - return mView.getTranslationX(); + return mView.getTranslationX() / scale; } /** Sets the translation of Y regarding the view scale. */ @@ -470,6 +466,13 @@ public class FilmStripView extends ViewGroup implements BottomControlsListener { public boolean areaContains(float x, float y) { return mViewArea.contains(x, y); } + + public void copyGeometry(ViewItem item) { + setLeftPosition(item.getLeftPosition()); + View v = item.getView(); + mView.setTranslationY(v.getTranslationY()); + mView.setTranslationX(v.getTranslationX()); + } } public FilmStripView(Context context) { @@ -529,16 +532,12 @@ public class FilmStripView extends ViewGroup implements BottomControlsListener { mPanoramaViewHelper = helper; } - public float getScale() { - return mScale; - } - public boolean isAnchoredTo(int id) { - if (mViewInfo[mCurrentInfo] == null) { + if (mViewItem[mCurrentItem] == null) { return false; } - if (mViewInfo[mCurrentInfo].getID() == id - && mViewInfo[mCurrentInfo].getCenterX() == mCenterX) { + if (mViewItem[mCurrentItem].getID() == id + && mViewItem[mCurrentItem].getCenterX() == mCenterX) { return true; } return false; @@ -548,7 +547,7 @@ public class FilmStripView extends ViewGroup implements BottomControlsListener { if (mDataAdapter == null) { return ImageData.TYPE_NONE; } - ViewInfo curr = mViewInfo[mCurrentInfo]; + ViewItem curr = mViewItem[mCurrentItem]; if (curr == null) { return ImageData.TYPE_NONE; } @@ -557,7 +556,7 @@ public class FilmStripView extends ViewGroup implements BottomControlsListener { @Override public void onDraw(Canvas c) { - if (mViewInfo[mCurrentInfo] != null && mController.hasNewGeometry()) { + if (mViewItem[mCurrentItem] != null && mController.hasNewGeometry()) { layoutChildren(); super.onDraw(c); } @@ -602,18 +601,18 @@ public class FilmStripView extends ViewGroup implements BottomControlsListener { mDataAdapter.suggestViewSizeBound(boundWidth / 2, boundHeight / 2); } - for (ViewInfo info : mViewInfo) { - if (info == null) { + for (ViewItem item : mViewItem) { + if (item == null) { continue; } - int id = info.getID(); + int id = item.getID(); int[] dim = calculateChildDimension( mDataAdapter.getImageData(id).getWidth(), mDataAdapter.getImageData(id).getHeight(), boundWidth, boundHeight); - info.getView().measure( + item.getView().measure( MeasureSpec.makeMeasureSpec( dim[0], MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec( @@ -638,33 +637,33 @@ public class FilmStripView extends ViewGroup implements BottomControlsListener { private int findTheNearestView(int pointX) { int nearest = 0; - // Find the first non-null ViewInfo. + // Find the first non-null ViewItem. while (nearest < BUFFER_SIZE - && (mViewInfo[nearest] == null || mViewInfo[nearest].getLeftPosition() == -1)) { + && (mViewItem[nearest] == null || mViewItem[nearest].getLeftPosition() == -1)) { nearest++; } - // No existing available ViewInfo + // No existing available ViewItem if (nearest == BUFFER_SIZE) { return -1; } - int min = Math.abs(pointX - mViewInfo[nearest].getCenterX()); + int min = Math.abs(pointX - mViewItem[nearest].getCenterX()); - for (int infoID = nearest + 1; infoID < BUFFER_SIZE && mViewInfo[infoID] != null; infoID++) { + for (int itemID = nearest + 1; itemID < BUFFER_SIZE && mViewItem[itemID] != null; itemID++) { // Not measured yet. - if (mViewInfo[infoID].getLeftPosition() == -1) + if (mViewItem[itemID].getLeftPosition() == -1) continue; - int c = mViewInfo[infoID].getCenterX(); + int c = mViewItem[itemID].getCenterX(); int dist = Math.abs(pointX - c); if (dist < min) { min = dist; - nearest = infoID; + nearest = itemID; } } return nearest; } - private ViewInfo buildInfoFromData(int dataID) { + private ViewItem buildItemFromData(int dataID) { ImageData data = mDataAdapter.getImageData(dataID); if (data == null) { return null; @@ -674,29 +673,29 @@ public class FilmStripView extends ViewGroup implements BottomControlsListener { if (v == null) { return null; } - ViewInfo info = new ViewInfo(dataID, v); - v = info.getView(); + ViewItem item = new ViewItem(dataID, v); + v = item.getView(); if (v != mCameraView) { - addView(info.getView()); + addView(item.getView()); } else { v.setVisibility(View.VISIBLE); } - return info; + return item; } - private void removeInfo(int infoID) { - if (infoID >= mViewInfo.length || mViewInfo[infoID] == null) { + private void removeItem(int itemID) { + if (itemID >= mViewItem.length || mViewItem[itemID] == null) { return; } - ImageData data = mDataAdapter.getImageData(mViewInfo[infoID].getID()); - checkForRemoval(data, mViewInfo[infoID].getView()); - mViewInfo[infoID] = null; + ImageData data = mDataAdapter.getImageData(mViewItem[itemID].getID()); + checkForRemoval(data, mViewItem[itemID].getView()); + mViewItem[itemID] = null; } /** * We try to keep the one closest to the center of the screen at position - * mCurrentInfo. + * mCurrentItem. */ private void stepIfNeeded() { if (!inFilmStrip() && !inFullScreen()) { @@ -706,49 +705,49 @@ public class FilmStripView extends ViewGroup implements BottomControlsListener { } int nearest = findTheNearestView(mCenterX); // no change made. - if (nearest == -1 || nearest == mCurrentInfo) + if (nearest == -1 || nearest == mCurrentItem) return; - // Going to change the current info, notify the listener. + // Going to change the current item, notify the listener. if (mListener != null) { - mListener.onCurrentDataChanged(mViewInfo[mCurrentInfo].getID(), false); + mListener.onCurrentDataChanged(mViewItem[mCurrentItem].getID(), false); } - int adjust = nearest - mCurrentInfo; + int adjust = nearest - mCurrentItem; if (adjust > 0) { for (int k = 0; k < adjust; k++) { - removeInfo(k); + removeItem(k); } for (int k = 0; k + adjust < BUFFER_SIZE; k++) { - mViewInfo[k] = mViewInfo[k + adjust]; + mViewItem[k] = mViewItem[k + adjust]; } for (int k = BUFFER_SIZE - adjust; k < BUFFER_SIZE; k++) { - mViewInfo[k] = null; - if (mViewInfo[k - 1] != null) { - mViewInfo[k] = buildInfoFromData(mViewInfo[k - 1].getID() + 1); + mViewItem[k] = null; + if (mViewItem[k - 1] != null) { + mViewItem[k] = buildItemFromData(mViewItem[k - 1].getID() + 1); } } } else { for (int k = BUFFER_SIZE - 1; k >= BUFFER_SIZE + adjust; k--) { - removeInfo(k); + removeItem(k); } for (int k = BUFFER_SIZE - 1; k + adjust >= 0; k--) { - mViewInfo[k] = mViewInfo[k + adjust]; + mViewItem[k] = mViewItem[k + adjust]; } for (int k = -1 - adjust; k >= 0; k--) { - mViewInfo[k] = null; - if (mViewInfo[k + 1] != null) { - mViewInfo[k] = buildInfoFromData(mViewInfo[k + 1].getID() - 1); + mViewItem[k] = null; + if (mViewItem[k + 1] != null) { + mViewItem[k] = buildItemFromData(mViewItem[k + 1].getID() - 1); } } } if (mListener != null) { - mListener.onCurrentDataChanged(mViewInfo[mCurrentInfo].getID(), true); + mListener.onCurrentDataChanged(mViewItem[mCurrentItem].getID(), true); } } /** Don't go beyond the bound. */ private void clampCenterX() { - ViewInfo curr = mViewInfo[mCurrentInfo]; + ViewItem curr = mViewItem[mCurrentItem]; if (curr == null) { return; } @@ -770,9 +769,9 @@ public class FilmStripView extends ViewGroup implements BottomControlsListener { private void adjustChildZOrder() { for (int i = BUFFER_SIZE - 1; i >= 0; i--) { - if (mViewInfo[i] == null) + if (mViewItem[i] == null) continue; - bringChildToFront(mViewInfo[i].getView()); + bringChildToFront(mViewItem[i].getView()); } } @@ -782,7 +781,7 @@ public class FilmStripView extends ViewGroup implements BottomControlsListener { */ @Override public void onViewPhotoSphere() { - ViewInfo curr = mViewInfo[mCurrentInfo]; + ViewItem curr = mViewItem[mCurrentItem]; if (curr != null) { mDataAdapter.getImageData(curr.getID()).viewPhotoSphere(mPanoramaViewHelper); } @@ -806,7 +805,7 @@ public class FilmStripView extends ViewGroup implements BottomControlsListener { * @return The ID of the current item, or -1. */ public int getCurrentId() { - ViewInfo current = mViewInfo[mCurrentInfo]; + ViewItem current = mViewItem[mCurrentItem]; if (current == null) { return -1; } @@ -854,14 +853,16 @@ public class FilmStripView extends ViewGroup implements BottomControlsListener { } private void snapInCenter() { - ViewInfo currentInfo = mViewInfo[mCurrentInfo]; - if (currentInfo == null || mController.isScrolling() || mIsUserScrolling) { + ViewItem currentItem = mViewItem[mCurrentItem]; + if (currentItem == null || mController.isScrolling() || mIsUserScrolling) { return; } - int currentViewCenter = currentInfo.getCenterX(); + int currentViewCenter = currentItem.getCenterX(); if (mCenterX != currentViewCenter) { + int snapInTime = (int) (SNAP_IN_CENTER_TIME_MS + * Math.abs(mCenterX - currentViewCenter) / mDrawArea.width()); mController.scrollTo(currentViewCenter, - DURATION_GEOMETRY_ADJUST, false); + snapInTime, false); } if (getCurrentViewType() == ImageData.TYPE_STICKY_VIEW && !mController.isScalling() @@ -871,11 +872,11 @@ public class FilmStripView extends ViewGroup implements BottomControlsListener { } private void layoutChildren() { - if (mViewInfo[mCurrentInfo] == null) { + if (mViewItem[mCurrentItem] == null) { return; } if (mAnchorPending) { - mCenterX = mViewInfo[mCurrentInfo].getCenterX(); + mCenterX = mViewItem[mCurrentItem].getCenterX(); mAnchorPending = false; } @@ -886,11 +887,6 @@ public class FilmStripView extends ViewGroup implements BottomControlsListener { clampCenterX(); - mViewInfo[mCurrentInfo].layoutIn(mDrawArea, mCenterX, mScale); - - int currentViewLeft = mViewInfo[mCurrentInfo].getLeftPosition(); - int currentViewCenter = mViewInfo[mCurrentInfo].getCenterX(); - int fullScreenWidth = mDrawArea.width() + mViewGap; /** * Transformed scale fraction between 0 and 1. 0 if the scale is * {@link FILM_STRIP_SCALE}. 1 if the scale is {@link FULL_SCREEN_SCALE} @@ -899,46 +895,93 @@ public class FilmStripView extends ViewGroup implements BottomControlsListener { float scaleFraction = mViewAnimInterpolator.getInterpolation( (mScale - FILM_STRIP_SCALE) / (FULL_SCREEN_SCALE - FILM_STRIP_SCALE)); + // Layout the current ViewItem first. + if (scaleFraction == 1 + && mViewItem[mCurrentItem - 1] != null + && mCenterX < mViewItem[mCurrentItem].getCenterX()) { + // In full-screen and it's not the first one and mCenterX is on + // the left of the center, we draw the current one to "fade down". + ViewItem curr = mViewItem[mCurrentItem]; + ViewItem prev = mViewItem[mCurrentItem - 1]; + int currCenterX = curr.getCenterX(); + int prevCenterX = prev.getCenterX(); + float fadeUpFraction = + ((float) mCenterX - prevCenterX) + / (currCenterX - prevCenterX); + curr.layoutIn(mDrawArea, currCenterX, + FILM_STRIP_SCALE + + (1f - FILM_STRIP_SCALE) * fadeUpFraction); + curr.getView().setAlpha(fadeUpFraction); + } else { + mViewItem[mCurrentItem].layoutIn(mDrawArea, mCenterX, mScale); + } + + // Layout the rest dependent on the current scale. + int currentViewLeft = mViewItem[mCurrentItem].getLeftPosition(); + int currentViewCenter = mViewItem[mCurrentItem].getCenterX(); + int fullScreenWidth = mDrawArea.width() + mViewGap; + // images on the left - for (int infoID = mCurrentInfo - 1; infoID >= 0; infoID--) { - ViewInfo curr = mViewInfo[infoID]; + for (int itemID = mCurrentItem - 1; itemID >= 0; itemID--) { + ViewItem curr = mViewItem[itemID]; if (curr == null) { continue; } - ViewInfo next = mViewInfo[infoID + 1]; + ViewItem next = mViewItem[itemID + 1]; int myLeft = - next.getLeftPosition() - curr.getView().getMeasuredWidth() - mViewGap; + next.getLeftPosition() - curr.getView().getMeasuredWidth() + - mViewGap; curr.setLeftPosition(myLeft); curr.layoutIn(mDrawArea, mCenterX, mScale); curr.getView().setAlpha(1f); - int infoDiff = mCurrentInfo - infoID; + int itemDiff = mCurrentItem - itemID; curr.setTranslationX( (currentViewCenter - - fullScreenWidth * infoDiff - curr.getCenterX()) * scaleFraction, + - fullScreenWidth * itemDiff - curr.getCenterX()) * scaleFraction, mScale); } // images on the right - for (int infoID = mCurrentInfo + 1; infoID < BUFFER_SIZE; infoID++) { - ViewInfo curr = mViewInfo[infoID]; + for (int itemID = mCurrentItem + 1; itemID < BUFFER_SIZE; itemID++) { + ViewItem curr = mViewItem[itemID]; if (curr == null) { continue; } - ViewInfo prev = mViewInfo[infoID - 1]; + ViewItem prev = mViewItem[itemID - 1]; int myLeft = - prev.getLeftPosition() + prev.getView().getMeasuredWidth() + mViewGap; + prev.getLeftPosition() + prev.getView().getMeasuredWidth() + + mViewGap; curr.setLeftPosition(myLeft); curr.layoutIn(mDrawArea, mCenterX, mScale); View currView = curr.getView(); if (scaleFraction == 1) { - currView.setVisibility(INVISIBLE); + // It's in full-screen mode. + if (itemID == mCurrentItem + 1) { + int currCenterX = curr.getCenterX(); + int prevCenterX = prev.getCenterX(); + if (mCenterX == prevCenterX) { + currView.setVisibility(INVISIBLE); + } else { + float fadeUpFraction = + ((float) mCenterX - prevCenterX) + / (currCenterX - prevCenterX); + curr.layoutIn(mDrawArea, currCenterX, + FILM_STRIP_SCALE + + (1f - FILM_STRIP_SCALE) * fadeUpFraction); + currView.setAlpha(fadeUpFraction); + currView.setVisibility(VISIBLE); + } + } else { + currView.setVisibility(INVISIBLE); + } + curr.setTranslationX(0, mScale); } else { if (currView.getVisibility() == INVISIBLE) { currView.setVisibility(VISIBLE); } - if (infoID == mCurrentInfo + 1) { + if (itemID == mCurrentItem + 1) { currView.setAlpha(1f - scaleFraction); } else { if (scaleFraction == 0f) { @@ -947,24 +990,21 @@ public class FilmStripView extends ViewGroup implements BottomControlsListener { currView.setVisibility(INVISIBLE); } } + curr.setTranslationX((currentViewLeft - myLeft) * scaleFraction, mScale); } - curr.setTranslationX((currentViewLeft - myLeft) * scaleFraction, mScale); } stepIfNeeded(); adjustChildZOrder(); snapInCenter(); - invalidate(); updateBottomControls(); mLastItemId = getCurrentId(); + + invalidate(); } @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { - if (mViewInfo[mCurrentInfo] == null) { - return; - } - mDrawArea.left = l; mDrawArea.top = t; mDrawArea.right = r; @@ -997,61 +1037,70 @@ public class FilmStripView extends ViewGroup implements BottomControlsListener { } private void updateRemoval(int dataID, final ImageData data) { - int removedInfo = findInfoByDataID(dataID); + int removedItem = findItemByDataID(dataID); // adjust the data id to be consistent for (int i = 0; i < BUFFER_SIZE; i++) { - if (mViewInfo[i] == null || mViewInfo[i].getID() <= dataID) { + if (mViewItem[i] == null || mViewItem[i].getID() <= dataID) { continue; } - mViewInfo[i].setID(mViewInfo[i].getID() - 1); + mViewItem[i].setID(mViewItem[i].getID() - 1); } - if (removedInfo == -1) { + if (removedItem == -1) { return; } - final View removedView = mViewInfo[removedInfo].getView(); + final View removedView = mViewItem[removedItem].getView(); final int offsetX = removedView.getMeasuredWidth() + mViewGap; - for (int i = removedInfo + 1; i < BUFFER_SIZE; i++) { - if (mViewInfo[i] != null) { - mViewInfo[i].setLeftPosition(mViewInfo[i].getLeftPosition() - offsetX); + for (int i = removedItem + 1; i < BUFFER_SIZE; i++) { + if (mViewItem[i] != null) { + mViewItem[i].setLeftPosition(mViewItem[i].getLeftPosition() - offsetX); } } - if (removedInfo >= mCurrentInfo - && mViewInfo[removedInfo].getID() < mDataAdapter.getTotalNumber()) { - // Fill the removed info by left shift when the current one or + if (removedItem >= mCurrentItem + && mViewItem[removedItem].getID() < mDataAdapter.getTotalNumber()) { + // Fill the removed item by left shift when the current one or // anyone on the right is removed, and there's more data on the // right available. - for (int i = removedInfo; i < BUFFER_SIZE - 1; i++) { - mViewInfo[i] = mViewInfo[i + 1]; + for (int i = removedItem; i < BUFFER_SIZE - 1; i++) { + mViewItem[i] = mViewItem[i + 1]; } // pull data out from the DataAdapter for the last one. int curr = BUFFER_SIZE - 1; int prev = curr - 1; - if (mViewInfo[prev] != null) { - mViewInfo[curr] = buildInfoFromData(mViewInfo[prev].getID() + 1); + if (mViewItem[prev] != null) { + mViewItem[curr] = buildItemFromData(mViewItem[prev].getID() + 1); + } + + // The animation part. + if (inFullScreen()) { + mViewItem[mCurrentItem].getView().setVisibility(VISIBLE); + ViewItem nextItem = mViewItem[mCurrentItem + 1]; + if (nextItem != null) { + nextItem.getView().setVisibility(INVISIBLE); + } } // Translate the views to their original places. - for (int i = removedInfo; i < BUFFER_SIZE; i++) { - if (mViewInfo[i] != null) { - mViewInfo[i].setTranslationX(offsetX, mScale); + for (int i = removedItem; i < BUFFER_SIZE; i++) { + if (mViewItem[i] != null) { + mViewItem[i].setTranslationX(offsetX, mScale); } } // The end of the filmstrip might have been changed. // The mCenterX might be out of the bound. - ViewInfo currInfo = mViewInfo[mCurrentInfo]; - if (currInfo.getID() == mDataAdapter.getTotalNumber() - 1 - && mCenterX > currInfo.getCenterX()) { - int adjustDiff = currInfo.getCenterX() - mCenterX; - mCenterX = currInfo.getCenterX(); + ViewItem currItem = mViewItem[mCurrentItem]; + if (currItem.getID() == mDataAdapter.getTotalNumber() - 1 + && mCenterX > currItem.getCenterX()) { + int adjustDiff = currItem.getCenterX() - mCenterX; + mCenterX = currItem.getCenterX(); for (int i = 0; i < BUFFER_SIZE; i++) { - if (mViewInfo[i] != null) { - mViewInfo[i].translateXBy(adjustDiff, mScale); + if (mViewItem[i] != null) { + mViewItem[i].translateXBy(adjustDiff, mScale); } } } @@ -1059,30 +1108,30 @@ public class FilmStripView extends ViewGroup implements BottomControlsListener { // fill the removed place by right shift mCenterX -= offsetX; - for (int i = removedInfo; i > 0; i--) { - mViewInfo[i] = mViewInfo[i - 1]; + for (int i = removedItem; i > 0; i--) { + mViewItem[i] = mViewItem[i - 1]; } // pull data out from the DataAdapter for the first one. int curr = 0; int next = curr + 1; - if (mViewInfo[next] != null) { - mViewInfo[curr] = buildInfoFromData(mViewInfo[next].getID() - 1); + if (mViewItem[next] != null) { + mViewItem[curr] = buildItemFromData(mViewItem[next].getID() - 1); } // Translate the views to their original places. - for (int i = removedInfo; i >= 0; i--) { - if (mViewInfo[i] != null) { - mViewInfo[i].setTranslationX(-offsetX, mScale); + for (int i = removedItem; i >= 0; i--) { + if (mViewItem[i] != null) { + mViewItem[i].setTranslationX(-offsetX, mScale); } } } // Now, slide every one back. for (int i = 0; i < BUFFER_SIZE; i++) { - if (mViewInfo[i] != null - && mViewInfo[i].getTranslationX(mScale) != 0f) { - slideViewBack(mViewInfo[i].getView()); + if (mViewItem[i] != null + && mViewItem[i].getTranslationX(mScale) != 0f) { + slideViewBack(mViewItem[i].getView()); } } @@ -1106,10 +1155,10 @@ public class FilmStripView extends ViewGroup implements BottomControlsListener { } // returns -1 on failure. - private int findInfoByDataID(int dataID) { + private int findItemByDataID(int dataID) { for (int i = 0; i < BUFFER_SIZE; i++) { - if (mViewInfo[i] != null - && mViewInfo[i].getID() == dataID) { + if (mViewItem[i] != null + && mViewItem[i].getID() == dataID) { return i; } } @@ -1117,28 +1166,28 @@ public class FilmStripView extends ViewGroup implements BottomControlsListener { } private void updateInsertion(int dataID) { - int insertedInfo = findInfoByDataID(dataID); - if (insertedInfo == -1) { - // Not in the current info buffers. Check if it's inserted + int insertedItem = findItemByDataID(dataID); + if (insertedItem == -1) { + // Not in the current item buffers. Check if it's inserted // at the end. if (dataID == mDataAdapter.getTotalNumber() - 1) { - int prev = findInfoByDataID(dataID - 1); + int prev = findItemByDataID(dataID - 1); if (prev >= 0 && prev < BUFFER_SIZE - 1) { // The previous data is in the buffer and we still // have room for the inserted data. - insertedInfo = prev + 1; + insertedItem = prev + 1; } } } // adjust the data id to be consistent for (int i = 0; i < BUFFER_SIZE; i++) { - if (mViewInfo[i] == null || mViewInfo[i].getID() < dataID) { + if (mViewItem[i] == null || mViewItem[i].getID() < dataID) { continue; } - mViewInfo[i].setID(mViewInfo[i].getID() + 1); + mViewItem[i].setID(mViewItem[i].getID() + 1); } - if (insertedInfo == -1) { + if (insertedItem == -1) { return; } @@ -1147,40 +1196,40 @@ public class FilmStripView extends ViewGroup implements BottomControlsListener { data.getWidth(), data.getHeight(), getMeasuredWidth(), getMeasuredHeight()); final int offsetX = dim[0] + mViewGap; - ViewInfo viewInfo = buildInfoFromData(dataID); + ViewItem viewItem = buildItemFromData(dataID); - if (insertedInfo >= mCurrentInfo) { - if (insertedInfo == mCurrentInfo) { - viewInfo.setLeftPosition(mViewInfo[mCurrentInfo].getLeftPosition()); + if (insertedItem >= mCurrentItem) { + if (insertedItem == mCurrentItem) { + viewItem.setLeftPosition(mViewItem[mCurrentItem].getLeftPosition()); } // Shift right to make rooms for newly inserted item. - removeInfo(BUFFER_SIZE - 1); - for (int i = BUFFER_SIZE - 1; i > insertedInfo; i--) { - mViewInfo[i] = mViewInfo[i - 1]; - if (mViewInfo[i] != null) { - mViewInfo[i].setTranslationX(-offsetX, mScale); - slideViewBack(mViewInfo[i].getView()); + removeItem(BUFFER_SIZE - 1); + for (int i = BUFFER_SIZE - 1; i > insertedItem; i--) { + mViewItem[i] = mViewItem[i - 1]; + if (mViewItem[i] != null) { + mViewItem[i].setTranslationX(-offsetX, mScale); + slideViewBack(mViewItem[i].getView()); } } } else { // Shift left. Put the inserted data on the left instead of the // found position. - --insertedInfo; - if (insertedInfo < 0) { + --insertedItem; + if (insertedItem < 0) { return; } - removeInfo(0); - for (int i = 1; i <= insertedInfo; i++) { - if (mViewInfo[i] != null) { - mViewInfo[i].setTranslationX(offsetX, mScale); - slideViewBack(mViewInfo[i].getView()); - mViewInfo[i - 1] = mViewInfo[i]; + removeItem(0); + for (int i = 1; i <= insertedItem; i++) { + if (mViewItem[i] != null) { + mViewItem[i].setTranslationX(offsetX, mScale); + slideViewBack(mViewItem[i].getView()); + mViewItem[i - 1] = mViewItem[i]; } } } - mViewInfo[insertedInfo] = viewInfo; - View insertedView = mViewInfo[insertedInfo].getView(); + mViewItem[insertedItem] = viewItem; + View insertedView = mViewItem[insertedItem].getView(); insertedView.setAlpha(0f); insertedView.setTranslationY(getHeight() / 8); insertedView.animate() @@ -1208,7 +1257,7 @@ public class FilmStripView extends ViewGroup implements BottomControlsListener { @Override public void onDataInserted(int dataID, ImageData data) { - if (mViewInfo[mCurrentInfo] == null) { + if (mViewItem[mCurrentItem] == null) { // empty now, simply do a reload. reload(); return; @@ -1245,9 +1294,9 @@ public class FilmStripView extends ViewGroup implements BottomControlsListener { if (ev.getActionMasked() == MotionEvent.ACTION_DOWN) { mCheckToIntercept = true; mDown = MotionEvent.obtain(ev); - ViewInfo viewInfo = mViewInfo[mCurrentInfo]; + ViewItem viewItem = mViewItem[mCurrentItem]; // Do not intercept touch if swipe is not enabled - if (viewInfo != null && !mDataAdapter.canSwipeInFullScreen(viewInfo.getID())) { + if (viewItem != null && !mDataAdapter.canSwipeInFullScreen(viewItem.getID())) { mCheckToIntercept = false; } return false; @@ -1281,22 +1330,38 @@ public class FilmStripView extends ViewGroup implements BottomControlsListener { return true; } - private void updateViewInfo(int infoID) { - ViewInfo info = mViewInfo[infoID]; - removeView(info.getView()); - mViewInfo[infoID] = buildInfoFromData(info.getID()); + private void updateViewItem(int itemID) { + ViewItem item = mViewItem[itemID]; + if (item == null) { + Log.e(TAG, "trying to update an null item"); + return; + } + removeView(item.getView()); + ImageData data = mDataAdapter.getImageData(item.getID()); + data.recycle(); + + ViewItem newItem = buildItemFromData(item.getID()); + if (newItem == null) { + Log.e(TAG, "new item is null"); + // keep using the old data. + data.prepare(); + addView(item.getView()); + return; + } + newItem.copyGeometry(item); + mViewItem[itemID] = newItem; } /** Some of the data is changed. */ private void update(DataAdapter.UpdateReporter reporter) { // No data yet. - if (mViewInfo[mCurrentInfo] == null) { + if (mViewItem[mCurrentItem] == null) { reload(); return; } // Check the current one. - ViewInfo curr = mViewInfo[mCurrentInfo]; + ViewItem curr = mViewItem[mCurrentItem]; int dataID = curr.getID(); if (reporter.isDataRemoved(dataID)) { mCenterX = -1; @@ -1304,40 +1369,42 @@ public class FilmStripView extends ViewGroup implements BottomControlsListener { return; } if (reporter.isDataUpdated(dataID)) { - updateViewInfo(mCurrentInfo); + updateViewItem(mCurrentItem); } // Check left - for (int i = mCurrentInfo - 1; i >= 0; i--) { - curr = mViewInfo[i]; + for (int i = mCurrentItem - 1; i >= 0; i--) { + curr = mViewItem[i]; if (curr != null) { dataID = curr.getID(); if (reporter.isDataRemoved(dataID) || reporter.isDataUpdated(dataID)) { - updateViewInfo(i); + updateViewItem(i); } } else { - ViewInfo next = mViewInfo[i + 1]; + ViewItem next = mViewItem[i + 1]; if (next != null) { - mViewInfo[i] = buildInfoFromData(next.getID() - 1); + mViewItem[i] = buildItemFromData(next.getID() - 1); } } } // Check right - for (int i = mCurrentInfo + 1; i < BUFFER_SIZE; i++) { - curr = mViewInfo[i]; + for (int i = mCurrentItem + 1; i < BUFFER_SIZE; i++) { + curr = mViewItem[i]; if (curr != null) { dataID = curr.getID(); if (reporter.isDataRemoved(dataID) || reporter.isDataUpdated(dataID)) { - updateViewInfo(i); + updateViewItem(i); } } else { - ViewInfo prev = mViewInfo[i - 1]; + ViewItem prev = mViewItem[i - 1]; if (prev != null) { - mViewInfo[i] = buildInfoFromData(prev.getID() + 1); + mViewItem[i] = buildItemFromData(prev.getID() + 1); } } } + // request a layout to find the measured width/height of the view first. + requestLayout(); } /** @@ -1351,35 +1418,31 @@ public class FilmStripView extends ViewGroup implements BottomControlsListener { return; } - mViewInfo[mCurrentInfo] = buildInfoFromData(0); - mViewInfo[mCurrentInfo].setLeftPosition(0); - if (mViewInfo[mCurrentInfo] == null) { + mViewItem[mCurrentItem] = buildItemFromData(0); + mViewItem[mCurrentItem].setLeftPosition(0); + if (mViewItem[mCurrentItem] == null) { return; } - if (getCurrentViewType() == ImageData.TYPE_STICKY_VIEW) { - // we are in camera mode by default. - mController.lockAtCurrentView(); - } - for (int i = 1; mCurrentInfo + i < BUFFER_SIZE || mCurrentInfo - i >= 0; i++) { - int infoID = mCurrentInfo + i; - if (infoID < BUFFER_SIZE && mViewInfo[infoID - 1] != null) { - mViewInfo[infoID] = buildInfoFromData(mViewInfo[infoID - 1].getID() + 1); + for (int i = 1; mCurrentItem + i < BUFFER_SIZE || mCurrentItem - i >= 0; i++) { + int itemID = mCurrentItem + i; + if (itemID < BUFFER_SIZE && mViewItem[itemID - 1] != null) { + mViewItem[itemID] = buildItemFromData(mViewItem[itemID - 1].getID() + 1); } - infoID = mCurrentInfo - i; - if (infoID >= 0 && mViewInfo[infoID + 1] != null) { - mViewInfo[infoID] = buildInfoFromData(mViewInfo[infoID + 1].getID() - 1); + itemID = mCurrentItem - i; + if (itemID >= 0 && mViewItem[itemID + 1] != null) { + mViewItem[itemID] = buildItemFromData(mViewItem[itemID + 1].getID() - 1); } } layoutChildren(); } - private void promoteData(int infoID, int dataID) { + private void promoteData(int itemID, int dataID) { if (mListener != null) { mListener.onDataPromoted(dataID); } } - private void demoteData(int infoID, int dataID) { + private void demoteData(int itemID, int dataID) { if (mListener != null) { mListener.onDataDemoted(dataID); } @@ -1404,9 +1467,6 @@ public class FilmStripView extends ViewGroup implements BottomControlsListener { private boolean mCanStopScroll; - private boolean mIsPositionLocked; - private int mLockedViewInfo; - MyController(Context context) { mScroller = new Scroller(context); mHasNewPosition = false; @@ -1435,7 +1495,7 @@ public class FilmStripView extends ViewGroup implements BottomControlsListener { } // If the position is locked, then we always return true to force // the position value to use the locked value. - return (mHasNewPosition || mHasNewScale || mIsPositionLocked); + return (mHasNewPosition || mHasNewScale); } /** @@ -1455,32 +1515,10 @@ public class FilmStripView extends ViewGroup implements BottomControlsListener { * value. */ int getNewPosition() { - if (mIsPositionLocked) { - if (mViewInfo[mLockedViewInfo] == null) - return mCenterX; - return mViewInfo[mLockedViewInfo].getCenterX(); - } - if (!mHasNewPosition) + if (!mHasNewPosition) { return mCenterX; - return mScroller.getCurrX(); - } - - @Override - public void lockAtCurrentView() { - mIsPositionLocked = true; - mLockedViewInfo = mCurrentInfo; - } - - @Override - public void unlockPosition() { - if (mIsPositionLocked) { - // only when the position is previously locked we set the - // current position to make it consistent. - if (mViewInfo[mLockedViewInfo] != null) { - mCenterX = mViewInfo[mLockedViewInfo].getCenterX(); - } - mIsPositionLocked = false; } + return mScroller.getCurrX(); } private int estimateMinX(int dataID, int leftPos, int viewWidth) { @@ -1503,11 +1541,11 @@ public class FilmStripView extends ViewGroup implements BottomControlsListener { @Override public void fling(float velocityX) { - if (!stopScrolling() || mIsPositionLocked) { + if (!stopScrolling()) { return; } - ViewInfo info = mViewInfo[mCurrentInfo]; - if (info == null) { + ViewItem item = mViewItem[mCurrentItem]; + if (item == null) { return; } @@ -1522,10 +1560,10 @@ public class FilmStripView extends ViewGroup implements BottomControlsListener { // Estimation of possible length on the left. To ensure the // velocity doesn't become too slow eventually, we add a huge number // to the estimated maximum. - int minX = estimateMinX(info.getID(), info.getLeftPosition(), w); + int minX = estimateMinX(item.getID(), item.getLeftPosition(), w); // Estimation of possible length on the right. Likewise, exaggerate // the possible maximum too. - int maxX = estimateMaxX(info.getID(), info.getLeftPosition(), w); + int maxX = estimateMaxX(item.getID(), item.getLeftPosition(), w); mScroller.fling(mCenterX, 0, (int) -velocityX, 0, minX, maxX, 0, 0); layoutChildren(); @@ -1548,7 +1586,7 @@ public class FilmStripView extends ViewGroup implements BottomControlsListener { @Override public void scrollTo(int position, int duration, boolean interruptible) { - if (!stopScrolling() || mIsPositionLocked) { + if (!stopScrolling()) { return; } mCanStopScroll = interruptible; @@ -1559,7 +1597,7 @@ public class FilmStripView extends ViewGroup implements BottomControlsListener { } private void scaleTo(float scale, int duration) { - if (mViewInfo[mCurrentInfo] == null) { + if (mViewItem[mCurrentItem] == null) { return; } stopScale(); @@ -1573,7 +1611,6 @@ public class FilmStripView extends ViewGroup implements BottomControlsListener { @Override public void gotoFilmStrip() { - unlockPosition(); scaleTo(FILM_STRIP_SCALE, DURATION_GEOMETRY_ADJUST); if (mListener != null) { mListener.onSwitchMode(false); @@ -1583,8 +1620,8 @@ public class FilmStripView extends ViewGroup implements BottomControlsListener { @Override public void gotoFullScreen() { - if (mViewInfo[mCurrentInfo] != null) { - mController.scrollTo(mViewInfo[mCurrentInfo].getCenterX(), + if (mViewItem[mCurrentItem] != null) { + mController.scrollTo(mViewItem[mCurrentItem].getCenterX(), DURATION_GEOMETRY_ADJUST, false); } enterFullScreen(); @@ -1613,15 +1650,15 @@ public class FilmStripView extends ViewGroup implements BottomControlsListener { } gotoFullScreen(); scrollTo( - estimateMinX(mViewInfo[mCurrentInfo].getID(), - mViewInfo[mCurrentInfo].getLeftPosition(), + estimateMinX(mViewItem[mCurrentItem].getID(), + mViewItem[mCurrentItem].getLeftPosition(), getWidth()), DURATION_GEOMETRY_ADJUST, false); } @Override public void onAnimationUpdate(ValueAnimator animation) { - if (mViewInfo[mCurrentInfo] == null) { + if (mViewItem[mCurrentItem] == null) { return; } mHasNewScale = true; @@ -1635,15 +1672,12 @@ public class FilmStripView extends ViewGroup implements BottomControlsListener { @Override public void onAnimationEnd(Animator anim) { - ViewInfo info = mViewInfo[mCurrentInfo]; - if (info == null) { + ViewItem item = mViewItem[mCurrentItem]; + if (item == null) { return; } - if (mCenterX == info.getCenterX()) { - if (inFullScreen()) { - lockAtCurrentView(); - } else if (inFilmStrip()) { - unlockPosition(); + if (mCenterX == item.getCenterX()) { + if (inFilmStrip()) { snapInCenter(); } } @@ -1665,8 +1699,8 @@ public class FilmStripView extends ViewGroup implements BottomControlsListener { @Override public boolean onSingleTapUp(float x, float y) { if (inFilmStrip()) { - ViewInfo centerInfo = mViewInfo[mCurrentInfo]; - if (centerInfo != null && centerInfo.areaContains(x, y)) { + ViewItem centerItem = mViewItem[mCurrentItem]; + if (centerItem != null && centerItem.areaContains(x, y)) { mController.gotoFullScreen(); return true; } @@ -1696,14 +1730,14 @@ public class FilmStripView extends ViewGroup implements BottomControlsListener { float halfH = getHeight() / 2; mIsUserScrolling = false; for (int i = 0; i < BUFFER_SIZE; i++) { - if (mViewInfo[i] == null) { + if (mViewItem[i] == null) { continue; } - float transY = mViewInfo[i].getTranslationY(mScale); + float transY = mViewItem[i].getTranslationY(mScale); if (transY == 0) { continue; } - int id = mViewInfo[i].getID(); + int id = mViewItem[i].getID(); if (mDataAdapter.getImageData(id) .isUIActionSupported(ImageData.ACTION_DEMOTE) @@ -1715,7 +1749,7 @@ public class FilmStripView extends ViewGroup implements BottomControlsListener { promoteData(i, id); } else { // put the view back. - mViewInfo[i].getView().animate() + mViewItem[i].getView().animate() .translationY(0f) .alpha(1f) .setDuration(DURATION_GEOMETRY_ADJUST) @@ -1728,7 +1762,7 @@ public class FilmStripView extends ViewGroup implements BottomControlsListener { @Override public boolean onScroll(float x, float y, float dx, float dy) { - if (mViewInfo[mCurrentInfo] == null) { + if (mViewItem[mCurrentItem] == null) { return false; } mIsUserScrolling = true; @@ -1747,10 +1781,10 @@ public class FilmStripView extends ViewGroup implements BottomControlsListener { int hit = 0; Rect hitRect = new Rect(); for (; hit < BUFFER_SIZE; hit++) { - if (mViewInfo[hit] == null) { + if (mViewItem[hit] == null) { continue; } - mViewInfo[hit].getView().getHitRect(hitRect); + mViewItem[hit].getView().getHitRect(hitRect); if (hitRect.contains((int) x, (int) y)) { break; } @@ -1759,21 +1793,22 @@ public class FilmStripView extends ViewGroup implements BottomControlsListener { return false; } - ImageData data = mDataAdapter.getImageData(mViewInfo[hit].getID()); - float transY = mViewInfo[hit].getTranslationY(mScale) - dy / mScale; + ImageData data = mDataAdapter.getImageData(mViewItem[hit].getID()); + float transY = mViewItem[hit].getTranslationY(mScale) - dy / mScale; if (!data.isUIActionSupported(ImageData.ACTION_DEMOTE) && transY > 0f) { transY = 0f; } if (!data.isUIActionSupported(ImageData.ACTION_PROMOTE) && transY < 0f) { transY = 0f; } - mViewInfo[hit].setTranslationY(transY, mScale); + mViewItem[hit].setTranslationY(transY, mScale); } } else if (inFullScreen()) { if (deltaX > 0 && inCameraFullscreen()) { mController.gotoFilmStrip(); } - mController.scroll(deltaX); + // Multiplied by 1.2 to make it more easy to swipe. + mController.scroll((int) (deltaX * 1.2)); } layoutChildren(); @@ -1782,11 +1817,16 @@ public class FilmStripView extends ViewGroup implements BottomControlsListener { @Override public boolean onFling(float velocityX, float velocityY) { - if (Math.abs(velocityX) > Math.abs(velocityY)) { - mController.fling(velocityX); - } else { + if (Math.abs(velocityX) < Math.abs(velocityY)) { // ignore vertical fling. + return true; + } + + if (mScale != FILM_STRIP_SCALE) { + // No fling in other modes. + return true; } + mController.fling(velocityX); return true; } |