summaryrefslogtreecommitdiffstats
path: root/carousel
diff options
context:
space:
mode:
authorJim Miller <jaggies@google.com>2011-03-01 19:28:50 -0800
committerJim Miller <jaggies@google.com>2011-03-02 16:06:23 -0800
commitceae13b8f2ae7342506ecb4e4fcce956dbb12af7 (patch)
tree9bd07a15ff3de57907f5bf73c3494f510044640e /carousel
parentb4959ac31abdaf6ab7309c17f56fceaa1baabed7 (diff)
downloadandroid_frameworks_ex-ceae13b8f2ae7342506ecb4e4fcce956dbb12af7.tar.gz
android_frameworks_ex-ceae13b8f2ae7342506ecb4e4fcce956dbb12af7.tar.bz2
android_frameworks_ex-ceae13b8f2ae7342506ecb4e4fcce956dbb12af7.zip
Fix 3404464: Add scale-down animation to Carousel
This changes the behavior to avoid snapping back to the original size, which was a very jarring effect. Instead, Carousel now has a scale-down animation that is triggered when the user releases the item. Change-Id: I81a91e65d0da991a98211f2ecb92fa89c8c81e22
Diffstat (limited to 'carousel')
-rw-r--r--carousel/java/com/android/ex/carousel/carousel.rs80
-rw-r--r--carousel/test/src/com/android/carouseltest/MyCarouselView.java5
2 files changed, 55 insertions, 30 deletions
diff --git a/carousel/java/com/android/ex/carousel/carousel.rs b/carousel/java/com/android/ex/carousel/carousel.rs
index 84f8ab3..49ef785 100644
--- a/carousel/java/com/android/ex/carousel/carousel.rs
+++ b/carousel/java/com/android/ex/carousel/carousel.rs
@@ -148,9 +148,10 @@ static const int DRAG_MODEL_CYLINDER_INSIDE = 2; // Drag relative to point on in
static const int DRAG_MODEL_CYLINDER_OUTSIDE = 3; // Drag relative to point on outside of cylinder
// Constants
-static const int ANIMATION_DELAY_TIME = 100; // hold off scale animation until this time
-static const int ANIMATION_SCALE_TIME = 200; // Time it takes to animate selected card, in ms
-static const float3 SELECTED_SCALE_FACTOR = { 0.0f, 0.0f, 0.0f }; // increase by this %
+static const int ANIMATION_DELAY_TIME = 125; // hold off scale animation until this time
+static const int ANIMATION_SCALE_UP_TIME = 200; // Time it takes to animate selected card, in ms
+static const int ANIMATION_SCALE_DOWN_TIME = 400; // Time it takes to animate selected card, in ms
+static const float3 SELECTED_SCALE_FACTOR = { 0.1f, 0.1f, 0.1f }; // increase by this %
static const float OVERSCROLL_SLOTS = 1.0f; // amount of allowed overscroll (in slots)
static const int VELOCITY_HISTORY_MAX = 10; // # recent velocity samples used to calculate average
static const int VISIBLE_SLOT_PADDING = 2; // # slots to draw on either side of visible slots
@@ -220,12 +221,13 @@ static bool updateCamera; // force a recompute of projection and lookat matri
static const float FLT_MAX = 1.0e37;
static int animatedSelection = -1;
static int currentFirstCard = -1;
-static int64_t touchTime = -1; // time of first touch (see doStart())
+static int64_t touchTime = -1; // time of first touch (see doStart())
+static int64_t releaseTime = 0L; // when touch was released
static float touchBias = 0.0f; // bias on first touch
static float2 touchPosition; // position of first touch, as defined by last call to doStart(x,y)
static float velocity = 0.0f; // angular velocity in radians/s
-static bool overscroll = false; // whether we're in the overscroll animation
-static bool autoscrolling = false; // whether we're in the autoscroll animation
+static bool isOverScrolling = false; // whether we're in the overscroll animation
+static bool isAutoScrolling = false; // whether we're in the autoscroll animation
static bool isDragging = false; // true while the user is dragging the carousel
static float selectionRadius = 50.0f; // movement greater than this will result in no selection
static bool enableSelection = false; // enabled until the user drags outside of selectionRadius
@@ -358,7 +360,7 @@ void createCards(int start, int total)
// this method.
cardAllocationValid = total > 0;
- updateAllocationVars(cards);
+ updateAllocationVars();
}
// Computes an alpha value for a card using elapsed time and constant fadeInDuration
@@ -564,16 +566,31 @@ void setCarouselRotationAngle(float carouselRotationAngle) {
// If card is currently being animated, returns true, otherwise returns false.
static bool getAnimatedScaleForSelected(float3* scale)
{
- const float3 one = { 1.0f, 1.0f, 1.0f };
- int64_t dt = rsUptimeMillis() - touchTime;
- if (dt >= ANIMATION_DELAY_TIME) {
- float fraction = (float) (dt - ANIMATION_DELAY_TIME) / ANIMATION_SCALE_TIME;
- fraction = min(fraction, 1.0f);
- *scale = one + fraction * SELECTED_SCALE_FACTOR;
+ static const float3 one = { 1.0f, 1.0f, 1.0f };
+ static float fraction = 0.0f;
+ bool stillAnimating = false;
+ if (isDragging) {
+ // "scale up" animation
+ int64_t dt = rsUptimeMillis() - touchTime - ANIMATION_DELAY_TIME;
+ if (dt > 0L && enableSelection) {
+ float s = (float) dt / ANIMATION_SCALE_UP_TIME;
+ s = min(s, 1.0f);
+ fraction = max(s, fraction);
+ }
+ stillAnimating = dt < ANIMATION_SCALE_UP_TIME;
} else {
- *scale = one;
+ // "scale down" animation
+ int64_t dt = rsUptimeMillis() - releaseTime;
+ if (dt < ANIMATION_SCALE_DOWN_TIME) {
+ float s = 1.0f - ((float) dt / ANIMATION_SCALE_DOWN_TIME);
+ fraction = min(s, fraction);
+ stillAnimating = true;
+ } else {
+ fraction = 0.0f;
+ }
}
- return dt < (ANIMATION_DELAY_TIME + ANIMATION_SCALE_TIME); // still animating;
+ *scale = one + fraction * SELECTED_SCALE_FACTOR;
+ return stillAnimating; // still animating;
}
// The Verhulst logistic function: http://en.wikipedia.org/wiki/Logistic_function
@@ -635,7 +652,7 @@ static bool getMatrixForCard(rs_matrix4x4* matrix, int i, bool enableSway, bool
}
rsMatrixRotate(matrix, degrees(rotation), 0, 1, 0);
bool stillAnimating = false;
- if (i == animatedSelection && enableSelection) {
+ if (i == animatedSelection) {
float3 scale;
stillAnimating = getAnimatedScaleForSelected(&scale);
rsMatrixScale(matrix, scale.x, scale.y, scale.z);
@@ -1099,10 +1116,11 @@ void doStart(float x, float y, long eventTime)
velocityHistory[0] = 0.0f;
velocityHistoryCount = 0;
+ releaseTime = lastTime; // used to disable scale down animation - any time in the past will do
touchTime = lastTime = eventTime;
touchBias = bias;
isDragging = true;
- overscroll = false;
+ isOverScrolling = false;
animatedSelection = doSelection(x, y); // used to provide visual feedback on touch
stopAutoscroll();
}
@@ -1123,7 +1141,9 @@ static float computeAverageVelocityFromHistory()
void doStop(float x, float y, long eventTime)
{
- updateAllocationVars(cards);
+ updateAllocationVars();
+
+ releaseTime = rsUptimeMillis();
if (enableSelection) {
int data[3];
@@ -1157,7 +1177,7 @@ void doStop(float x, float y, long eventTime)
void doLongPress()
{
int64_t currentTime = rsUptimeMillis();
- updateAllocationVars(cards);
+ updateAllocationVars();
// Selection happens for most recent position detected in doMotion()
if (enableSelection && animatedSelection != -1) {
if (debugSelection) rsDebug("doLongPress(), selection = ", animatedSelection);
@@ -1233,7 +1253,7 @@ void setCarouselRotationAngle2(
}
animating = true;
- autoscrolling = true;
+ isAutoScrolling = true;
autoscrollDuration = milliseconds;
autoscrollInterpolationMode = interpolationMode;
autoscrollStartAngle = carouselRotationAngleToRadians(actualStart);
@@ -1246,13 +1266,13 @@ void setCarouselRotationAngle2(
autoscrollStopAngle = clamp(autoscrollStopAngle, lowBias, highBias);
//stop other animation kinds
- overscroll = false;
+ isOverScrolling = false;
velocity = 0.0f;
}
static void stopAutoscroll()
{
- autoscrolling = false;
+ isAutoScrolling = false;
autoscrollStartTime = 0L; //reset for next time
}
@@ -1559,7 +1579,7 @@ static bool updateNextPosition(int64_t currentTime)
const float highBias = maximumBias();
const float lowBias = minimumBias();
bool stillAnimating = false;
- if (overscroll) {
+ if (isOverScrolling) {
if (bias > highBias) {
bias -= 4.0f * dt * easeOut((bias - highBias) * 2.0f);
if (fabs(bias - highBias) < biasMin) {
@@ -1575,14 +1595,14 @@ static bool updateNextPosition(int64_t currentTime)
stillAnimating = true;
}
} else {
- overscroll = false;
+ isOverScrolling = false;
}
- } else if (autoscrolling) {
+ } else if (isAutoScrolling) {
stillAnimating = doAutoscroll(currentTime);
} else {
stillAnimating = doPhysics(dt);
- overscroll = bias > highBias || bias < lowBias;
- if (overscroll) {
+ isOverScrolling = bias > highBias || bias < lowBias;
+ if (isOverScrolling) {
velocity = 0.0f; // prevent bouncing due to v > 0 after overscroll animation.
}
}
@@ -1590,7 +1610,7 @@ static bool updateNextPosition(int64_t currentTime)
highBias + wedgeAngle(OVERSCROLL_SLOTS));
if (newbias != bias) { // we clamped
velocity = 0.0f;
- overscroll = true;
+ isOverScrolling = true;
}
bias = newbias;
return stillAnimating;
@@ -1776,7 +1796,7 @@ int root() {
rsgBindSampler(multiTextureFragmentProgram, 0, linearClamp);
rsgBindSampler(multiTextureFragmentProgram, 1, linearClamp);
- updateAllocationVars(cards);
+ updateAllocationVars();
rsgBindProgramFragment(singleTextureFragmentProgram);
// rsgClearDepth() currently follows the value of glDepthMask(), so it's disabled when
@@ -1788,7 +1808,7 @@ int root() {
updateCameraMatrix(rsgGetWidth(), rsgGetHeight());
- bool stillAnimating = (currentTime - touchTime) <= ANIMATION_SCALE_TIME;
+ bool stillAnimating = (currentTime - touchTime) <= ANIMATION_SCALE_UP_TIME;
if (!isDragging && animating) {
stillAnimating = updateNextPosition(currentTime);
diff --git a/carousel/test/src/com/android/carouseltest/MyCarouselView.java b/carousel/test/src/com/android/carouseltest/MyCarouselView.java
index f028e6c..973a9bc 100644
--- a/carousel/test/src/com/android/carouseltest/MyCarouselView.java
+++ b/carousel/test/src/com/android/carouseltest/MyCarouselView.java
@@ -41,4 +41,9 @@ public class MyCarouselView extends CarouselView {
return new Info(R.raw.carousel);
}
+ @Override
+ public boolean interpretLongPressEvents() {
+ return true;
+ }
+
}