blob: 0d85920b33192579f46be7c9f8d3c5f00e380eb2 [file] [log] [blame]
Michael Kolbfe251992010-07-08 15:41:55 -07001/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
Michael Kolb27b08392010-10-04 12:49:23 -07004 * 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
Michael Kolbfe251992010-07-08 15:41:55 -07007 *
Michael Kolb27b08392010-10-04 12:49:23 -07008 * http://www.apache.org/licenses/LICENSE-2.0
Michael Kolbfe251992010-07-08 15:41:55 -07009 *
10 * Unless required by applicable law or agreed to in writing, software
Michael Kolb27b08392010-10-04 12:49:23 -070011 * 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.
Michael Kolbfe251992010-07-08 15:41:55 -070015 */
16
17package com.android.browser;
18
Michael Kolb27b08392010-10-04 12:49:23 -070019import android.animation.Animator;
20import android.animation.Animator.AnimatorListener;
21import android.animation.ObjectAnimator;
22import android.animation.PropertyValuesHolder;
Michael Kolbfe251992010-07-08 15:41:55 -070023import android.content.Context;
Michael Kolbc3503762010-10-03 14:45:11 -070024import android.graphics.Canvas;
25import android.graphics.drawable.Drawable;
Michael Kolbfe251992010-07-08 15:41:55 -070026import android.util.AttributeSet;
27import android.view.View;
Michael Kolb27b08392010-10-04 12:49:23 -070028import android.view.animation.AccelerateInterpolator;
Michael Kolbfe251992010-07-08 15:41:55 -070029import android.widget.HorizontalScrollView;
30import android.widget.LinearLayout;
31
32/**
33 * custom view for displaying tabs in the tabbed title bar
34 */
35public class TabScrollView extends HorizontalScrollView {
36
Michael Kolbebba8b42010-09-30 12:57:59 -070037 private BrowserActivity mBrowserActivity;
Michael Kolbfe251992010-07-08 15:41:55 -070038 private LinearLayout mContentView;
Michael Kolbfe251992010-07-08 15:41:55 -070039 private int mSelected;
Michael Kolbc3503762010-10-03 14:45:11 -070040 private Drawable mArrowLeft;
41 private Drawable mArrowRight;
Michael Kolb27b08392010-10-04 12:49:23 -070042 private int mAnimationDuration;
Michael Kolbfe251992010-07-08 15:41:55 -070043
44 /**
45 * @param context
46 * @param attrs
47 * @param defStyle
48 */
49 public TabScrollView(Context context, AttributeSet attrs, int defStyle) {
50 super(context, attrs, defStyle);
51 init(context);
52 }
53
54 /**
55 * @param context
56 * @param attrs
57 */
58 public TabScrollView(Context context, AttributeSet attrs) {
59 super(context, attrs);
60 init(context);
61 }
62
63 /**
64 * @param context
65 */
66 public TabScrollView(Context context) {
67 super(context);
68 init(context);
69 }
70
71 private void init(Context ctx) {
Michael Kolb27b08392010-10-04 12:49:23 -070072 mBrowserActivity = (BrowserActivity) ctx;
73 mAnimationDuration = ctx.getResources().getInteger(
74 R.integer.tab_animation_duration);
Michael Kolbfe251992010-07-08 15:41:55 -070075 setHorizontalScrollBarEnabled(false);
Michael Kolbebba8b42010-09-30 12:57:59 -070076 mContentView = new LinearLayout(mBrowserActivity);
Michael Kolbfe251992010-07-08 15:41:55 -070077 mContentView.setOrientation(LinearLayout.HORIZONTAL);
Michael Kolb27b08392010-10-04 12:49:23 -070078 mContentView.setLayoutParams(
79 new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT));
Michael Kolbfe251992010-07-08 15:41:55 -070080 addView(mContentView);
81 mSelected = -1;
Michael Kolbc3503762010-10-03 14:45:11 -070082 mArrowLeft = ctx.getResources().getDrawable(R.drawable.ic_arrow_left);
83 mArrowRight = ctx.getResources().getDrawable(R.drawable.ic_arrow_right);
Michael Kolb27b08392010-10-04 12:49:23 -070084 // prevent ProGuard from removing the property methods
85 setScroll(getScroll());
Michael Kolbfe251992010-07-08 15:41:55 -070086 }
87
88 @Override
89 protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
90 super.onLayout(changed, left, top, right, bottom);
91 ensureChildVisible(getSelectedTab());
92 }
93
94 void setSelectedTab(int position) {
95 View v = getSelectedTab();
96 if (v != null) {
Michael Kolbb7b115e2010-09-25 16:59:37 -070097 v.setActivated(false);
Michael Kolbfe251992010-07-08 15:41:55 -070098 }
99 mSelected = position;
100 v = getSelectedTab();
101 if (v != null) {
Michael Kolbb7b115e2010-09-25 16:59:37 -0700102 v.setActivated(true);
Michael Kolbfe251992010-07-08 15:41:55 -0700103 }
104 requestLayout();
105 }
106
Michael Kolbebba8b42010-09-30 12:57:59 -0700107 int getChildIndex(View v) {
108 return mContentView.indexOfChild(v);
109 }
110
Michael Kolbfe251992010-07-08 15:41:55 -0700111 View getSelectedTab() {
112 if ((mSelected >= 0) && (mSelected < mContentView.getChildCount())) {
113 return mContentView.getChildAt(mSelected);
114 } else {
115 return null;
116 }
117 }
118
119 void clearTabs() {
120 mContentView.removeAllViews();
121 }
122
123 void addTab(View tab) {
124 mContentView.addView(tab);
Michael Kolb27b08392010-10-04 12:49:23 -0700125 animateIn(tab);
Michael Kolbb7b115e2010-09-25 16:59:37 -0700126 tab.setActivated(false);
Michael Kolbfe251992010-07-08 15:41:55 -0700127 }
128
Michael Kolbfe251992010-07-08 15:41:55 -0700129 void removeTab(View tab) {
Michael Kolbbdc2a242010-09-07 13:48:07 -0700130 int ix = mContentView.indexOfChild(tab);
131 if (ix == mSelected) {
132 mSelected = -1;
133 } else if (ix < mSelected) {
134 mSelected--;
135 }
Michael Kolb27b08392010-10-04 12:49:23 -0700136 animateOut(tab);
Michael Kolbfe251992010-07-08 15:41:55 -0700137 }
138
Michael Kolb27b08392010-10-04 12:49:23 -0700139 private void ensureChildVisible(View child) {
Michael Kolbfe251992010-07-08 15:41:55 -0700140 if (child != null) {
141 int childl = child.getLeft();
142 int childr = childl + child.getWidth();
143 int viewl = getScrollX();
144 int viewr = viewl + getWidth();
145 if (childl < viewl) {
146 // need scrolling to left
Michael Kolb27b08392010-10-04 12:49:23 -0700147 animateScroll(childl);
Michael Kolbfe251992010-07-08 15:41:55 -0700148 } else if (childr > viewr) {
149 // need scrolling to right
Michael Kolb27b08392010-10-04 12:49:23 -0700150 animateScroll(childr - viewr + viewl);
Michael Kolbfe251992010-07-08 15:41:55 -0700151 }
152 }
153 }
154
Michael Kolbc3503762010-10-03 14:45:11 -0700155 @Override
156 protected void dispatchDraw(Canvas canvas) {
157 super.dispatchDraw(canvas);
158 int l = getScrollX();
159 int r = l + getWidth();
160 int dis = 8;
161 if (l > 0) {
162 int aw = mArrowLeft.getIntrinsicWidth();
163 mArrowLeft.setBounds(l + dis, 0, l + dis + aw, getHeight());
164 mArrowLeft.draw(canvas);
165 }
166 if (r < mContentView.getWidth()) {
167 int aw = mArrowRight.getIntrinsicWidth();
168 mArrowRight.setBounds(r - dis - aw, 0, r - dis, getHeight());
169 mArrowRight.draw(canvas);
170 }
171 }
172
Michael Kolb27b08392010-10-04 12:49:23 -0700173 private void animateIn(View tab) {
174 ObjectAnimator animator = new ObjectAnimator<PropertyValuesHolder>(
175 mAnimationDuration, tab,
176 new PropertyValuesHolder<Integer>("TranslationX", 500, 0));
177 animator.start();
178 }
179
180 private void animateOut(final View tab) {
181 ObjectAnimator animator = new ObjectAnimator<PropertyValuesHolder>(
182 mAnimationDuration, tab,
183 new PropertyValuesHolder<Integer>("TranslationX", 0,
184 getScrollX() - tab.getRight()));
185 animator.addListener(new AnimatorListener() {
186
187 @Override
188 public void onAnimationCancel(Animator animation) {
189 }
190
191 @Override
192 public void onAnimationEnd(Animator animation) {
193 mContentView.removeView(tab);
194 }
195
196 @Override
197 public void onAnimationRepeat(Animator animation) {
198 }
199
200 @Override
201 public void onAnimationStart(Animator animation) {
202 }
203 });
204 animator.setInterpolator(new AccelerateInterpolator());
205 animator.start();
206 }
207
208 private void animateScroll(int newscroll) {
209 ObjectAnimator animator = new ObjectAnimator<PropertyValuesHolder>(
210 mAnimationDuration, this,
211 new PropertyValuesHolder<Integer>("scroll", getScrollX(), newscroll));
212 animator.start();
213 }
214
215 /**
216 * required for animation
217 */
218 public void setScroll(int newscroll) {
219 scrollTo(newscroll, getScrollY());
220 }
221
222 /**
223 * required for animation
224 */
225 public int getScroll() {
226 return getScrollX();
227 }
228
Michael Kolbfe251992010-07-08 15:41:55 -0700229}