blob: af02e8d0bf60de7a906115c8f88df14a144676a3 [file] [log] [blame]
Michael Kolb9829b432011-06-04 13:29:00 -07001/*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5 * use this file except in compliance with the License. You may obtain a copy of
6 * the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 * License for the specific language governing permissions and limitations under
14 * the License.
15 */
16
17package com.android.browser;
18
Michael Kolbdcd81d32011-07-22 10:30:49 -070019import android.animation.Animator;
20import android.animation.AnimatorListenerAdapter;
21import android.animation.ObjectAnimator;
Michael Kolb9829b432011-06-04 13:29:00 -070022import android.content.Context;
23import android.util.AttributeSet;
Michael Kolbdcd81d32011-07-22 10:30:49 -070024import android.view.MotionEvent;
Michael Kolb9829b432011-06-04 13:29:00 -070025import android.view.View;
26
27import com.android.browser.view.Gallery;
28
29/**
30 * custom view for displaying tabs in the nav screen
31 */
32public class NavTabGallery extends Gallery {
33
Michael Kolbdcd81d32011-07-22 10:30:49 -070034 interface OnRemoveListener {
35 public void onRemovePosition(int position);
36 }
37
38 // after drag animation velocity in pixels/sec
39 private static final float MIN_VELOCITY = 1500;
40
41 private OnRemoveListener mRemoveListener;
42 private boolean mBlockUpCallback;
Michael Kolbe76f7042011-07-27 15:16:32 -070043 private Animator mAnimator;
Michael Kolbdcd81d32011-07-22 10:30:49 -070044
Michael Kolb9829b432011-06-04 13:29:00 -070045 public NavTabGallery(Context context, AttributeSet attrs, int defStyle) {
46 super(context, attrs, defStyle);
47 }
48
49 public NavTabGallery(Context context, AttributeSet attrs) {
50 super(context, attrs);
51 }
52
53 public NavTabGallery(Context context) {
54 super(context);
55 }
56
Michael Kolbdcd81d32011-07-22 10:30:49 -070057 public void setOnRemoveListener(OnRemoveListener l) {
58 mRemoveListener = l;
59 }
60
Michael Kolb9829b432011-06-04 13:29:00 -070061 protected void setSelection(int ix) {
62 super.setSelectedPositionInt(ix);
63 }
64
65 protected int getSelectionIndex() {
66 return getSelectedItemPosition();
67 }
68
69 protected Tab getSelectedItem() {
70 return (Tab) mAdapter.getItem(getSelectedItemPosition());
71 }
72
73 View getSelectedTab() {
74 return getSelectedView();
75 }
76
Michael Kolbdcd81d32011-07-22 10:30:49 -070077 @Override
78 protected void onOrthoDrag(View v, MotionEvent down, MotionEvent move,
79 float distance) {
Michael Kolbe76f7042011-07-27 15:16:32 -070080 if (mAnimator == null) {
81 offsetView(v, - distance);
82 }
Michael Kolbdcd81d32011-07-22 10:30:49 -070083 }
84
85 @Override
86 protected void onOrthoFling(View v, MotionEvent down, MotionEvent move,
87 float velocity) {
Michael Kolbe76f7042011-07-27 15:16:32 -070088 if ((mAnimator == null) && (Math.abs(velocity) > MIN_VELOCITY)) {
Michael Kolbdcd81d32011-07-22 10:30:49 -070089 mBlockUpCallback = true;
90 animateOut(v, velocity);
91 }
92 }
93
94 @Override
95 protected void onUp(View downView) {
Michael Kolbe76f7042011-07-27 15:16:32 -070096 if (mAnimator != null) return;
Michael Kolbdcd81d32011-07-22 10:30:49 -070097 if (mBlockUpCallback) {
98 mBlockUpCallback = false;
99 return;
100 }
101 if (mIsOrthoDragged && downView != null) {
102 // offset
103 int diff = calculateTop(downView, false) - (mHorizontal ? downView.getTop()
104 : downView.getLeft());
105 if (Math.abs(diff) > (mHorizontal ? downView.getHeight() : downView.getWidth()) / 2) {
106 // remove it
107 animateOut(downView, - Math.signum(diff) * MIN_VELOCITY);
108 } else {
109 // snap back
110 offsetView(downView, diff);
111 }
112 } else {
113 super.onUp(downView);
114 }
115 }
116
117 private void offsetView(View v, float distance) {
118 if (mHorizontal) {
119 v.offsetTopAndBottom((int) distance);
120 } else {
121 v.offsetLeftAndRight((int) distance);
122 }
123 }
124
Michael Kolbe76f7042011-07-27 15:16:32 -0700125 protected void animateOut(View v) {
126 animateOut(v, -MIN_VELOCITY);
127 }
128
129 private void animateOut(final View v, float velocity) {
Michael Kolb3bb854b2011-08-01 10:45:16 -0700130 if ((v == null) || (mAnimator != null)) return;
Michael Kolbe76f7042011-07-27 15:16:32 -0700131 final int position = mFirstPosition + indexOfChild(v);
Michael Kolbdcd81d32011-07-22 10:30:49 -0700132 int target = 0;
133 if (velocity < 0) {
134 target = mHorizontal ? -v.getHeight() : - v.getWidth();
135 } else {
136 target = mHorizontal ? getHeight() : getWidth();
137 }
138 int distance = target - (mHorizontal ? v.getTop() : v.getLeft());
139 long duration = (long) (Math.abs(distance) * 1000 / Math.abs(velocity));
Michael Kolbdcd81d32011-07-22 10:30:49 -0700140 if (mHorizontal) {
Michael Kolbe76f7042011-07-27 15:16:32 -0700141 mAnimator = ObjectAnimator.ofFloat(v, TRANSLATION_Y, 0, target);
Michael Kolbdcd81d32011-07-22 10:30:49 -0700142 } else {
Michael Kolbe76f7042011-07-27 15:16:32 -0700143 mAnimator = ObjectAnimator.ofFloat(v, TRANSLATION_X, 0, target);
Michael Kolbdcd81d32011-07-22 10:30:49 -0700144 }
Michael Kolbe76f7042011-07-27 15:16:32 -0700145 mAnimator.setDuration(duration);
146 mAnimator.addListener(new AnimatorListenerAdapter() {
Michael Kolbdcd81d32011-07-22 10:30:49 -0700147 public void onAnimationEnd(Animator a) {
148 if (mRemoveListener != null) {
Michael Kolbe76f7042011-07-27 15:16:32 -0700149 boolean needsGap = position < (mAdapter.getCount() - 1);
150 if (needsGap) {
151 setGapPosition(position, mHorizontal ? v.getWidth() : v.getHeight());
152 }
Michael Kolbdcd81d32011-07-22 10:30:49 -0700153 mRemoveListener.onRemovePosition(position);
Michael Kolbc1eeb122011-08-01 09:56:26 -0700154 if (!needsGap && (position > 0) && (mAdapter.getCount() > 0)) {
Michael Kolbe76f7042011-07-27 15:16:32 -0700155 scrollToChild(position - 1);
156 }
157 mAnimator = null;
Michael Kolbdcd81d32011-07-22 10:30:49 -0700158 }
159 }
160 });
Michael Kolbe76f7042011-07-27 15:16:32 -0700161 mAnimator.start();
Michael Kolbdcd81d32011-07-22 10:30:49 -0700162 }
163
Michael Kolb9829b432011-06-04 13:29:00 -0700164}