diff options
author | The Android Open Source Project <initial-contribution@android.com> | 2009-02-20 07:38:31 -0800 |
---|---|---|
committer | The Android Open Source Project <initial-contribution@android.com> | 2009-02-20 07:38:31 -0800 |
commit | 15ab3eae2ec3d73b3e8aa60b33ae41445bf83f4b (patch) | |
tree | d03d027a7ed97af616904e02a7b420babf40d44f /core/java/android/widget | |
parent | 3001a035439d8134a7d70d796376d1dfbff3cdcd (diff) | |
download | frameworks_base-15ab3eae2ec3d73b3e8aa60b33ae41445bf83f4b.zip frameworks_base-15ab3eae2ec3d73b3e8aa60b33ae41445bf83f4b.tar.gz frameworks_base-15ab3eae2ec3d73b3e8aa60b33ae41445bf83f4b.tar.bz2 |
auto import from //branches/cupcake/...@132569
Diffstat (limited to 'core/java/android/widget')
-rw-r--r-- | core/java/android/widget/Adapter.java | 2 | ||||
-rw-r--r-- | core/java/android/widget/TextView.java | 16 | ||||
-rw-r--r-- | core/java/android/widget/ZoomRing.java | 113 | ||||
-rw-r--r-- | core/java/android/widget/ZoomRingController.java | 82 |
4 files changed, 150 insertions, 63 deletions
diff --git a/core/java/android/widget/Adapter.java b/core/java/android/widget/Adapter.java index e952dd5..f2b3e2a 100644 --- a/core/java/android/widget/Adapter.java +++ b/core/java/android/widget/Adapter.java @@ -116,7 +116,7 @@ public interface Adapter { * can be converted to the other in {@link #getView}. Note: Integers must be in the * range 0 to {@link #getViewTypeCount} - 1. {@link #IGNORE_ITEM_VIEW_TYPE} can * also be returned. - * @see IGNORE_ITEM_VIEW_TYPE + * @see #IGNORE_ITEM_VIEW_TYPE */ int getItemViewType(int position); diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java index bdc54ff..c852be5 100644 --- a/core/java/android/widget/TextView.java +++ b/core/java/android/widget/TextView.java @@ -4132,8 +4132,20 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener removeParcelableSpans(content, start, end); content.replace(start, end, text.text); } - Selection.setSelection((Spannable)getText(), - text.selectionStart, text.selectionEnd); + + // Now set the selection position... make sure it is in range, to + // avoid crashes. If this is a partial update, it is possible that + // the underlying text may have changed, causing us problems here. + // Also we just don't want to trust clients to do the right thing. + Spannable sp = (Spannable)getText(); + final int N = sp.length(); + int start = text.selectionStart; + if (start < 0) start = 0; + else if (start > N) start = N; + int end = text.selectionEnd; + if (end < 0) end = 0; + else if (end > N) end = N; + Selection.setSelection(sp, start, end); } /** diff --git a/core/java/android/widget/ZoomRing.java b/core/java/android/widget/ZoomRing.java index 22881b3..a29e1a0 100644 --- a/core/java/android/widget/ZoomRing.java +++ b/core/java/android/widget/ZoomRing.java @@ -84,6 +84,10 @@ public class ZoomRing extends View { private Drawable mThumbPlusArrowDrawable; /** Shown beneath the thumb if we can still zoom out. */ private Drawable mThumbMinusArrowDrawable; + private static final int THUMB_ARROW_PLUS = 1 << 0; + private static final int THUMB_ARROW_MINUS = 1 << 1; + /** Bitwise-OR of {@link #THUMB_ARROW_MINUS} and {@link #THUMB_ARROW_PLUS} */ + private int mThumbArrowsToDraw; private static final int THUMB_ARROWS_FADE_DURATION = 300; private long mThumbArrowsFadeStartTime; private int mThumbArrowsAlpha = 255; @@ -166,7 +170,7 @@ public class ZoomRing extends View { // TODO: add padding to drawable setBackgroundResource(R.drawable.zoom_ring_track); // TODO get from style - setRingBounds(30, Integer.MAX_VALUE); + setRingBounds(43, Integer.MAX_VALUE); mThumbHalfHeight = mThumbDrawable.getIntrinsicHeight() / 2; mThumbHalfWidth = mThumbDrawable.getIntrinsicWidth() / 2; @@ -276,7 +280,7 @@ public class ZoomRing extends View { thumbCenterX + mThumbHalfWidth, thumbCenterY + mThumbHalfHeight); - if (mThumbArrowsAlpha > 0) { + if (mThumbArrowsToDraw > 0) { setThumbArrowsAngle(angle); } @@ -420,12 +424,15 @@ public class ZoomRing extends View { switch (action) { case MotionEvent.ACTION_DOWN: - mCallback.onUserInteractionStarted(); - if (time - mPreviousUpTime <= DOUBLE_TAP_DISMISS_TIMEOUT) { mCallback.onZoomRingDismissed(true); + onTouchUp(time); + + // Dismissing, so halt here + return true; } + mCallback.onUserInteractionStarted(); mPreviousDownX = x; mPreviousDownY = y; resetState(); @@ -441,23 +448,7 @@ public class ZoomRing extends View { case MotionEvent.ACTION_CANCEL: case MotionEvent.ACTION_UP: - if (mMode == MODE_MOVE_ZOOM_RING || mMode == MODE_WAITING_FOR_MOVE_ZOOM_RING) { - mCallback.onZoomRingSetMovableHintVisible(false); - if (mMode == MODE_MOVE_ZOOM_RING) { - mCallback.onZoomRingMovingStopped(); - } - } else if (mMode == MODE_DRAG_THUMB || mMode == MODE_TAP_DRAG || - mMode == MODE_WAITING_FOR_DRAG_THUMB) { - onThumbDragStopped(); - - if (mMode == MODE_DRAG_THUMB) { - // Animate back to a tick - setThumbAngleAnimated(mPreviousCallbackAngle, 0); - } - } - - mPreviousUpTime = time; - mCallback.onUserInteractionStopped(); + onTouchUp(time); return true; default: @@ -524,10 +515,9 @@ public class ZoomRing extends View { deltaThumbAndTick = getDelta(mThumbAngle, tickAngle, !oldDirectionIsCcw); boundAngle = getBoundIfExceeds(mThumbAngle, deltaThumbAndTick); if (boundAngle != Integer.MIN_VALUE) { - Log - .d( - TAG, - "Tapped somewhere where the shortest distance goes through a bound, but then the opposite direction also went through a bound!"); + // Not allowed to be here, it is between two bounds + mMode = MODE_IGNORE_UNTIL_UP; + return true; } } } @@ -574,6 +564,26 @@ public class ZoomRing extends View { return true; } + + private void onTouchUp(long time) { + if (mMode == MODE_MOVE_ZOOM_RING || mMode == MODE_WAITING_FOR_MOVE_ZOOM_RING) { + mCallback.onZoomRingSetMovableHintVisible(false); + if (mMode == MODE_MOVE_ZOOM_RING) { + mCallback.onZoomRingMovingStopped(); + } + } else if (mMode == MODE_DRAG_THUMB || mMode == MODE_TAP_DRAG || + mMode == MODE_WAITING_FOR_DRAG_THUMB) { + onThumbDragStopped(); + + if (mMode == MODE_DRAG_THUMB) { + // Animate back to a tick + setThumbAngleAnimated(mPreviousCallbackAngle, 0); + } + } + + mPreviousUpTime = time; + mCallback.onUserInteractionStopped(); + } private boolean isDeltaInBounds(int startAngle, int deltaAngle) { return getBoundIfExceeds(startAngle, deltaAngle) == Integer.MIN_VALUE; @@ -766,9 +776,11 @@ public class ZoomRing extends View { } } - int deltaAngle = getDelta(mThumbAngle, touchAngle, useDirection, ccw); - mAcculumalatedTrailAngle += Math.toDegrees(deltaAngle / (double) RADIAN_INT_MULTIPLIER); - + if (DRAW_TRAIL) { + int deltaAngle = getDelta(mThumbAngle, touchAngle, useDirection, ccw); + mAcculumalatedTrailAngle += Math.toDegrees(deltaAngle / (double) RADIAN_INT_MULTIPLIER); + } + if (animateThumbToNewAngle) { if (useDirection) { setThumbAngleAnimated(touchAngle, 0, ccw); @@ -851,15 +863,10 @@ public class ZoomRing extends View { if (DRAW_TRAIL) { mTrail.draw(canvas); } - - // If we aren't near the bounds, draw the corresponding arrows - int callbackAngle = mPreviousCallbackAngle; - if (callbackAngle < mThumbCwBound - RADIAN_INT_ERROR || - callbackAngle > mThumbCwBound + RADIAN_INT_ERROR) { + if ((mThumbArrowsToDraw & THUMB_ARROW_PLUS) != 0) { mThumbPlusArrowDrawable.draw(canvas); } - if (callbackAngle < mThumbCcwBound - RADIAN_INT_ERROR || - callbackAngle > mThumbCcwBound + RADIAN_INT_ERROR) { + if ((mThumbArrowsToDraw & THUMB_ARROW_MINUS) != 0) { mThumbMinusArrowDrawable.draw(canvas); } mThumbDrawable.draw(canvas); @@ -875,8 +882,21 @@ public class ZoomRing extends View { public void setThumbArrowsVisible(boolean visible) { if (visible) { mThumbArrowsAlpha = 255; - mThumbPlusArrowDrawable.setAlpha(255); - mThumbMinusArrowDrawable.setAlpha(255); + int callbackAngle = mPreviousCallbackAngle; + if (callbackAngle < mThumbCwBound - RADIAN_INT_ERROR || + callbackAngle > mThumbCwBound + RADIAN_INT_ERROR) { + mThumbPlusArrowDrawable.setAlpha(255); + mThumbArrowsToDraw |= THUMB_ARROW_PLUS; + } else { + mThumbArrowsToDraw &= ~THUMB_ARROW_PLUS; + } + if (callbackAngle < mThumbCcwBound - RADIAN_INT_ERROR || + callbackAngle > mThumbCcwBound + RADIAN_INT_ERROR) { + mThumbMinusArrowDrawable.setAlpha(255); + mThumbArrowsToDraw |= THUMB_ARROW_MINUS; + } else { + mThumbArrowsToDraw &= ~THUMB_ARROW_MINUS; + } invalidate(); } else if (mThumbArrowsAlpha == 255) { // Only start fade if we're fully visible (otherwise another fade is happening already) @@ -886,17 +906,24 @@ public class ZoomRing extends View { } private void onThumbArrowsFadeTick() { - if (mThumbArrowsAlpha <= 0) return; + if (mThumbArrowsAlpha <= 0) { + mThumbArrowsToDraw = 0; + return; + } mThumbArrowsAlpha = (int) (255 - (255 * (SystemClock.elapsedRealtime() - mThumbArrowsFadeStartTime) / THUMB_ARROWS_FADE_DURATION)); if (mThumbArrowsAlpha < 0) mThumbArrowsAlpha = 0; - mThumbPlusArrowDrawable.setAlpha(mThumbArrowsAlpha); - mThumbMinusArrowDrawable.setAlpha(mThumbArrowsAlpha); - invalidateDrawable(mThumbPlusArrowDrawable); - invalidateDrawable(mThumbMinusArrowDrawable); - + if ((mThumbArrowsToDraw & THUMB_ARROW_PLUS) != 0) { + mThumbPlusArrowDrawable.setAlpha(mThumbArrowsAlpha); + invalidateDrawable(mThumbPlusArrowDrawable); + } + if ((mThumbArrowsToDraw & THUMB_ARROW_MINUS) != 0) { + mThumbMinusArrowDrawable.setAlpha(mThumbArrowsAlpha); + invalidateDrawable(mThumbMinusArrowDrawable); + } + if (!mHandler.hasMessages(MSG_THUMB_ARROWS_FADE_TICK)) { mHandler.sendEmptyMessage(MSG_THUMB_ARROWS_FADE_TICK); } diff --git a/core/java/android/widget/ZoomRingController.java b/core/java/android/widget/ZoomRingController.java index 31074b6..2e97fda 100644 --- a/core/java/android/widget/ZoomRingController.java +++ b/core/java/android/widget/ZoomRingController.java @@ -57,7 +57,7 @@ import android.view.animation.DecelerateInterpolator; public class ZoomRingController implements ZoomRing.OnZoomRingCallback, View.OnTouchListener, View.OnKeyListener { - private static final int ZOOM_RING_RADIUS_INSET = 10; + private static final int ZOOM_RING_RADIUS_INSET = 24; private static final int ZOOM_RING_RECENTERING_DURATION = 500; @@ -79,7 +79,7 @@ public class ZoomRingController implements ZoomRing.OnZoomRingCallback, private static final int MAX_PAN_GAP = 20; private static final int MAX_INITIATE_PAN_GAP = 10; // TODO view config - private static final int INITIATE_PAN_DELAY = 400; + private static final int INITIATE_PAN_DELAY = 300; private static final String SETTING_NAME_SHOWN_TOAST = "shown_zoom_ring_toast"; @@ -146,7 +146,7 @@ public class ZoomRingController implements ZoomRing.OnZoomRingCallback, private int mZoomRingHeight; /** Invokes panning of owner view if the zoom ring is touching an edge. */ - private Panner mPanner = new Panner(); + private Panner mPanner; private long mTouchingEdgeStartTime; private boolean mPanningEnabledForThisInteraction; @@ -241,6 +241,7 @@ public class ZoomRingController implements ZoomRing.OnZoomRingCallback, mContext = context; mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); + mPanner = new Panner(); mOwnerView = ownerView; mZoomRing = new ZoomRing(context); @@ -389,6 +390,8 @@ public class ZoomRingController implements ZoomRing.OnZoomRingCallback, }; } + mPanningArrows.setAnimation(null); + mHandler.post(mPostedVisibleInitializer); // Handle configuration changes when visible @@ -409,12 +412,13 @@ public class ZoomRingController implements ZoomRing.OnZoomRingCallback, } else { mOwnerView.setOnTouchListener(null); } - + // No longer care about configuration changes mContext.unregisterReceiver(mConfigurationChangedReceiver); mWindowManager.removeView(mContainer); - + mHandler.removeCallbacks(mPostedVisibleInitializer); + if (mCallback != null) { mCallback.onVisibilityChanged(false); } @@ -464,6 +468,9 @@ public class ZoomRingController implements ZoomRing.OnZoomRingCallback, public boolean handleDoubleTapEvent(MotionEvent event) { int action = event.getAction(); + // TODO: make sure this works well with the + // ownerView.setOnTouchListener(this) instead of window receiving + // touches if (action == MotionEvent.ACTION_DOWN) { mTouchMode = TOUCH_MODE_WAITING_FOR_TAP_DRAG_MOVEMENT; int x = (int) event.getX(); @@ -493,6 +500,7 @@ public class ZoomRingController implements ZoomRing.OnZoomRingCallback, mViewConfig.getScaledTouchSlop()) { mZoomRing.setTapDragMode(true, x, y); mTouchMode = TOUCH_MODE_FORWARDING_FOR_TAP_DRAG; + setTouchTargetView(mZoomRing); } return true; @@ -587,7 +595,6 @@ public class ZoomRingController implements ZoomRing.OnZoomRingCallback, public void onZoomRingMovingStarted() { mScroller.abortAnimation(); - mPanningEnabledForThisInteraction = false; mTouchingEdgeStartTime = 0; if (mCallback != null) { mCallback.onBeginPan(); @@ -658,6 +665,8 @@ public class ZoomRingController implements ZoomRing.OnZoomRingCallback, if (!horizontalPanning) { // Neither are panning, reset any timer to start pan mode mTouchingEdgeStartTime = 0; + mPanningEnabledForThisInteraction = false; + mPanner.stop(); } } } @@ -752,6 +761,7 @@ public class ZoomRingController implements ZoomRing.OnZoomRingCallback, // The ring was dismissed but we need to throw away all events until the up if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) { mOwnerView.setOnTouchListener(null); + setTouchTargetView(null); mReleaseTouchListenerOnUp = false; } @@ -763,16 +773,13 @@ public class ZoomRingController implements ZoomRing.OnZoomRingCallback, switch (action) { case MotionEvent.ACTION_DOWN: - targetView = mTouchTargetView = - getViewForTouch((int) event.getRawX(), (int) event.getRawY()); - if (targetView != null) { - targetView.getLocationInWindow(mTouchTargetLocationInWindow); - } + targetView = getViewForTouch((int) event.getRawX(), (int) event.getRawY()); + setTouchTargetView(targetView); break; case MotionEvent.ACTION_UP: case MotionEvent.ACTION_CANCEL: - mTouchTargetView = null; + setTouchTargetView(null); break; } @@ -799,6 +806,13 @@ public class ZoomRingController implements ZoomRing.OnZoomRingCallback, } } + private void setTouchTargetView(View view) { + mTouchTargetView = view; + if (view != null) { + view.getLocationInWindow(mTouchTargetLocationInWindow); + } + } + /** * Returns the View that should receive a touch at the given coordinates. * @@ -950,6 +964,22 @@ public class ZoomRingController implements ZoomRing.OnZoomRingCallback, } } + public void setPannerStartVelocity(float startVelocity) { + mPanner.mStartVelocity = startVelocity; + } + + public void setPannerAcceleration(float acceleration) { + mPanner.mAcceleration = acceleration; + } + + public void setPannerMaxVelocity(float maxVelocity) { + mPanner.mMaxVelocity = maxVelocity; + } + + public void setPannerStartAcceleratingDuration(int duration) { + mPanner.mStartAcceleratingDuration = duration; + } + private class Panner implements Runnable { private static final int RUN_DELAY = 15; private static final float STOP_SLOWDOWN = 0.8f; @@ -967,6 +997,13 @@ public class ZoomRingController implements ZoomRing.OnZoomRingCallback, /** The time of the last callback to pan the map/browser/etc. */ private long mPreviousCallbackTime; + // TODO Adjust to be DPI safe + private float mStartVelocity = 135; + private float mAcceleration = 160; + private float mMaxVelocity = 1000; + private int mStartAcceleratingDuration = 700; + private float mVelocity; + /** -100 (full left) to 0 (none) to 100 (full right) */ public void setHorizontalStrength(int horizontalStrength) { if (mHorizontalStrength == 0 && mVerticalStrength == 0 && horizontalStrength != 0) { @@ -1013,11 +1050,12 @@ public class ZoomRingController implements ZoomRing.OnZoomRingCallback, boolean firstRun = mPreviousCallbackTime == 0; long curTime = SystemClock.elapsedRealtime(); - int panAmount = getPanAmount(mStartTime, mPreviousCallbackTime, curTime); + int panAmount = getPanAmount(mPreviousCallbackTime, curTime); mPreviousCallbackTime = curTime; if (firstRun) { mStartTime = curTime; + mVelocity = mStartVelocity; } else { int panX = panAmount * mHorizontalStrength / 100; int panY = panAmount * mVerticalStrength / 100; @@ -1030,12 +1068,22 @@ public class ZoomRingController implements ZoomRing.OnZoomRingCallback, mUiHandler.postDelayed(this, RUN_DELAY); } - // TODO make setter for this value so zoom clients can have different pan rates, if they want - private static final int PAN_VELOCITY_PX_S = 30; - private int getPanAmount(long startTime, long previousTime, long currentTime) { - return (int) ((currentTime - previousTime) * PAN_VELOCITY_PX_S / 100); + private int getPanAmount(long previousTime, long currentTime) { + if (mVelocity > mMaxVelocity) { + mVelocity = mMaxVelocity; + } else if (mVelocity < mMaxVelocity) { + // See if it's time to add in some acceleration + if (currentTime - mStartTime > mStartAcceleratingDuration) { + mVelocity += (currentTime - previousTime) * mAcceleration / 1000; + } + } + + return (int) ((currentTime - previousTime) * mVelocity) / 1000; } + } + + public interface OnZoomListener { void onBeginDrag(); |