diff --git a/FlipView/Demo/APK/Aphid-FlipView-Demo.apk b/FlipView/Demo/APK/Aphid-FlipView-Demo.apk index ba7d3ca..efa76e5 100644 Binary files a/FlipView/Demo/APK/Aphid-FlipView-Demo.apk and b/FlipView/Demo/APK/Aphid-FlipView-Demo.apk differ diff --git a/FlipView/Demo/src/com/aphidmobile/flip/demo/FlipComplexLayoutActivity.java b/FlipView/Demo/src/com/aphidmobile/flip/demo/FlipComplexLayoutActivity.java index bc0cd11..8434f23 100644 --- a/FlipView/Demo/src/com/aphidmobile/flip/demo/FlipComplexLayoutActivity.java +++ b/FlipView/Demo/src/com/aphidmobile/flip/demo/FlipComplexLayoutActivity.java @@ -37,7 +37,7 @@ public void onCreate(Bundle savedInstanceState) { flipView = new FlipViewController(this); - //Use RGB_565 to reduce peak memory usage on large screen device + //Use RGB_565 can reduce peak memory usage on large screen device flipView.setAnimationBitmapFormat(Bitmap.Config.RGB_565); flipView.setAdapter(new TravelAdapter(this)); diff --git a/FlipView/Demo/src/com/aphidmobile/flip/demo/adapter/TravelAdapter.java b/FlipView/Demo/src/com/aphidmobile/flip/demo/adapter/TravelAdapter.java index 12b627c..3d8c188 100644 --- a/FlipView/Demo/src/com/aphidmobile/flip/demo/adapter/TravelAdapter.java +++ b/FlipView/Demo/src/com/aphidmobile/flip/demo/adapter/TravelAdapter.java @@ -43,8 +43,10 @@ public long getItemId(int position) { @Override public View getView(int position, View convertView, ViewGroup parent) { View layout = convertView; - if (convertView == null) + if (convertView == null) { layout = inflater.inflate(R.layout.complex1, null); + AphidLog.d("created new view from adapter: %d", position); + } final Travels.Data data = Travels.IMG_DESCRIPTIONS.get(position); diff --git a/FlipView/FlipLibrary/src/com/aphidmobile/flip/FlipCards.java b/FlipView/FlipLibrary/src/com/aphidmobile/flip/FlipCards.java index ce63b26..d64ad7a 100644 --- a/FlipView/FlipLibrary/src/com/aphidmobile/flip/FlipCards.java +++ b/FlipView/FlipLibrary/src/com/aphidmobile/flip/FlipCards.java @@ -17,14 +17,17 @@ package com.aphidmobile.flip; -import android.view.*; +import android.view.MotionEvent; +import android.view.View; import com.aphidmobile.utils.AphidLog; import com.aphidmobile.utils.TextureUtils; +import com.aphidmobile.utils.UI; +import junit.framework.Assert; import javax.microedition.khronos.opengles.GL10; public class FlipCards { - private static final float ACCELERATION = 0.65f; + private static final float ACCELERATION = 0.65f; private static final float MOVEMENT_RATE = 1.5f; private static final int MAX_TIP_ANGLE = 60; private static final int MAX_TOUCH_MOVE_ANGLE = 15; @@ -37,7 +40,7 @@ public class FlipCards { private ViewDualCards frontCards; private ViewDualCards backCards; - private float angle = 0f; + private float accumulatedAngle = 0f; private boolean forward = true; private int animatedFrame = 0; private int state = STATE_INIT; @@ -47,18 +50,19 @@ public class FlipCards { private FlipViewController controller; - private int activeIndex = -1; + //private int activeIndex = -1; private boolean waitForTexture = false; - + private boolean visible = false; + private int maxIndex = 0; + public FlipCards(FlipViewController controller, boolean orientationVertical) { this.controller = controller; frontCards = new ViewDualCards(orientationVertical); backCards = new ViewDualCards(orientationVertical); this.orientationVertical = orientationVertical; - resetAxises(); } public boolean isVisible() { @@ -70,159 +74,170 @@ public void setVisible(boolean visible) { if (!visible) waitForTexture = false; } - + boolean refreshPageView(View view) { boolean match = false; if (frontCards.getView() == view) { - frontCards.markForceReload(); + frontCards.resetWithIndex(frontCards.getIndex()); match = true; } if (backCards.getView() == view) { - backCards.markForceReload(); + backCards.resetWithIndex(backCards.getIndex()); match = true; } - + return match; } - + boolean refreshPage(int pageIndex) { boolean match = false; if (frontCards.getIndex() == pageIndex) { - frontCards.markForceReload(); + frontCards.resetWithIndex(pageIndex); match = true; } if (backCards.getIndex() == pageIndex) { - backCards.markForceReload(); + backCards.resetWithIndex(pageIndex); match = true; } - + return match; } + + void refreshAllPages() { + frontCards.resetWithIndex(frontCards.getIndex()); + backCards.resetWithIndex(backCards.getIndex()); + } public void reloadTexture(int frontIndex, View frontView, int backIndex, View backView) { synchronized (this) { - if (frontView != null) { - if (backCards.getView() == frontView) { - frontCards.setView(-1, null, controller.getAnimationBitmapFormat()); - swapCards(); - } - } - - if (backView != null) { - if (frontCards.getView() == backView) { - backCards.setView(-1, null, controller.getAnimationBitmapFormat()); - swapCards(); - } - } - - boolean frontChanged = frontCards.setView(frontIndex, frontView, controller.getAnimationBitmapFormat()); - boolean backChanged = backCards.setView(backIndex, backView, controller.getAnimationBitmapFormat()); + boolean frontChanged = frontCards.loadView(frontIndex, frontView, controller.getAnimationBitmapFormat()); + boolean backChanged = backCards.loadView(backIndex, backView, controller.getAnimationBitmapFormat()); if (AphidLog.ENABLE_DEBUG) AphidLog.d("reloading texture: %s and %s; old views: %s, %s, front changed %s, back changed %s", frontView, backView, frontCards.getView(), backCards.getView(), frontChanged, backChanged); - - if (AphidLog.ENABLE_DEBUG) - AphidLog.d("reloadTexture: activeIndex %d, front %d, back %d, angle %.1f", activeIndex, frontIndex, backIndex, angle); - - if (waitForTexture) { - if (frontIndex == activeIndex) { - if (angle >= 180) - angle -= 180; - else if (angle < 0) - angle += 180; - } else if (backIndex == activeIndex) { - if (angle < 0) - angle += 180; - } - waitForTexture = false; - } -// AphidLog.i("View changed: front (%d, %s), back (%d, %s), angle %s, activeIndex %d", frontIndex, frontView, backIndex, backView, angle, activeIndex); + if (AphidLog.ENABLE_DEBUG) + AphidLog.d("reloadTexture: activeIndex %d, front %d, back %d, angle %.1f", getPageIndexFromAngle(), frontIndex, backIndex, accumulatedAngle); } } - private void setState(int state) { - if (this.state != state) { - /* - if (AphidLog.ENABLE_DEBUG) - AphidLog.i("setState: from %d, to %d; angle %.1f", this.state, state, angle); - */ - this.state = state; - animatedFrame = 0; - } + synchronized void resetSelection(int selection, int maxIndex) { + UI.assertInMainThread(); + + //stop flip animation when selection is manually changed + + this.maxIndex = maxIndex; + setVisible(false); + setState(STATE_INIT); + accumulatedAngle = selection * 180; + frontCards.resetWithIndex(selection); + backCards.resetWithIndex(selection + 1 < maxIndex ? selection + 1 : -1); + controller.postHideFlipAnimation(); } - public synchronized void draw(FlipRenderer renderer, GL10 gl) { - applyTexture(renderer, gl); + public synchronized void draw(FlipRenderer renderer, GL10 gl) { + frontCards.buildTexture(renderer, gl); + backCards.buildTexture(renderer, gl); if (!TextureUtils.isValidTexture(frontCards.getTexture()) && !TextureUtils.isValidTexture(backCards.getTexture())) return; - + if (!visible) return; switch (state) { - case STATE_INIT: - break; - case STATE_TOUCH: - break; - case STATE_AUTO_ROTATE: { - if (waitForTexture) - controller.getSurfaceView().requestRender(); - else { - animatedFrame++; - float delta = (forward ? ACCELERATION : -ACCELERATION) * animatedFrame; - - angle += delta; - - if (backCards.getIndex() == -1) { - if (angle >= MAX_TIP_ANGLE) - angle = MAX_TIP_ANGLE; - } + case STATE_INIT: + case STATE_TOUCH: + break; + case STATE_AUTO_ROTATE: { + if (waitForTexture) + controller.getSurfaceView().requestRender(); + else { + animatedFrame++; + float delta = (forward ? ACCELERATION : -ACCELERATION) * animatedFrame % 180; - if (angle >= 180 || angle <= 0) { - setState(STATE_INIT); + float oldAngle = accumulatedAngle; - if (angle >= 180) { // flip to next page - if (backCards.getIndex() != -1) { - activeIndex = backCards.getIndex(); - waitForTexture = true; - controller.postFlippedToView(activeIndex); - } + accumulatedAngle += delta; - angle = 180; - } else - angle = 0; + if (oldAngle < 0) { //bouncing back after flip backward and over the first page + Assert.assertTrue(forward); + if (accumulatedAngle >= 0) { + accumulatedAngle = 0; + setState(STATE_INIT); + } + } else { + if (frontCards.getIndex() == maxIndex - 1 && oldAngle > frontCards.getIndex() * 180) { //bouncing back after flip forward and over the last page + Assert.assertTrue(!forward); + if (accumulatedAngle <= frontCards.getIndex() * 180) { + setState(STATE_INIT); + accumulatedAngle = frontCards.getIndex() * 180; + } + } else { + if (forward) { + Assert.assertTrue("index of backCards should not be -1 when automatically flipping forward", backCards.getIndex() != -1); + if (accumulatedAngle >= backCards.getIndex() * 180) { //moved to the next page + accumulatedAngle = backCards.getIndex() * 180; + waitForTexture = true; + setState(STATE_INIT); + controller.postFlippedToView(backCards.getIndex()); + + swapCards(); + backCards.resetWithIndex(frontCards.getIndex() + 1); + } + } else { //backward + if (accumulatedAngle <= frontCards.getIndex() * 180) { //firstCards restored + accumulatedAngle = frontCards.getIndex() * 180; + setState(STATE_INIT); + } + } + } + } //ends of `if (oldAngle < 0) {} else {}` - controller.postHideFlipAnimation(); - } else - controller.getSurfaceView().requestRender(); + if (state == STATE_INIT) + controller.postHideFlipAnimation(); + else + controller.getSurfaceView().requestRender(); + } } - } - break; - default: - AphidLog.e("Invalid state: " + state); break; + default: + AphidLog.e("Invalid state: " + state); + break; } - if (angle < 90) { //render front view over back view - frontCards.getTopCard().setAngle(0); + float angle = getDisplayAngle(); + if (angle < 0) { + frontCards.getTopCard().setAxis(Card.AXIS_BOTTOM); + frontCards.getTopCard().setAngle(-angle); frontCards.getTopCard().draw(gl); - backCards.getBottomCard().setAngle(0); - backCards.getBottomCard().draw(gl); - - frontCards.getBottomCard().setAngle(angle); + frontCards.getBottomCard().setAngle(0); frontCards.getBottomCard().draw(gl); - } else { //render back view first - frontCards.getTopCard().setAngle(0); - frontCards.getTopCard().draw(gl); - - backCards.getTopCard().setAngle(180 - angle); - backCards.getTopCard().draw(gl); - - backCards.getBottomCard().setAngle(0); - backCards.getBottomCard().draw(gl); + + //no need to draw backCards here + } else { + if (angle < 90) { //render front view over back view + frontCards.getTopCard().setAngle(0); + frontCards.getTopCard().draw(gl); + + backCards.getBottomCard().setAngle(0); + backCards.getBottomCard().draw(gl); + + frontCards.getBottomCard().setAxis(Card.AXIS_TOP); + frontCards.getBottomCard().setAngle(angle); + frontCards.getBottomCard().draw(gl); + } else { //render back view first + frontCards.getTopCard().setAngle(0); + frontCards.getTopCard().draw(gl); + + backCards.getTopCard().setAxis(Card.AXIS_BOTTOM); + backCards.getTopCard().setAngle(180 - angle); + backCards.getTopCard().draw(gl); + + backCards.getBottomCard().setAngle(0); + backCards.getBottomCard().draw(gl); + } } } @@ -240,18 +255,18 @@ public synchronized boolean handleTouchEvent(MotionEvent event, boolean isOnTouc if (waitForTexture) return isOnTouchEvent; float delta = orientationVertical ? (lastPosition - event.getY()) : (lastPosition - event.getX()); - + if (Math.abs(delta) > controller.getTouchSlop()) { - setState(STATE_TOUCH); //XXX: initialize views? + setState(STATE_TOUCH); forward = delta > 0; } if (state == STATE_TOUCH) { - if (Math.abs(delta) > MIN_MOVEMENT) - forward = delta > 0; - + if (Math.abs(delta) > MIN_MOVEMENT) //ignore small movements + forward = delta > 0; + controller.showFlipAnimation(); - - float angleDelta ; + + float angleDelta; if (orientationVertical) angleDelta = 180 * delta / controller.getContentHeight() * MOVEMENT_RATE; else @@ -259,34 +274,37 @@ public synchronized boolean handleTouchEvent(MotionEvent event, boolean isOnTouc if (Math.abs(angleDelta) > MAX_TOUCH_MOVE_ANGLE) //prevent large delta when moving too fast angleDelta = Math.signum(angleDelta) * MAX_TOUCH_MOVE_ANGLE; - - angle += angleDelta; - + + accumulatedAngle += angleDelta; + //Bounce the page for the first and the last page - if (backCards.getIndex() == -1) { //the last page - if (angle >= MAX_TIP_ANGLE) - angle = MAX_TIP_ANGLE; - } else if (backCards.getIndex() == 0) { //the first page - if (angle <= 180 - MAX_TIP_ANGLE) - angle = 180 - MAX_TIP_ANGLE; - } - - if (angle < 0) { - if (frontCards.getIndex() > 0) { - activeIndex = frontCards.getIndex() - 1; //xxx - waitForTexture = true; - controller.flippedToView(activeIndex, false); - } else { - swapCards(); - frontCards.setView(-1, null, controller.getAnimationBitmapFormat()); - if (-angle >= MAX_TIP_ANGLE) - angle = -MAX_TIP_ANGLE; - angle += 180; + if (frontCards.getIndex() == maxIndex - 1) { //the last page + if (accumulatedAngle > frontCards.getIndex() * 180 + MAX_TIP_ANGLE) + accumulatedAngle = frontCards.getIndex() * 180 + MAX_TIP_ANGLE; + } else if (accumulatedAngle < -MAX_TIP_ANGLE) + accumulatedAngle = -MAX_TIP_ANGLE; + + int anglePageIndex = getPageIndexFromAngle(); + + if (accumulatedAngle >= 0) { + if (anglePageIndex != frontCards.getIndex()) { + if (anglePageIndex == frontCards.getIndex() - 1) { //moved to previous page + swapCards(); //frontCards becomes the backCards + frontCards.resetWithIndex(backCards.getIndex() - 1); + //waitForTexture = true; + controller.flippedToView(anglePageIndex, false); + } else if (anglePageIndex == frontCards.getIndex() + 1) { //moved to next page + swapCards(); + backCards.resetWithIndex(frontCards.getIndex() + 1); + //waitForTexture = true; + controller.flippedToView(anglePageIndex, false); + } else + throw new RuntimeException(AphidLog.format("Inconsistent states: anglePageIndex: %d, accumulatedAngle %.1f, frontCards %d, backCards %d", anglePageIndex, accumulatedAngle, frontCards.getIndex(), backCards.getIndex())); } } - + lastPosition = orientationVertical ? event.getY() : event.getX(); - + controller.getSurfaceView().requestRender(); return true; } @@ -295,36 +313,42 @@ public synchronized boolean handleTouchEvent(MotionEvent event, boolean isOnTouc case MotionEvent.ACTION_UP: case MotionEvent.ACTION_CANCEL: if (state == STATE_TOUCH) { - if (frontCards.getIndex() == -1) // If at the first or last card + if (accumulatedAngle < 0) forward = true; - else if (backCards.getIndex() == -1) + else if (accumulatedAngle > frontCards.getIndex() * 180 && frontCards.getIndex() == maxIndex - 1) forward = false; - + setState(STATE_AUTO_ROTATE); controller.getSurfaceView().requestRender(); - } + } return isOnTouchEvent; } return false; } - private void resetAxises() { - frontCards.getTopCard().setAxis(Card.AXIS_TOP); - frontCards.getBottomCard().setAxis(Card.AXIS_TOP); - backCards.getBottomCard().setAxis(Card.AXIS_TOP); - backCards.getTopCard().setAxis(Card.AXIS_BOTTOM); - } - private void swapCards() { ViewDualCards tmp = frontCards; frontCards = backCards; backCards = tmp; - resetAxises(); } - private void applyTexture(FlipRenderer renderer, GL10 gl) { - frontCards.buildTexture(renderer, gl); - backCards.buildTexture(renderer, gl); + private void setState(int state) { + if (this.state != state) { + /* + if (AphidLog.ENABLE_DEBUG) + AphidLog.i("setState: from %d, to %d; angle %.1f", this.state, state, angle); + */ + this.state = state; + animatedFrame = 0; + } + } + + private int getPageIndexFromAngle() { + return ((int) accumulatedAngle) / 180; + } + + private float getDisplayAngle() { + return accumulatedAngle % 180; } } \ No newline at end of file diff --git a/FlipView/FlipLibrary/src/com/aphidmobile/flip/FlipRenderer.java b/FlipView/FlipLibrary/src/com/aphidmobile/flip/FlipRenderer.java index 6b6dddb..d7f3c1f 100644 --- a/FlipView/FlipLibrary/src/com/aphidmobile/flip/FlipRenderer.java +++ b/FlipView/FlipLibrary/src/com/aphidmobile/flip/FlipRenderer.java @@ -1,15 +1,13 @@ package com.aphidmobile.flip; -import javax.microedition.khronos.egl.EGLConfig; -import javax.microedition.khronos.opengles.GL10; - -import com.aphidmobile.utils.AphidLog; - import android.opengl.GLSurfaceView; import android.opengl.GLU; import android.view.View; +import com.aphidmobile.utils.AphidLog; import com.aphidmobile.utils.TextureUtils; +import javax.microedition.khronos.egl.EGLConfig; +import javax.microedition.khronos.opengles.GL10; import java.util.LinkedList; import static javax.microedition.khronos.opengles.GL10.*; @@ -35,9 +33,9 @@ public class FlipRenderer implements GLSurfaceView.Renderer { private FlipViewController flipViewController; private FlipCards cards; - + private boolean created = false; - + private final LinkedList postDestroyTextures = new LinkedList(); public FlipRenderer(FlipViewController flipViewController, FlipCards cards) { @@ -53,12 +51,12 @@ public void onSurfaceCreated(GL10 gl, EGLConfig config) { gl.glEnable(GL_DEPTH_TEST); gl.glDepthFunc(GL_LEQUAL); gl.glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); - + created = true; - + cards.invalidateTexture(); flipViewController.reloadTexture(); - + if (AphidLog.ENABLE_DEBUG) AphidLog.d("onSurfaceCreated"); } @@ -100,18 +98,18 @@ public void onSurfaceChanged(GL10 gl, int width, int height) { } @Override - public void onDrawFrame(GL10 gl) { + public void onDrawFrame(GL10 gl) { gl.glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - + synchronized (postDestroyTextures) { for (Texture texture : postDestroyTextures) texture.destroy(gl); postDestroyTextures.clear(); } - + cards.draw(this, gl); } - + public void postDestroyTexture(Texture texture) { synchronized (postDestroyTextures) { postDestroyTextures.add(texture); @@ -122,12 +120,14 @@ public void updateTexture(int frontIndex, View frontView, int backIndex, View ba if (created) { cards.reloadTexture(frontIndex, frontView, backIndex, backView); flipViewController.getSurfaceView().requestRender(); - } + } } public static void checkError(GL10 gl) { - int error = gl.glGetError(); - if (error != 0) - throw new RuntimeException(GLU.gluErrorString(error)); + if (AphidLog.ENABLE_DEBUG) { + int error = gl.glGetError(); + if (error != 0) + throw new RuntimeException(GLU.gluErrorString(error)); + } } } diff --git a/FlipView/FlipLibrary/src/com/aphidmobile/flip/FlipViewController.java b/FlipView/FlipLibrary/src/com/aphidmobile/flip/FlipViewController.java index 84c0dfa..b124070 100644 --- a/FlipView/FlipLibrary/src/com/aphidmobile/flip/FlipViewController.java +++ b/FlipView/FlipLibrary/src/com/aphidmobile/flip/FlipViewController.java @@ -41,7 +41,7 @@ public class FlipViewController extends AdapterView { public static final int ORIENTATION_VERTICAL = 0; public static final int ORIENTATION_HORIZONTAL = 1; - private static final int MAX_RELEASED_VIEW_SIZE = 4; + private static final int MAX_RELEASED_VIEW_SIZE = 1; public static interface ViewFlipListener { void onViewFlipped(View view, int position); @@ -217,9 +217,9 @@ void reloadTexture() { } /** - * Request the animator to update display if the pageView is active. + * Request the animator to update display if the pageView has been preloaded. * - * If the pageView is being used in the animation or its content has been buffered, the animator reloads it forcibly. + * If the pageView is being used in the animation or its content has been buffered, the animator forcibly reloads it. * * The reloading process is a bit heavy for an active page, so please don't invoke it too frequently for an active page. The cost is trivial for inactive pages. * @param pageView @@ -228,12 +228,24 @@ public void refreshPage(View pageView) { if (cards.refreshPageView(pageView)) requestLayout(); } - + + /** + * @see #refreshPage(android.view.View) + * @param pageIndex + */ public void refreshPage(int pageIndex) { if (cards.refreshPage(pageIndex)) requestLayout(); } + /** + * Force the animator reload all preloaded pages + */ + public void refreshAllPages() { + cards.refreshAllPages(); + requestLayout(); + } + //-------------------------------------------------------------------------------------------------------------------- // Touch Event @Override @@ -311,6 +323,8 @@ public void setSelection(int position) { requestLayout(); updateVisibleView(inFlipAnimation ? -1 : bufferIndex); + + cards.resetSelection(position, adapter.getCount()); } @Override @@ -392,16 +406,18 @@ private void releaseView(View view) { } private void addReleasedView(View view) { + Assert.assertNotNull(view); if (releasedViews.size() < MAX_RELEASED_VIEW_SIZE) releasedViews.add(view); } private View viewFromAdapter(int position, boolean addToTop) { Assert.assertNotNull(adapter); - + View releasedView = releasedViews.isEmpty() ? null : releasedViews.removeFirst(); + View view = adapter.getView(position, releasedView, this); - if (view != releasedView) + if (releasedView != null && view != releasedView) addReleasedView(releasedView); setupAdapterView(view, addToTop, view == releasedView); @@ -421,15 +437,16 @@ private void setupAdapterView(View view, boolean addToTop, boolean isReusedView) } private void updateVisibleView(int index) { + /* if (AphidLog.ENABLE_DEBUG) AphidLog.d("Update visible views, index %d, buffered: %d, adapter %d", index, bufferedViews.size(), adapterIndex); + */ for (int i = 0; i < bufferedViews.size(); i++) bufferedViews.get(i).setVisibility(index == i ? VISIBLE : INVISIBLE); } void postFlippedToView(final int indexInAdapter) { - AphidLog.d("postFlippedToView: " + indexInAdapter); handler.post(new Runnable() { @Override public void run() { @@ -443,7 +460,7 @@ private void debugBufferedViews() { AphidLog.d("bufferedViews: %s; buffer index %d, adapter index %d", bufferedViews, bufferIndex, adapterIndex); } - void flippedToView(final int indexInAdapter, boolean isPost) { //XXX: can be simplified and unified with setSelection + void flippedToView(final int indexInAdapter, boolean isPost) { if (AphidLog.ENABLE_DEBUG) AphidLog.d("flippedToView: %d, isPost %s", indexInAdapter, isPost); @@ -476,13 +493,11 @@ void flippedToView(final int indexInAdapter, boolean isPost) { //XXX: can be sim updateVisibleView(inFlipAnimation ? -1 : bufferIndex); } } else { - //Issue #17 - if (indexInAdapter == 0 || indexInAdapter != adapterIndex) //indexInAdapter=0 is a special case after bouncing from edge - setSelection(indexInAdapter); + AphidLog.e("Should not happen: indexInAdapter %d, adapterIndex %d", indexInAdapter, adapterIndex); } } else - Assert.assertTrue("Invalid indexInAdapter: " + indexInAdapter, false); - debugBufferedViews(); + Assert.fail("Invalid indexInAdapter: " + indexInAdapter); + //debugBufferedViews(); } void postHideFlipAnimation() { diff --git a/FlipView/FlipLibrary/src/com/aphidmobile/flip/GrabIt.java b/FlipView/FlipLibrary/src/com/aphidmobile/flip/GrabIt.java index 4f123d3..67952c8 100644 --- a/FlipView/FlipLibrary/src/com/aphidmobile/flip/GrabIt.java +++ b/FlipView/FlipLibrary/src/com/aphidmobile/flip/GrabIt.java @@ -33,10 +33,10 @@ public static Bitmap takeScreenshot(View view, Bitmap.Config config) { Canvas canvas = new Canvas(bitmap); view.draw(canvas); - //canvas.drawColor(Color.RED, PorterDuff.Mode.DARKEN); //XXX: debug option + //canvas.drawColor(Color.RED, PorterDuff.Mode.DARKEN); //NOTES: debug option if (AphidLog.ENABLE_DEBUG) - AphidLog.d("create bitmap %dx%d", width, height); + AphidLog.d("create bitmap %dx%d, format %s", width, height, config); return bitmap; } else { diff --git a/FlipView/FlipLibrary/src/com/aphidmobile/flip/Texture.java b/FlipView/FlipLibrary/src/com/aphidmobile/flip/Texture.java index 3720801..643b4c3 100644 --- a/FlipView/FlipLibrary/src/com/aphidmobile/flip/Texture.java +++ b/FlipView/FlipLibrary/src/com/aphidmobile/flip/Texture.java @@ -44,16 +44,16 @@ public static Texture createTexture(Bitmap bitmap, FlipRenderer renderer, GL10 g Assert.assertTrue("bitmap should not be null or recycled", bitmap != null && !bitmap.isRecycled()); - int w = Integer.highestOneBit(bitmap.getWidth() - 1) << 1; - int h = Integer.highestOneBit(bitmap.getHeight() - 1) << 1; + int potW = Integer.highestOneBit(bitmap.getWidth() - 1) << 1; + int potH = Integer.highestOneBit(bitmap.getHeight() - 1) << 1; t.contentWidth = bitmap.getWidth(); t.contentHeight = bitmap.getHeight(); - t.width = w; - t.height = h; + t.width = potW; + t.height = potH; if (AphidLog.ENABLE_DEBUG) - AphidLog.d("createTexture: %d, %d; POT: %d, %d", bitmap.getWidth(), bitmap.getHeight(), w, h); + AphidLog.d("createTexture: %d, %d; POT: %d, %d", bitmap.getWidth(), bitmap.getHeight(), potW, potH); gl.glGenTextures(1, t.id, 0); @@ -66,15 +66,15 @@ public static Texture createTexture(Bitmap bitmap, FlipRenderer renderer, GL10 g switch (bitmap.getConfig()) { case ARGB_8888: - gl.glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, null); + gl.glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, potW, potH, 0, GL_RGBA, GL_UNSIGNED_BYTE, null); GLUtils.texSubImage2D(GL_TEXTURE_2D, 0, 0, 0, bitmap); break; case ARGB_4444: - gl.glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, null); + gl.glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, potW, potH, 0, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, null); GLUtils.texSubImage2D(GL_TEXTURE_2D, 0, 0, 0, bitmap); break; case RGB_565: - gl.glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, w, h, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, null); + gl.glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, potW, potH, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, null); GLUtils.texSubImage2D(GL_TEXTURE_2D, 0, 0, 0, bitmap); break; case ALPHA_8: diff --git a/FlipView/FlipLibrary/src/com/aphidmobile/flip/ViewDualCards.java b/FlipView/FlipLibrary/src/com/aphidmobile/flip/ViewDualCards.java index 4fccdda..87b5e77 100644 --- a/FlipView/FlipLibrary/src/com/aphidmobile/flip/ViewDualCards.java +++ b/FlipView/FlipLibrary/src/com/aphidmobile/flip/ViewDualCards.java @@ -53,8 +53,15 @@ public int getIndex() { public View getView() { return viewRef != null ? viewRef.get() : null; } + + synchronized void resetWithIndex(int index) { + this.index = index; + viewRef = null; + recycleScreenshot(); + recycleTexture(); + } - public synchronized boolean setView(int index, View view, Bitmap.Config format) { + synchronized boolean loadView(int index, View view, Bitmap.Config format) { UI.assertInMainThread(); if (this.index == index @@ -65,10 +72,7 @@ && getView() == view this.index = index; viewRef = null; - if (texture != null) { - texture.postDestroy(); - texture = null; - } + recycleTexture(); if (view != null) { viewRef = new WeakReference(view); recycleScreenshot(); @@ -80,16 +84,6 @@ && getView() == view return true; } - synchronized void markForceReload() { - UI.assertInMainThread(); - - recycleScreenshot(); - if (texture != null) { - texture.postDestroy(); - texture = null; - } - } - public Texture getTexture() { return texture; } @@ -191,4 +185,13 @@ private void recycleScreenshot() { UI.recycleBitmap(screenshot); screenshot = null; } + + private void recycleTexture() { + if (texture != null) { + texture.postDestroy(); + texture = null; + } + } + + } diff --git a/FlipView/FlipLibrary/src/com/aphidmobile/utils/AphidLog.java b/FlipView/FlipLibrary/src/com/aphidmobile/utils/AphidLog.java index 9e3962e..564a5e9 100644 --- a/FlipView/FlipLibrary/src/com/aphidmobile/utils/AphidLog.java +++ b/FlipView/FlipLibrary/src/com/aphidmobile/utils/AphidLog.java @@ -26,7 +26,7 @@ public class AphidLog { private AphidLog() { } - public static final String TAG = "OpenAphid"; + public static final String TAG = "FlipView"; /** * A little trick to reuse a formatter in the same thread