Improve ScrollLayoutManager

This commit is contained in:
seven332 committed 2016-04-03 17:12:13 +08:00
1 parent e8251ee521
commit 52ab8cebb0
1 file changed
+160 -72
@@ -42,12 +42,14 @@ public class ScrollLayoutManager extends GalleryView.LayoutManager {
private static final int INTERVAL = 24;
private static final float RESERVATIONS = 0.5f;
private static final float RESERVATION = 1f;
private static final float MAX_SCALE = 2.0f;
private static final float MIN_SCALE = 0.5f;
private static final float MIN_SCALE = 1.0f;
private static final float SCALE_ERROR = 0.01f;
private static final int INVALID_TOP = Integer.MAX_VALUE;
private GalleryView.Adapter mAdapter;
private GLProgressView mProgress;
@@ -61,7 +63,9 @@ public class ScrollLayoutManager extends GalleryView.LayoutManager {
private int mOffsetY;
private int mDeltaX;
private int mDeltaY;
private int mFirstShownLoadedPageIndex = GalleryPageView.INVALID_INDEX;
private int mKeepTopPageIndex = GalleryPageView.INVALID_INDEX;
private int mKeepTop = INVALID_TOP;
private int mFirstShownPageIndex = GalleryPageView.INVALID_INDEX;
private boolean mScrollUp;
private boolean mFlingUp;
private boolean mStopAnimationFinger;
@@ -91,7 +95,9 @@ public class ScrollLayoutManager extends GalleryView.LayoutManager {
mOffsetY = 0;
mDeltaX = 0;
mDeltaY = 0;
mFirstShownLoadedPageIndex = GalleryPageView.INVALID_INDEX;
mKeepTopPageIndex = GalleryPageView.INVALID_INDEX;
mKeepTop = INVALID_TOP;
mFirstShownPageIndex = GalleryPageView.INVALID_INDEX;
mScrollUp = false;
mFlingUp = false;
mStopAnimationFinger = false;
@@ -181,6 +187,19 @@ public class ScrollLayoutManager extends GalleryView.LayoutManager {
return null;
}
private boolean isInScreen(GalleryPageView page) {
int height = mGalleryView.getHeight();
Rect bound = page.bounds();
int pageTop = bound.top;
int pageBottom = bound.bottom;
return (pageTop >= 0 && pageTop < height) || (pageBottom > 0 && pageBottom <= height) ||
(pageTop < 0 && pageBottom > height);
}
private float getReservation() {
return Math.max(RESERVATION, (((1 + 2 * RESERVATION) * mScale) - 1) / 2);
}
private void fillPages(int startIndex, int startOffset) {
final GalleryView.Adapter adapter = mAdapter;
final GalleryView galleryView = mGalleryView;
@@ -191,8 +210,9 @@ public class ScrollLayoutManager extends GalleryView.LayoutManager {
final int pageWidth = (int) (width * mScale);
final int size = adapter.size();
final int interval = mInterval;
final int minY = (int) (-height * RESERVATIONS);
final int maxY = (int) (height * (1 + RESERVATIONS));
final float reservation = getReservation();
final int minY = (int) (-height * reservation);
final int maxY = (int) (height * (1 + reservation));
final int widthSpec = GLView.MeasureSpec.makeMeasureSpec(pageWidth, GLView.MeasureSpec.EXACTLY);
final int heightSpec = GLView.MeasureSpec.makeMeasureSpec(height, GLView.MeasureSpec.UNSPECIFIED);
@@ -378,7 +398,6 @@ public class ScrollLayoutManager extends GalleryView.LayoutManager {
GalleryView galleryView = mGalleryView;
AssertUtils.assertNotEquals("The PagerLayoutManager is not attached", adapter, null);
int height = galleryView.getHeight();
int size = adapter.size();
String errorStr = adapter.getError();
@@ -442,48 +461,50 @@ public class ScrollLayoutManager extends GalleryView.LayoutManager {
removeAllPages();
}
// Find first shown loaded page top
GalleryPageView firstShownLoadedPage = null;
int firstShownLoadedPageTop = mOffsetY;
if (mFirstShownLoadedPageIndex != GalleryPageView.INVALID_INDEX) {
// Find keep index and keep top
int keepTop = INVALID_TOP;
int keepTopIndex;
if (GalleryPageView.INVALID_INDEX != mKeepTopPageIndex) {
keepTopIndex = mKeepTopPageIndex;
keepTop = mKeepTop;
} else if (GalleryPageView.INVALID_INDEX != mFirstShownPageIndex) {
keepTopIndex = mFirstShownPageIndex;
} else {
keepTopIndex = GalleryPageView.INVALID_INDEX;
}
if (GalleryPageView.INVALID_INDEX != keepTopIndex && INVALID_TOP == keepTop) {
keepTop = mOffsetY;
for (GalleryPageView page : pages) {
// Check first shown loaded page
if (mFirstShownLoadedPageIndex == page.getIndex()) {
firstShownLoadedPage = page;
// Check keep page
if (keepTopIndex == page.getIndex()) {
break;
}
firstShownLoadedPageTop += page.getHeight() + mInterval;
keepTop += page.getHeight() + mInterval;
}
}
int startIndex;
int startOffset;
if (null != firstShownLoadedPage) {
startIndex = mFirstShownLoadedPageIndex;
startOffset = firstShownLoadedPageTop;
if (GalleryPageView.INVALID_INDEX != keepTopIndex) {
startIndex = keepTopIndex;
startOffset = keepTop;
} else {
startIndex = mIndex;
startOffset = mOffsetY;
}
fillPages(startIndex, startOffset);
// Get first shown loaded image
mFirstShownLoadedPageIndex = GalleryPageView.INVALID_INDEX;
if (mScrollUp || mFlingUp) {
for (GalleryPageView page : mPages) {
// Check first shown loaded page
if (!page.isLoaded()) {
continue;
}
// Get first shown image
mFirstShownPageIndex = GalleryPageView.INVALID_INDEX;
for (GalleryPageView page : mPages) {
// Check first shown loaded page
if ((mScrollUp || mFlingUp) && !page.isLoaded()) {
continue;
}
Rect bound = page.bounds();
int pageTop = bound.top;
int pageBottom = bound.bottom;
if ((pageTop >= 0 && pageTop < height) || (pageBottom > 0 && pageBottom <= height) ||
(pageTop < 0 && pageBottom > height)) {
mFirstShownLoadedPageIndex = page.getIndex();
break;
}
if (isInScreen(page)) {
mFirstShownPageIndex = page.getIndex();
break;
}
}
}
@@ -511,9 +532,7 @@ public class ScrollLayoutManager extends GalleryView.LayoutManager {
float startScale = mScale;
float endScale;
if (startScale < 1.0f - SCALE_ERROR) {
endScale = 1.0f;
} else if (startScale < MAX_SCALE - SCALE_ERROR) {
if (startScale < MAX_SCALE - SCALE_ERROR) {
endScale = MAX_SCALE;
} else {
endScale = MIN_SCALE;
@@ -585,6 +604,7 @@ public class ScrollLayoutManager extends GalleryView.LayoutManager {
int width = galleryView.getWidth();
int height = galleryView.getHeight();
int pageWidth = (int) (width * mScale);
final float reservation = getReservation();
boolean requestFill = false;
boolean result = false;
@@ -611,7 +631,7 @@ public class ScrollLayoutManager extends GalleryView.LayoutManager {
if (remainY < 0) { // Try to show top
int limit;
if (mIndex > 0) {
limit = (int) (-height * RESERVATIONS) + mInterval;
limit = (int) (-height * reservation) + mInterval;
} else {
limit = 0;
}
@@ -652,7 +672,7 @@ public class ScrollLayoutManager extends GalleryView.LayoutManager {
int limit;
if (hasNext) {
limit = (int) (height * (1 + RESERVATIONS)) - mInterval;
limit = (int) (height * (1 + reservation)) - mInterval;
} else {
limit = height;
}
@@ -700,6 +720,8 @@ public class ScrollLayoutManager extends GalleryView.LayoutManager {
@Override
public void onScroll(float dx, float dy, float totalX, float totalY, float x, float y) {
mKeepTopPageIndex = GalleryPageView.INVALID_INDEX;
mKeepTop = INVALID_TOP;
mScrollUp = dy < 0;
scrollInternal(dx, dy, false, x, y);
}
@@ -710,6 +732,8 @@ public class ScrollLayoutManager extends GalleryView.LayoutManager {
return;
}
mKeepTopPageIndex = GalleryPageView.INVALID_INDEX;
mKeepTop = INVALID_TOP;
mFlingUp = velocityY > 0;
int maxX;
@@ -753,16 +777,33 @@ public class ScrollLayoutManager extends GalleryView.LayoutManager {
@Override
public void onScale(float focusX, float focusY, float scale) {
if (mPages.isEmpty()) {
return;
}
float oldScale = mScale;
mScale = MathUtils.clamp(oldScale * scale, MIN_SCALE, MAX_SCALE);
scale = mScale / oldScale;
mGalleryView.forceFill();
if (oldScale != mScale) {
// Keep scale page origin position
for (GalleryPageView page : mPages) {
if (page.bounds().top < focusY) {
mKeepTopPageIndex = page.getIndex();
mKeepTop = page.bounds().top;
} else {
break;
}
}
if (1.0f != scale) {
mGalleryView.forceFill();
int oldKeepTop = mKeepTop;
mKeepTop = INVALID_TOP;
// Apply scroll
int newOffsetX = (int) (focusX - ((focusX - mOffsetX) * scale));
int newOffsetY = (int) (focusY - ((focusY - mOffsetY) * scale));
scrollInternal(mOffsetX - newOffsetX, mOffsetY - newOffsetY, false, focusX, focusY);
int newKeepTop = (int) (focusY - ((focusY - oldKeepTop) * scale));
scrollInternal(mOffsetX - newOffsetX, oldKeepTop - newKeepTop, false, focusX, focusY);
}
}
@@ -810,6 +851,9 @@ public class ScrollLayoutManager extends GalleryView.LayoutManager {
return;
}
///////
// UP
///////
GalleryView galleryView = mGalleryView;
if (mIndex == 0 && mOffsetY >= 0) {
GLEdgeView edgeView = galleryView.getEdgeView();
@@ -819,13 +863,37 @@ public class ScrollLayoutManager extends GalleryView.LayoutManager {
} else {
// Cancel all animations
cancelAllAnimations();
mOffsetY += galleryView.getHeight() / 2;
// Backup offset
int offset = mOffsetY;
// Reset parameters
resetParameters();
// Restore offset
mOffsetY = offset;
// Get first shown page
GalleryPageView previousPage = null;
GalleryPageView firstShownPage = null;
for (GalleryPageView p: mPages) {
if (isInScreen(p)) {
firstShownPage = p;
break;
}
previousPage = p;
}
int height = galleryView.getHeight();
int maxOffset = height - mInterval;
if (null == firstShownPage) {
Log.e(TAG, "Can't find first shown page when paging left");
mOffsetY += height / 2;
} else {
int firstShownTop = firstShownPage.bounds().top;
if (firstShownTop >= 0) {
if (null == previousPage) {
Log.e(TAG, "Can't find previous page when paging left and offsetY == 0");
mOffsetY += height / 2;
} else {
mOffsetY += Math.min(maxOffset, -previousPage.bounds().top);
}
} else {
mOffsetY += Math.min(maxOffset, -firstShownTop);
}
}
// Request fill
mGalleryView.requestFill();
}
@@ -838,6 +906,9 @@ public class ScrollLayoutManager extends GalleryView.LayoutManager {
return;
}
/////////
// DOWN
/////////
GalleryView galleryView = mGalleryView;
getBottomState();
int bottom = mBottomStateBottom;
@@ -850,13 +921,38 @@ public class ScrollLayoutManager extends GalleryView.LayoutManager {
} else {
// Cancel all animations
cancelAllAnimations();
mOffsetY -= galleryView.getHeight() / 2;
// Backup offset
int offset = mOffsetY;
// Reset parameters
resetParameters();
// Restore offset
mOffsetY = offset;
// Get first shown page
GalleryPageView lastShownPage = null;
GalleryPageView nextPage = null;
for (GalleryPageView p: mPages) {
if (isInScreen(p)) {
lastShownPage = p;
} else if (null != lastShownPage) {
nextPage = p;
break;
}
}
int height = galleryView.getHeight();
int maxOffset = height - mInterval;
if (null == lastShownPage) {
Log.e(TAG, "Can't find last shown page when paging left");
mOffsetY -= height / 2;
} else {
int lastShownBottom = lastShownPage.bounds().bottom;
if (lastShownBottom <= height) {
if (null == nextPage) {
Log.e(TAG, "Can't find previous page when paging left and offsetY == 0");
mOffsetY -= height / 2;
} else {
mOffsetY -= Math.min(maxOffset, nextPage.bounds().bottom - height);
}
} else {
mOffsetY -= Math.min(maxOffset, lastShownBottom - height);
}
}
// Request fill
mGalleryView.requestFill();
}
@@ -879,13 +975,8 @@ public class ScrollLayoutManager extends GalleryView.LayoutManager {
@Override
public int getCurrentIndex() {
int height = mGalleryView.getHeight();
for (GalleryPageView page : mPages) {
Rect bound = page.bounds();
int pageTop = bound.top;
int pageBottom = bound.bottom;
if ((pageTop >= 0 && pageTop < height) || (pageBottom > 0 && pageBottom <= height) ||
(pageTop < 0 && pageBottom > height)) {
if (isInScreen(page)) {
return page.getIndex();
}
}
@@ -899,9 +990,13 @@ public class ScrollLayoutManager extends GalleryView.LayoutManager {
// Can't get size now, assume size is MAX
size = Integer.MAX_VALUE;
}
if (index == mIndex || index < 0 || index >= size) {
if (index < 0 || index >= size) {
return;
}
mKeepTopPageIndex = index;
mKeepTop = INVALID_TOP;
if (mPages.isEmpty()) {
mIndex = index;
} else {
@@ -918,24 +1013,17 @@ public class ScrollLayoutManager extends GalleryView.LayoutManager {
// Cancel all animations
cancelAllAnimations();
mOffsetY -= targetPage.bounds().top;
// Backup offset
int offset = mOffsetY;
// Reset parameters
resetParameters();
// Restore offset
mOffsetY = offset;
// Request fill
mGalleryView.requestFill();
} else {
mIndex = index;
mOffsetY = 0;
// Cancel all animations
cancelAllAnimations();
// Remove all view
removeProgress();
removeErrorView();
removeAllPages();
// Reset parameters
resetParameters();
// Request fill
mGalleryView.requestFill();
}