Merge change 26390 into eclair
* changes: Bring the dimples back, and make the "spin around" animation have a fling feeling.
This commit is contained in:
@@ -25,8 +25,9 @@ import android.util.AttributeSet;
|
|||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.MotionEvent;
|
import android.view.MotionEvent;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.SoundEffectConstants;
|
import android.view.VelocityTracker;
|
||||||
import android.view.animation.AccelerateInterpolator;
|
import android.view.ViewConfiguration;
|
||||||
|
import android.view.animation.DecelerateInterpolator;
|
||||||
import static android.view.animation.AnimationUtils.currentAnimationTimeMillis;
|
import static android.view.animation.AnimationUtils.currentAnimationTimeMillis;
|
||||||
import com.android.internal.R;
|
import com.android.internal.R;
|
||||||
|
|
||||||
@@ -60,16 +61,18 @@ public class RotarySelector extends View {
|
|||||||
private int mLeftHandleX;
|
private int mLeftHandleX;
|
||||||
private int mRightHandleX;
|
private int mRightHandleX;
|
||||||
|
|
||||||
// current offset of user's dragging
|
// current offset of rotary widget along the x axis
|
||||||
private int mTouchDragOffset = 0;
|
private int mRotaryOffsetX = 0;
|
||||||
|
|
||||||
// state of the animation used to bring the handle back to its start position when
|
// state of the animation used to bring the handle back to its start position when
|
||||||
// the user lets go before triggering an action
|
// the user lets go before triggering an action
|
||||||
private boolean mAnimating = false;
|
private boolean mAnimating = false;
|
||||||
private long mAnimationStartTime; // set to the end point of the animatino
|
private long mAnimationStartTime;
|
||||||
private long mAnimationDuration;
|
private long mAnimationDuration;
|
||||||
private int mAnimatingDeltaXStart; // the animation will interpolate from this delta down to zero
|
private int mAnimatingDeltaXStart; // the animation will interpolate from this delta to zero
|
||||||
private AccelerateInterpolator mInterpolator;
|
private int mAnimatingDeltaXEnd;
|
||||||
|
|
||||||
|
private DecelerateInterpolator mInterpolator;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If the user is currently dragging something.
|
* If the user is currently dragging something.
|
||||||
@@ -87,8 +90,8 @@ public class RotarySelector extends View {
|
|||||||
|
|
||||||
// Vibration (haptic feedback)
|
// Vibration (haptic feedback)
|
||||||
private Vibrator mVibrator;
|
private Vibrator mVibrator;
|
||||||
private static final long VIBRATE_SHORT = 60; // msec
|
private static final long VIBRATE_SHORT = 30; // msec
|
||||||
private static final long VIBRATE_LONG = 100; // msec
|
private static final long VIBRATE_LONG = 60; // msec
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The drawable for the arrows need to be scrunched this many dips towards the rotary bg below
|
* The drawable for the arrows need to be scrunched this many dips towards the rotary bg below
|
||||||
@@ -114,11 +117,27 @@ public class RotarySelector extends View {
|
|||||||
static final int SNAP_BACK_ANIMATION_DURATION_MILLIS = 300;
|
static final int SNAP_BACK_ANIMATION_DURATION_MILLIS = 300;
|
||||||
static final int SPIN_ANIMATION_DURATION_MILLIS = 800;
|
static final int SPIN_ANIMATION_DURATION_MILLIS = 800;
|
||||||
|
|
||||||
private static final boolean DRAW_CENTER_DIMPLE = false;
|
private static final boolean DRAW_CENTER_DIMPLE = true;
|
||||||
private int mEdgeTriggerThresh;
|
private int mEdgeTriggerThresh;
|
||||||
private int mDimpleWidth;
|
private int mDimpleWidth;
|
||||||
private int mBackgroundWidth;
|
private int mBackgroundWidth;
|
||||||
private int mBackgroundHeight;
|
private int mBackgroundHeight;
|
||||||
|
private final int mOuterRadius;
|
||||||
|
private final int mInnerRadius;
|
||||||
|
private int mDimpleSpacing;
|
||||||
|
|
||||||
|
private VelocityTracker mVelocityTracker;
|
||||||
|
private int mMinimumVelocity;
|
||||||
|
private int mMaximumVelocity;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The number of dimples we are flinging when we do the "spin" animation. Used to know when to
|
||||||
|
* wrap the icons back around so they "rotate back" onto the screen.
|
||||||
|
* @see #updateAnimation()
|
||||||
|
*/
|
||||||
|
private int mDimplesOfFling = 0;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public RotarySelector(Context context) {
|
public RotarySelector(Context context) {
|
||||||
this(context, null);
|
this(context, null);
|
||||||
@@ -152,7 +171,7 @@ public class RotarySelector extends View {
|
|||||||
mArrowLongLeft.setBounds(0, 0, arrowW, arrowH);
|
mArrowLongLeft.setBounds(0, 0, arrowW, arrowH);
|
||||||
mArrowLongRight.setBounds(0, 0, arrowW, arrowH);
|
mArrowLongRight.setBounds(0, 0, arrowW, arrowH);
|
||||||
|
|
||||||
mInterpolator = new AccelerateInterpolator();
|
mInterpolator = new DecelerateInterpolator(1f);
|
||||||
|
|
||||||
mEdgeTriggerThresh = (int) (mDensity * EDGE_TRIGGER_DIP);
|
mEdgeTriggerThresh = (int) (mDensity * EDGE_TRIGGER_DIP);
|
||||||
|
|
||||||
@@ -160,6 +179,23 @@ public class RotarySelector extends View {
|
|||||||
|
|
||||||
mBackgroundWidth = mBackground.getIntrinsicWidth();
|
mBackgroundWidth = mBackground.getIntrinsicWidth();
|
||||||
mBackgroundHeight = mBackground.getIntrinsicHeight();
|
mBackgroundHeight = mBackground.getIntrinsicHeight();
|
||||||
|
mOuterRadius = (int) (mDensity * OUTER_ROTARY_RADIUS_DIP);
|
||||||
|
mInnerRadius = (int) ((OUTER_ROTARY_RADIUS_DIP - ROTARY_STROKE_WIDTH_DIP) * mDensity);
|
||||||
|
|
||||||
|
final ViewConfiguration configuration = ViewConfiguration.get(mContext);
|
||||||
|
mMinimumVelocity = configuration.getScaledMinimumFlingVelocity() * 2;
|
||||||
|
mMaximumVelocity = configuration.getScaledMaximumFlingVelocity();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
|
||||||
|
super.onSizeChanged(w, h, oldw, oldh);
|
||||||
|
|
||||||
|
mLeftHandleX = (int) (EDGE_PADDING_DIP * mDensity) + mDimpleWidth / 2;
|
||||||
|
mRightHandleX =
|
||||||
|
getWidth() - (int) (EDGE_PADDING_DIP * mDensity) - mDimpleWidth / 2;
|
||||||
|
|
||||||
|
mDimpleSpacing = (getWidth() / 2) - mLeftHandleX;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -229,43 +265,21 @@ public class RotarySelector extends View {
|
|||||||
setMeasuredDimension(width, backgroundH + arrowH - arrowScrunch);
|
setMeasuredDimension(width, backgroundH + arrowH - arrowScrunch);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
|
|
||||||
super.onSizeChanged(w, h, oldw, oldh);
|
|
||||||
|
|
||||||
mLeftHandleX = (int) (EDGE_PADDING_DIP * mDensity) + mDimpleWidth / 2;
|
|
||||||
mRightHandleX =
|
|
||||||
getWidth() - (int) (EDGE_PADDING_DIP * mDensity) - mDimpleWidth / 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
// private Paint mPaint = new Paint();
|
// private Paint mPaint = new Paint();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onDraw(Canvas canvas) {
|
protected void onDraw(Canvas canvas) {
|
||||||
super.onDraw(canvas);
|
super.onDraw(canvas);
|
||||||
if (DBG) {
|
if (DBG) {
|
||||||
log(String.format("onDraw: mAnimating=%s, mTouchDragOffset=%d, mGrabbedState=%d",
|
log(String.format("onDraw: mAnimating=%s, mRotaryOffsetX=%d, mGrabbedState=%d",
|
||||||
mAnimating, mTouchDragOffset, mGrabbedState));
|
mAnimating, mRotaryOffsetX, mGrabbedState));
|
||||||
}
|
}
|
||||||
|
|
||||||
final int height = getHeight();
|
final int height = getHeight();
|
||||||
|
|
||||||
// update animating state before we draw anything
|
// update animating state before we draw anything
|
||||||
if (mAnimating) {
|
if (mAnimating) {
|
||||||
final long millisSoFar = currentAnimationTimeMillis() - mAnimationStartTime;
|
updateAnimation();
|
||||||
final long millisLeft = mAnimationDuration - millisSoFar;
|
|
||||||
if (DBG) log("millisleft for animating: " + millisLeft);
|
|
||||||
if (millisLeft <= 0) {
|
|
||||||
reset();
|
|
||||||
} else {
|
|
||||||
// we always use the snap back duration as the denominator for interpolation
|
|
||||||
// to get a consistent velocity (bascially this makes us happy for the snap back
|
|
||||||
// and the spin around one).
|
|
||||||
final long denom = SNAP_BACK_ANIMATION_DURATION_MILLIS; // mAnimationDuration
|
|
||||||
float interpolation = mInterpolator.getInterpolation(
|
|
||||||
(float) millisLeft / denom);
|
|
||||||
mTouchDragOffset = (int) (mAnimatingDeltaXStart * interpolation);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Background:
|
// Background:
|
||||||
@@ -302,16 +316,13 @@ public class RotarySelector extends View {
|
|||||||
// float or = OUTER_ROTARY_RADIUS_DIP * mDensity;
|
// float or = OUTER_ROTARY_RADIUS_DIP * mDensity;
|
||||||
// canvas.drawCircle(getWidth() / 2, or + mBackground.getBounds().top, or, mPaint);
|
// canvas.drawCircle(getWidth() / 2, or + mBackground.getBounds().top, or, mPaint);
|
||||||
|
|
||||||
final int outerRadius = (int) (mDensity * OUTER_ROTARY_RADIUS_DIP);
|
|
||||||
final int innerRadius =
|
|
||||||
(int) ((OUTER_ROTARY_RADIUS_DIP - ROTARY_STROKE_WIDTH_DIP) * mDensity);
|
|
||||||
final int bgTop = mBackground.getBounds().top;
|
final int bgTop = mBackground.getBounds().top;
|
||||||
{
|
{
|
||||||
final int xOffset = mLeftHandleX + mTouchDragOffset;
|
final int xOffset = mLeftHandleX + mRotaryOffsetX;
|
||||||
final int drawableY = getYOnArc(
|
final int drawableY = getYOnArc(
|
||||||
mBackground,
|
mBackground,
|
||||||
innerRadius,
|
mInnerRadius,
|
||||||
outerRadius,
|
mOuterRadius,
|
||||||
xOffset);
|
xOffset);
|
||||||
|
|
||||||
drawCentered(mDimple, canvas, xOffset, drawableY + bgTop);
|
drawCentered(mDimple, canvas, xOffset, drawableY + bgTop);
|
||||||
@@ -321,22 +332,22 @@ public class RotarySelector extends View {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (DRAW_CENTER_DIMPLE) {
|
if (DRAW_CENTER_DIMPLE) {
|
||||||
final int xOffset = getWidth() / 2 + mTouchDragOffset;
|
final int xOffset = getWidth() / 2 + mRotaryOffsetX;
|
||||||
final int drawableY = getYOnArc(
|
final int drawableY = getYOnArc(
|
||||||
mBackground,
|
mBackground,
|
||||||
innerRadius,
|
mInnerRadius,
|
||||||
outerRadius,
|
mOuterRadius,
|
||||||
xOffset);
|
xOffset);
|
||||||
|
|
||||||
drawCentered(mDimple, canvas, xOffset, drawableY + bgTop);
|
drawCentered(mDimple, canvas, xOffset, drawableY + bgTop);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
final int xOffset = mRightHandleX + mTouchDragOffset;
|
final int xOffset = mRightHandleX + mRotaryOffsetX;
|
||||||
final int drawableY = getYOnArc(
|
final int drawableY = getYOnArc(
|
||||||
mBackground,
|
mBackground,
|
||||||
innerRadius,
|
mInnerRadius,
|
||||||
outerRadius,
|
mOuterRadius,
|
||||||
xOffset);
|
xOffset);
|
||||||
|
|
||||||
drawCentered(mDimple, canvas, xOffset, drawableY + bgTop);
|
drawCentered(mDimple, canvas, xOffset, drawableY + bgTop);
|
||||||
@@ -345,7 +356,33 @@ public class RotarySelector extends View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mAnimating) invalidate();
|
// draw extra left hand dimples
|
||||||
|
int dimpleLeft = mRotaryOffsetX + mLeftHandleX - mDimpleSpacing;
|
||||||
|
final int halfdimple = mDimpleWidth / 2;
|
||||||
|
while (dimpleLeft > -halfdimple) {
|
||||||
|
final int drawableY = getYOnArc(
|
||||||
|
mBackground,
|
||||||
|
mInnerRadius,
|
||||||
|
mOuterRadius,
|
||||||
|
dimpleLeft);
|
||||||
|
|
||||||
|
drawCentered(mDimple, canvas, dimpleLeft, drawableY + bgTop);
|
||||||
|
dimpleLeft -= mDimpleSpacing;
|
||||||
|
}
|
||||||
|
|
||||||
|
// draw extra right hand dimples
|
||||||
|
int dimpleRight = mRotaryOffsetX + mRightHandleX + mDimpleSpacing;
|
||||||
|
final int rightThresh = mRight + halfdimple;
|
||||||
|
while (dimpleRight < rightThresh) {
|
||||||
|
final int drawableY = getYOnArc(
|
||||||
|
mBackground,
|
||||||
|
mInnerRadius,
|
||||||
|
mOuterRadius,
|
||||||
|
dimpleRight);
|
||||||
|
|
||||||
|
drawCentered(mDimple, canvas, dimpleRight, drawableY + bgTop);
|
||||||
|
dimpleRight += mDimpleSpacing;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -395,6 +432,11 @@ public class RotarySelector extends View {
|
|||||||
if (mAnimating) {
|
if (mAnimating) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
if (mVelocityTracker == null) {
|
||||||
|
mVelocityTracker = VelocityTracker.obtain();
|
||||||
|
}
|
||||||
|
mVelocityTracker.addMovement(event);
|
||||||
|
|
||||||
|
|
||||||
final int eventX = (int) event.getX();
|
final int eventX = (int) event.getX();
|
||||||
final int hitWindow = mDimpleWidth;
|
final int hitWindow = mDimpleWidth;
|
||||||
@@ -409,12 +451,12 @@ public class RotarySelector extends View {
|
|||||||
invalidate();
|
invalidate();
|
||||||
}
|
}
|
||||||
if (eventX < mLeftHandleX + hitWindow) {
|
if (eventX < mLeftHandleX + hitWindow) {
|
||||||
mTouchDragOffset = eventX - mLeftHandleX;
|
mRotaryOffsetX = eventX - mLeftHandleX;
|
||||||
mGrabbedState = LEFT_HANDLE_GRABBED;
|
mGrabbedState = LEFT_HANDLE_GRABBED;
|
||||||
invalidate();
|
invalidate();
|
||||||
vibrate(VIBRATE_SHORT);
|
vibrate(VIBRATE_SHORT);
|
||||||
} else if (eventX > mRightHandleX - hitWindow) {
|
} else if (eventX > mRightHandleX - hitWindow) {
|
||||||
mTouchDragOffset = eventX - mRightHandleX;
|
mRotaryOffsetX = eventX - mRightHandleX;
|
||||||
mGrabbedState = RIGHT_HANDLE_GRABBED;
|
mGrabbedState = RIGHT_HANDLE_GRABBED;
|
||||||
invalidate();
|
invalidate();
|
||||||
vibrate(VIBRATE_SHORT);
|
vibrate(VIBRATE_SHORT);
|
||||||
@@ -424,35 +466,38 @@ public class RotarySelector extends View {
|
|||||||
case MotionEvent.ACTION_MOVE:
|
case MotionEvent.ACTION_MOVE:
|
||||||
if (DBG) log("touch-move");
|
if (DBG) log("touch-move");
|
||||||
if (mGrabbedState == LEFT_HANDLE_GRABBED) {
|
if (mGrabbedState == LEFT_HANDLE_GRABBED) {
|
||||||
mTouchDragOffset = eventX - mLeftHandleX;
|
mRotaryOffsetX = eventX - mLeftHandleX;
|
||||||
invalidate();
|
invalidate();
|
||||||
if (eventX >= getRight() - mEdgeTriggerThresh && !mTriggered) {
|
if (eventX >= getRight() - mEdgeTriggerThresh && !mTriggered) {
|
||||||
mTriggered = true;
|
mTriggered = true;
|
||||||
dispatchTriggerEvent(OnDialTriggerListener.LEFT_HANDLE);
|
dispatchTriggerEvent(OnDialTriggerListener.LEFT_HANDLE);
|
||||||
// set up "spin around animation"
|
final VelocityTracker velocityTracker = mVelocityTracker;
|
||||||
mAnimating = true;
|
velocityTracker.computeCurrentVelocity(1000, mMaximumVelocity);
|
||||||
mAnimationStartTime = currentAnimationTimeMillis();
|
final int velocity = Math.max(mMinimumVelocity, (int) velocityTracker.getXVelocity());
|
||||||
mAnimationDuration = SPIN_ANIMATION_DURATION_MILLIS;
|
mDimplesOfFling = Math.max(
|
||||||
mAnimatingDeltaXStart = -mBackgroundWidth*3;
|
8,
|
||||||
mTouchDragOffset = 0;
|
Math.abs(velocity / mDimpleSpacing));
|
||||||
mGrabbedState = NOTHING_GRABBED;
|
startAnimationWithVelocity(
|
||||||
invalidate();
|
eventX - mLeftHandleX,
|
||||||
|
mDimplesOfFling * mDimpleSpacing,
|
||||||
|
velocity);
|
||||||
}
|
}
|
||||||
} else if (mGrabbedState == RIGHT_HANDLE_GRABBED) {
|
} else if (mGrabbedState == RIGHT_HANDLE_GRABBED) {
|
||||||
mTouchDragOffset = eventX - mRightHandleX;
|
mRotaryOffsetX = eventX - mRightHandleX;
|
||||||
invalidate();
|
invalidate();
|
||||||
if (eventX <= mEdgeTriggerThresh && !mTriggered) {
|
if (eventX <= mEdgeTriggerThresh && !mTriggered) {
|
||||||
mTriggered = true;
|
mTriggered = true;
|
||||||
dispatchTriggerEvent(OnDialTriggerListener.RIGHT_HANDLE);
|
dispatchTriggerEvent(OnDialTriggerListener.RIGHT_HANDLE);
|
||||||
// set up "spin around animation"
|
final VelocityTracker velocityTracker = mVelocityTracker;
|
||||||
mAnimating = true;
|
velocityTracker.computeCurrentVelocity(1000, mMaximumVelocity);
|
||||||
mAnimationStartTime = currentAnimationTimeMillis();
|
final int velocity = Math.min(-mMinimumVelocity, (int) velocityTracker.getXVelocity());
|
||||||
mAnimationDuration = SPIN_ANIMATION_DURATION_MILLIS;
|
mDimplesOfFling = Math.max(
|
||||||
mAnimatingDeltaXStart = mBackgroundWidth*3;
|
8,
|
||||||
mTouchDragOffset = 0;
|
Math.abs(velocity / mDimpleSpacing));
|
||||||
mGrabbedState = NOTHING_GRABBED;
|
startAnimationWithVelocity(
|
||||||
invalidate();
|
eventX - mRightHandleX,
|
||||||
|
-(mDimplesOfFling * mDimpleSpacing),
|
||||||
|
velocity);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -462,35 +507,84 @@ public class RotarySelector extends View {
|
|||||||
if (mGrabbedState == LEFT_HANDLE_GRABBED
|
if (mGrabbedState == LEFT_HANDLE_GRABBED
|
||||||
&& Math.abs(eventX - mLeftHandleX) > 5) {
|
&& Math.abs(eventX - mLeftHandleX) > 5) {
|
||||||
// set up "snap back" animation
|
// set up "snap back" animation
|
||||||
mAnimating = true;
|
startAnimation(eventX - mLeftHandleX, 0, SNAP_BACK_ANIMATION_DURATION_MILLIS);
|
||||||
mAnimationStartTime = currentAnimationTimeMillis();
|
|
||||||
mAnimationDuration = SNAP_BACK_ANIMATION_DURATION_MILLIS;
|
|
||||||
mAnimatingDeltaXStart = eventX - mLeftHandleX;
|
|
||||||
} else if (mGrabbedState == RIGHT_HANDLE_GRABBED
|
} else if (mGrabbedState == RIGHT_HANDLE_GRABBED
|
||||||
&& Math.abs(eventX - mRightHandleX) > 5) {
|
&& Math.abs(eventX - mRightHandleX) > 5) {
|
||||||
// set up "snap back" animation
|
// set up "snap back" animation
|
||||||
mAnimating = true;
|
startAnimation(eventX - mRightHandleX, 0, SNAP_BACK_ANIMATION_DURATION_MILLIS);
|
||||||
mAnimationStartTime = currentAnimationTimeMillis();
|
|
||||||
mAnimationDuration = SNAP_BACK_ANIMATION_DURATION_MILLIS;
|
|
||||||
mAnimatingDeltaXStart = eventX - mRightHandleX;
|
|
||||||
}
|
}
|
||||||
|
mRotaryOffsetX = 0;
|
||||||
mTouchDragOffset = 0;
|
|
||||||
mGrabbedState = NOTHING_GRABBED;
|
mGrabbedState = NOTHING_GRABBED;
|
||||||
invalidate();
|
invalidate();
|
||||||
|
if (mVelocityTracker != null) {
|
||||||
|
mVelocityTracker.recycle(); // wishin' we had generational GC
|
||||||
|
mVelocityTracker = null;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case MotionEvent.ACTION_CANCEL:
|
case MotionEvent.ACTION_CANCEL:
|
||||||
if (DBG) log("touch-cancel");
|
if (DBG) log("touch-cancel");
|
||||||
reset();
|
reset();
|
||||||
invalidate();
|
invalidate();
|
||||||
|
if (mVelocityTracker != null) {
|
||||||
|
mVelocityTracker.recycle();
|
||||||
|
mVelocityTracker = null;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void startAnimation(int startX, int endX, int duration) {
|
||||||
|
mAnimating = true;
|
||||||
|
mAnimationStartTime = currentAnimationTimeMillis();
|
||||||
|
mAnimationDuration = duration;
|
||||||
|
mAnimatingDeltaXStart = startX;
|
||||||
|
mAnimatingDeltaXEnd = endX;
|
||||||
|
mGrabbedState = NOTHING_GRABBED;
|
||||||
|
mDimplesOfFling = 0;
|
||||||
|
invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void startAnimationWithVelocity(int startX, int endX, int pixelsPerSecond) {
|
||||||
|
mAnimating = true;
|
||||||
|
mAnimationStartTime = currentAnimationTimeMillis();
|
||||||
|
mAnimationDuration = 1000 * (endX - startX) / pixelsPerSecond;
|
||||||
|
mAnimatingDeltaXStart = startX;
|
||||||
|
mAnimatingDeltaXEnd = endX;
|
||||||
|
mGrabbedState = NOTHING_GRABBED;
|
||||||
|
invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateAnimation() {
|
||||||
|
final long millisSoFar = currentAnimationTimeMillis() - mAnimationStartTime;
|
||||||
|
final long millisLeft = mAnimationDuration - millisSoFar;
|
||||||
|
final int totalDeltaX = mAnimatingDeltaXStart - mAnimatingDeltaXEnd;
|
||||||
|
if (DBG) log("millisleft for animating: " + millisLeft);
|
||||||
|
if (millisLeft <= 0) {
|
||||||
|
reset();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// from 0 to 1 as animation progresses
|
||||||
|
float interpolation =
|
||||||
|
mInterpolator.getInterpolation((float) millisSoFar / mAnimationDuration);
|
||||||
|
final int dx = (int) (totalDeltaX * (1 - interpolation));
|
||||||
|
mRotaryOffsetX = mAnimatingDeltaXEnd + dx;
|
||||||
|
if (mDimplesOfFling > 0) {
|
||||||
|
if (mRotaryOffsetX < 4 * mDimpleSpacing) {
|
||||||
|
// wrap around on fling left
|
||||||
|
mRotaryOffsetX += (4 + mDimplesOfFling - 4) * mDimpleSpacing;
|
||||||
|
} else if (mRotaryOffsetX > 4 * mDimpleSpacing) {
|
||||||
|
// wrap around on fling right
|
||||||
|
mRotaryOffsetX -= (4 + mDimplesOfFling - 4) * mDimpleSpacing;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
private void reset() {
|
private void reset() {
|
||||||
mAnimating = false;
|
mAnimating = false;
|
||||||
mTouchDragOffset = 0;
|
mRotaryOffsetX = 0;
|
||||||
|
mDimplesOfFling = 0;
|
||||||
mGrabbedState = NOTHING_GRABBED;
|
mGrabbedState = NOTHING_GRABBED;
|
||||||
mTriggered = false;
|
mTriggered = false;
|
||||||
}
|
}
|
||||||
@@ -500,7 +594,8 @@ public class RotarySelector extends View {
|
|||||||
*/
|
*/
|
||||||
private synchronized void vibrate(long duration) {
|
private synchronized void vibrate(long duration) {
|
||||||
if (mVibrator == null) {
|
if (mVibrator == null) {
|
||||||
mVibrator = (android.os.Vibrator) getContext().getSystemService(Context.VIBRATOR_SERVICE);
|
mVibrator = (android.os.Vibrator)
|
||||||
|
getContext().getSystemService(Context.VIBRATOR_SERVICE);
|
||||||
}
|
}
|
||||||
mVibrator.vibrate(duration);
|
mVibrator.vibrate(duration);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user