summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorMichael Kolb <kolby@google.com>2011-07-22 10:30:49 -0700
committerMichael Kolb <kolby@google.com>2011-07-26 16:51:07 -0700
commitdcd81d37547c3116fd3843894060b6e705d2b1f7 (patch)
tree4ca88034ec791453b34092607b36e00f0dd25314 /src
parent31868118c7f2d93fb56c367b7ac46e29c75b1017 (diff)
downloadpackages_apps_Browser-dcd81d37547c3116fd3843894060b6e705d2b1f7.zip
packages_apps_Browser-dcd81d37547c3116fd3843894060b6e705d2b1f7.tar.gz
packages_apps_Browser-dcd81d37547c3116fd3843894060b6e705d2b1f7.tar.bz2
add tab dragging
Bug: 5081671 enable dragging tabs to close them animations are not correct yet and will be fixed later Change-Id: Ib0a4ca07706fd73464e307f2061c4246863b9ec8
Diffstat (limited to 'src')
-rw-r--r--src/com/android/browser/NavScreen.java10
-rw-r--r--src/com/android/browser/NavTabGallery.java90
-rw-r--r--src/com/android/browser/view/Gallery.java99
3 files changed, 169 insertions, 30 deletions
diff --git a/src/com/android/browser/NavScreen.java b/src/com/android/browser/NavScreen.java
index ee20535..f52ef88 100644
--- a/src/com/android/browser/NavScreen.java
+++ b/src/com/android/browser/NavScreen.java
@@ -23,8 +23,8 @@ import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
-import android.view.ViewConfiguration;
import android.view.View.OnClickListener;
+import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.webkit.WebView;
import android.widget.BaseAdapter;
@@ -37,6 +37,8 @@ import android.widget.PopupMenu.OnMenuItemClickListener;
import android.widget.RelativeLayout;
import android.widget.TextView;
+import com.android.browser.NavTabGallery.OnRemoveListener;
+
public class NavScreen extends RelativeLayout
implements OnClickListener, OnMenuItemClickListener {
@@ -124,6 +126,12 @@ public class NavScreen extends RelativeLayout
? LinearLayout.HORIZONTAL : LinearLayout.VERTICAL);
// update state for active tab
mScroller.setSelection(mUiController.getTabControl().getTabPosition(mUi.getActiveTab()));
+ mScroller.setOnRemoveListener(new OnRemoveListener() {
+ public void onRemovePosition(int pos) {
+ Tab tab = mAdapter.getItem(pos);
+ onCloseTab(tab);
+ }
+ });
mNeedsMenu = !ViewConfiguration.get(getContext()).hasPermanentMenuKey();
if (!mNeedsMenu) {
mMore.setVisibility(View.GONE);
diff --git a/src/com/android/browser/NavTabGallery.java b/src/com/android/browser/NavTabGallery.java
index 3014eaf..0cd1f82 100644
--- a/src/com/android/browser/NavTabGallery.java
+++ b/src/com/android/browser/NavTabGallery.java
@@ -16,8 +16,12 @@
package com.android.browser;
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.ObjectAnimator;
import android.content.Context;
import android.util.AttributeSet;
+import android.view.MotionEvent;
import android.view.View;
import com.android.browser.view.Gallery;
@@ -27,6 +31,16 @@ import com.android.browser.view.Gallery;
*/
public class NavTabGallery extends Gallery {
+ interface OnRemoveListener {
+ public void onRemovePosition(int position);
+ }
+
+ // after drag animation velocity in pixels/sec
+ private static final float MIN_VELOCITY = 1500;
+
+ private OnRemoveListener mRemoveListener;
+ private boolean mBlockUpCallback;
+
public NavTabGallery(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
@@ -39,6 +53,10 @@ public class NavTabGallery extends Gallery {
super(context);
}
+ public void setOnRemoveListener(OnRemoveListener l) {
+ mRemoveListener = l;
+ }
+
protected void setSelection(int ix) {
super.setSelectedPositionInt(ix);
}
@@ -55,4 +73,76 @@ public class NavTabGallery extends Gallery {
return getSelectedView();
}
+ @Override
+ protected void onOrthoDrag(View v, MotionEvent down, MotionEvent move,
+ float distance) {
+ offsetView(v, - distance);
+ }
+
+ @Override
+ protected void onOrthoFling(View v, MotionEvent down, MotionEvent move,
+ float velocity) {
+ if (Math.abs(velocity) > MIN_VELOCITY) {
+ mBlockUpCallback = true;
+ animateOut(v, velocity);
+ }
+ }
+
+ @Override
+ protected void onUp(View downView) {
+ if (mBlockUpCallback) {
+ mBlockUpCallback = false;
+ return;
+ }
+ if (mIsOrthoDragged && downView != null) {
+ // offset
+ int diff = calculateTop(downView, false) - (mHorizontal ? downView.getTop()
+ : downView.getLeft());
+ if (Math.abs(diff) > (mHorizontal ? downView.getHeight() : downView.getWidth()) / 2) {
+ // remove it
+ animateOut(downView, - Math.signum(diff) * MIN_VELOCITY);
+ } else {
+ // snap back
+ offsetView(downView, diff);
+ }
+ } else {
+ super.onUp(downView);
+ }
+ }
+
+ private void offsetView(View v, float distance) {
+ if (mHorizontal) {
+ v.offsetTopAndBottom((int) distance);
+ } else {
+ v.offsetLeftAndRight((int) distance);
+ }
+ }
+
+ private void animateOut(View v, float velocity) {
+ final int position = mDownTouchPosition;
+ int target = 0;
+ if (velocity < 0) {
+ target = mHorizontal ? -v.getHeight() : - v.getWidth();
+ } else {
+ target = mHorizontal ? getHeight() : getWidth();
+ }
+ int distance = target - (mHorizontal ? v.getTop() : v.getLeft());
+ long duration = (long) (Math.abs(distance) * 1000 / Math.abs(velocity));
+ ObjectAnimator animator = null;
+ if (mHorizontal) {
+ animator = ObjectAnimator.ofFloat(v, TRANSLATION_Y, 0, target);
+ } else {
+ animator = ObjectAnimator.ofFloat(v, TRANSLATION_X, 0, target);
+ }
+ animator.setDuration(duration);
+ animator.addListener(new AnimatorListenerAdapter() {
+ public void onAnimationEnd(Animator a) {
+ if (mRemoveListener != null) {
+ mRemoveListener.onRemovePosition(position);
+ }
+ }
+ });
+ animator.start();
+ }
+
}
diff --git a/src/com/android/browser/view/Gallery.java b/src/com/android/browser/view/Gallery.java
index 0c73537..d9c172e 100644
--- a/src/com/android/browser/view/Gallery.java
+++ b/src/com/android/browser/view/Gallery.java
@@ -63,7 +63,7 @@ public class Gallery extends ViewGroup implements
private RecycleBin mRecycler;
- private boolean mHorizontal;
+ protected boolean mHorizontal;
private int mFirstPosition;
private int mItemCount;
private boolean mDataChanged;
@@ -82,8 +82,8 @@ public class Gallery extends ViewGroup implements
private GestureDetector mGestureDetector;
- private int mDownTouchPosition;
- private View mDownTouchView;
+ protected int mDownTouchPosition;
+ protected View mDownTouchView;
private FlingRunnable mFlingRunnable = new FlingRunnable();
private OnItemSelectedListener mOnItemSelectedListener;
@@ -114,12 +114,14 @@ public class Gallery extends ViewGroup implements
private boolean mIsFirstScroll;
private boolean mIsBeingDragged;
+ protected boolean mIsOrthoDragged;
private int mActivePointerId = INVALID_POINTER;
private int mTouchSlop;
private float mLastMotionCoord;
+ private float mLastOrthoCoord;
public Gallery(Context context) {
this(context, null);
@@ -676,7 +678,7 @@ public class Gallery extends ViewGroup implements
* This will either be the left or right edge of the view,
* depending on the fromLeft paramter
* @param fromLeft
- * Are we posiitoning views based on the left edge? (i.e.,
+ * Are we positioning views based on the left edge? (i.e.,
* building from left to right)?
* @return A view that has been added to the gallery
*/
@@ -769,7 +771,7 @@ public class Gallery extends ViewGroup implements
* Child to place
* @return Where the top of the child should be
*/
- private int calculateTop(View child, boolean duringLayout) {
+ protected int calculateTop(View child, boolean duringLayout) {
int myHeight = mHorizontal ? (duringLayout ? getMeasuredHeight()
: getHeight()) : (duringLayout ? getMeasuredWidth()
: getWidth());
@@ -805,6 +807,9 @@ public class Gallery extends ViewGroup implements
if ((action == MotionEvent.ACTION_MOVE) && (mIsBeingDragged)) {
return true;
}
+ if ((action == MotionEvent.ACTION_MOVE) && (mIsOrthoDragged)) {
+ return true;
+ }
switch (action & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_MOVE: {
/*
@@ -821,10 +826,20 @@ public class Gallery extends ViewGroup implements
final int pointerIndex = ev.findPointerIndex(activePointerId);
final float coord = mHorizontal ? ev.getX(pointerIndex) : ev
.getY(pointerIndex);
+
final int diff = (int) Math.abs(coord - mLastMotionCoord);
if (diff > mTouchSlop) {
mIsBeingDragged = true;
mLastMotionCoord = coord;
+ } else {
+ final float ocoord = mHorizontal ? ev.getY(pointerIndex)
+ : ev.getX(pointerIndex);
+ if (Math.abs(ocoord - mLastOrthoCoord) > mTouchSlop) {
+ mIsOrthoDragged = true;
+ mLastOrthoCoord = ocoord;
+ }
+ }
+ if (mIsBeingDragged || mIsOrthoDragged) {
if (mParent != null)
mParent.requestDisallowInterceptTouchEvent(true);
}
@@ -844,6 +859,9 @@ public class Gallery extends ViewGroup implements
* flinged.
*/
mIsBeingDragged = !mFlingRunnable.mScroller.isFinished();
+ mIsOrthoDragged = false;
+ final float ocoord = mHorizontal ? ev.getY() : ev.getX();
+ mLastOrthoCoord = ocoord;
mGestureDetector.onTouchEvent(ev);
break;
}
@@ -851,20 +869,24 @@ public class Gallery extends ViewGroup implements
case MotionEvent.ACTION_UP:
/* Release the drag */
mIsBeingDragged = false;
+ mIsOrthoDragged = false;
mActivePointerId = INVALID_POINTER;
break;
case MotionEvent.ACTION_POINTER_DOWN: {
final int index = ev.getActionIndex();
mLastMotionCoord = mHorizontal ? ev.getX(index) : ev.getY(index);
+ mLastOrthoCoord = mHorizontal ? ev.getY(index) : ev.getX(index);
mActivePointerId = ev.getPointerId(index);
break;
}
case MotionEvent.ACTION_POINTER_UP:
- mLastMotionCoord = ev.getX(ev.findPointerIndex(mActivePointerId));
+ mLastMotionCoord = mHorizontal ? ev.getX(ev.findPointerIndex(mActivePointerId))
+ : ev.getY(ev.findPointerIndex(mActivePointerId));
+ mLastOrthoCoord = mHorizontal ? ev.getY(ev.findPointerIndex(mActivePointerId))
+ : ev.getX(ev.findPointerIndex(mActivePointerId));
break;
}
-
- return mIsBeingDragged;
+ return mIsBeingDragged || mIsOrthoDragged;
}
@Override
@@ -874,7 +896,7 @@ public class Gallery extends ViewGroup implements
int action = event.getAction();
if (action == MotionEvent.ACTION_UP) {
// Helper method for lifted finger
- onUp();
+ onUp(mDownTouchView);
} else if (action == MotionEvent.ACTION_CANCEL) {
onCancel();
}
@@ -902,6 +924,10 @@ public class Gallery extends ViewGroup implements
if (!mSuppressSelectionChanged)
mSuppressSelectionChanged = true;
}
+ if (isOrthoMove(velocityX, velocityY)) {
+ onOrthoFling(mDownTouchView, e1, e2, mHorizontal ? velocityY : velocityX);
+ return true;
+ }
mFlingRunnable.startUsingVelocity(mHorizontal ? (int) -velocityX
: (int) -velocityY);
return true;
@@ -912,30 +938,43 @@ public class Gallery extends ViewGroup implements
if (localLOGV)
Log.v(TAG, String.valueOf(e2.getX() - e1.getX()));
mParent.requestDisallowInterceptTouchEvent(true);
- if (!mShouldCallbackDuringFling) {
- if (mIsFirstScroll) {
- if (!mSuppressSelectionChanged)
- mSuppressSelectionChanged = true;
- postDelayed(mDisableSuppressSelectionChangedRunnable,
- SCROLL_TO_FLING_UNCERTAINTY_TIMEOUT);
+ if (mIsOrthoDragged && isOrthoMove(distanceX, distanceY)) {
+ onOrthoDrag(mDownTouchView, e1, e2, mHorizontal ? distanceY : distanceX);
+ } else if (mIsBeingDragged) {
+ if (!mShouldCallbackDuringFling) {
+ if (mIsFirstScroll) {
+ if (!mSuppressSelectionChanged) {
+ mSuppressSelectionChanged = true;
+ }
+ postDelayed(mDisableSuppressSelectionChangedRunnable,
+ SCROLL_TO_FLING_UNCERTAINTY_TIMEOUT);
+ }
+ } else {
+ if (mSuppressSelectionChanged) {
+ mSuppressSelectionChanged = false;
+ }
}
- } else {
- if (mSuppressSelectionChanged)
- mSuppressSelectionChanged = false;
- }
- trackMotionScroll(mHorizontal ? -1 * (int) distanceX : -1
- * (int) distanceY);
+ trackMotionScroll(mHorizontal ? -1 * (int) distanceX : -1
+ * (int) distanceY);
- mIsFirstScroll = false;
+ mIsFirstScroll = false;
+ }
return true;
}
+ protected void onOrthoDrag(View draggedView, MotionEvent down,
+ MotionEvent move, float distance) {
+ }
+
+ protected void onOrthoFling(View draggedView, MotionEvent down,
+ MotionEvent move, float velocity) {
+ }
+
public boolean onDown(MotionEvent e) {
mFlingRunnable.stop(false);
mDownTouchPosition = pointToPosition((int) e.getX(), (int) e.getY());
if (mDownTouchPosition >= 0) {
mDownTouchView = getChildAt(mDownTouchPosition - mFirstPosition);
- mDownTouchView.setPressed(true);
}
// Reset the multiple-scroll tracking state
mIsFirstScroll = true;
@@ -946,18 +985,23 @@ public class Gallery extends ViewGroup implements
/**
* Called when a touch event's action is MotionEvent.ACTION_UP.
*/
- void onUp() {
+ protected void onUp(View downView) {
if (mFlingRunnable.mScroller.isFinished()) {
scrollIntoSlots();
}
dispatchUnpress();
}
+ private boolean isOrthoMove(float moveX, float moveY) {
+ return mHorizontal && Math.abs(moveY) > Math.abs(moveX)
+ || !mHorizontal && Math.abs(moveX) > Math.abs(moveY);
+ }
+
/**
* Called when a touch event's action is MotionEvent.ACTION_CANCEL.
*/
void onCancel() {
- onUp();
+ onUp(mDownTouchView);
}
public void onLongPress(MotionEvent e) {
@@ -986,9 +1030,6 @@ public class Gallery extends ViewGroup implements
@Override
protected void dispatchSetPressed(boolean pressed) {
- if (mSelectedChild != null) {
- mSelectedChild.setPressed(pressed);
- }
}
@Override
@@ -1063,7 +1104,7 @@ public class Gallery extends ViewGroup implements
long itemId) {
}
- boolean movePrevious() {
+ protected boolean movePrevious() {
if (mItemCount > 0 && mSelectedPosition > 0) {
scrollToChild(mSelectedPosition - mFirstPosition - 1);
return true;