add tab dragging
Bug: 5081671
enable dragging tabs to close them
animations are not correct yet and will be fixed later
Change-Id: Ib0a4ca07706fd73464e307f2061c4246863b9ec8
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 @@
*/
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 @@
super(context);
}
+ public void setOnRemoveListener(OnRemoveListener l) {
+ mRemoveListener = l;
+ }
+
protected void setSelection(int ix) {
super.setSelectedPositionInt(ix);
}
@@ -55,4 +73,76 @@
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();
+ }
+
}