blob: f43d6d68b7b3e4fb283bc021e1d14cbd9c5f01f1 [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 Kolb678afc82011-05-17 14:52:41 -070019import com.android.browser.TabBar.TabView;
20
Michael Kolb27b08392010-10-04 12:49:23 -070021import android.animation.ObjectAnimator;
Michael Kolbfe251992010-07-08 15:41:55 -070022import android.content.Context;
23import android.util.AttributeSet;
24import android.view.View;
25import android.widget.HorizontalScrollView;
26import android.widget.LinearLayout;
27
28/**
29 * custom view for displaying tabs in the tabbed title bar
30 */
31public class TabScrollView extends HorizontalScrollView {
32
Michael Kolbfe251992010-07-08 15:41:55 -070033 private LinearLayout mContentView;
Michael Kolbfe251992010-07-08 15:41:55 -070034 private int mSelected;
Michael Kolb27b08392010-10-04 12:49:23 -070035 private int mAnimationDuration;
Michael Kolb2b5a13a2010-12-09 14:13:42 -080036 private int mTabOverlap;
Michael Kolbfe251992010-07-08 15:41:55 -070037
38 /**
39 * @param context
40 * @param attrs
41 * @param defStyle
42 */
43 public TabScrollView(Context context, AttributeSet attrs, int defStyle) {
44 super(context, attrs, defStyle);
45 init(context);
46 }
47
48 /**
49 * @param context
50 * @param attrs
51 */
52 public TabScrollView(Context context, AttributeSet attrs) {
53 super(context, attrs);
54 init(context);
55 }
56
57 /**
58 * @param context
59 */
60 public TabScrollView(Context context) {
61 super(context);
62 init(context);
63 }
64
65 private void init(Context ctx) {
Michael Kolb27b08392010-10-04 12:49:23 -070066 mAnimationDuration = ctx.getResources().getInteger(
67 R.integer.tab_animation_duration);
Michael Kolb2b5a13a2010-12-09 14:13:42 -080068 mTabOverlap = (int) ctx.getResources().getDimension(R.dimen.tab_overlap);
Michael Kolbfe251992010-07-08 15:41:55 -070069 setHorizontalScrollBarEnabled(false);
Michael Kolb2b5a13a2010-12-09 14:13:42 -080070 setOverScrollMode(OVER_SCROLL_NEVER);
Romain Guye3989562011-01-27 12:06:29 -080071 mContentView = new TabLayout(ctx);
Michael Kolbfe251992010-07-08 15:41:55 -070072 mContentView.setOrientation(LinearLayout.HORIZONTAL);
Michael Kolb27b08392010-10-04 12:49:23 -070073 mContentView.setLayoutParams(
74 new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT));
Michael Kolbf558f0d2011-01-13 19:24:18 -080075 mContentView.setPadding(
76 (int) ctx.getResources().getDimension(R.dimen.tab_first_padding_left),
77 0, 0, 0);
Michael Kolbfe251992010-07-08 15:41:55 -070078 addView(mContentView);
79 mSelected = -1;
Michael Kolb27b08392010-10-04 12:49:23 -070080 // prevent ProGuard from removing the property methods
81 setScroll(getScroll());
Michael Kolbfe251992010-07-08 15:41:55 -070082 }
83
84 @Override
85 protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
86 super.onLayout(changed, left, top, right, bottom);
87 ensureChildVisible(getSelectedTab());
88 }
89
Michael Kolb678afc82011-05-17 14:52:41 -070090 // in case of a configuration change, adjust tab width
91 protected void updateLayout() {
92 final int count = mContentView.getChildCount();
93 for (int i = 0; i < count; i++) {
94 final TabView tv = (TabView) mContentView.getChildAt(i);
95 tv.updateLayoutParams();
96 }
97 ensureChildVisible(getSelectedTab());
98 }
99
Michael Kolbfe251992010-07-08 15:41:55 -0700100 void setSelectedTab(int position) {
101 View v = getSelectedTab();
102 if (v != null) {
Michael Kolbb7b115e2010-09-25 16:59:37 -0700103 v.setActivated(false);
Michael Kolbfe251992010-07-08 15:41:55 -0700104 }
105 mSelected = position;
106 v = getSelectedTab();
107 if (v != null) {
Michael Kolbb7b115e2010-09-25 16:59:37 -0700108 v.setActivated(true);
Michael Kolbfe251992010-07-08 15:41:55 -0700109 }
110 requestLayout();
111 }
112
Michael Kolbebba8b42010-09-30 12:57:59 -0700113 int getChildIndex(View v) {
114 return mContentView.indexOfChild(v);
115 }
116
Michael Kolbfe251992010-07-08 15:41:55 -0700117 View getSelectedTab() {
118 if ((mSelected >= 0) && (mSelected < mContentView.getChildCount())) {
119 return mContentView.getChildAt(mSelected);
120 } else {
121 return null;
122 }
123 }
124
125 void clearTabs() {
126 mContentView.removeAllViews();
127 }
128
129 void addTab(View tab) {
130 mContentView.addView(tab);
Michael Kolbb7b115e2010-09-25 16:59:37 -0700131 tab.setActivated(false);
Michael Kolbfe251992010-07-08 15:41:55 -0700132 }
133
Michael Kolbfe251992010-07-08 15:41:55 -0700134 void removeTab(View tab) {
Michael Kolbbdc2a242010-09-07 13:48:07 -0700135 int ix = mContentView.indexOfChild(tab);
136 if (ix == mSelected) {
137 mSelected = -1;
138 } else if (ix < mSelected) {
139 mSelected--;
140 }
John Reck599e9102011-01-06 20:37:31 -0800141 mContentView.removeView(tab);
Michael Kolbfe251992010-07-08 15:41:55 -0700142 }
143
Michael Kolb27b08392010-10-04 12:49:23 -0700144 private void ensureChildVisible(View child) {
Michael Kolbfe251992010-07-08 15:41:55 -0700145 if (child != null) {
146 int childl = child.getLeft();
147 int childr = childl + child.getWidth();
148 int viewl = getScrollX();
149 int viewr = viewl + getWidth();
150 if (childl < viewl) {
151 // need scrolling to left
Michael Kolb27b08392010-10-04 12:49:23 -0700152 animateScroll(childl);
Michael Kolbfe251992010-07-08 15:41:55 -0700153 } else if (childr > viewr) {
154 // need scrolling to right
Michael Kolb27b08392010-10-04 12:49:23 -0700155 animateScroll(childr - viewr + viewl);
Michael Kolbfe251992010-07-08 15:41:55 -0700156 }
157 }
158 }
159
John Reck599e9102011-01-06 20:37:31 -0800160// TODO: These animations are broken and don't work correctly, removing for now
161// as animateOut is actually causing issues
162// private void animateIn(View tab) {
163// ObjectAnimator animator = ObjectAnimator.ofInt(tab, "TranslationX", 500, 0);
164// animator.setDuration(mAnimationDuration);
165// animator.start();
166// }
167//
168// private void animateOut(final View tab) {
169// ObjectAnimator animator = ObjectAnimator.ofInt(
170// tab, "TranslationX", 0, getScrollX() - tab.getRight());
171// animator.setDuration(mAnimationDuration);
172// animator.addListener(new AnimatorListenerAdapter() {
173// @Override
174// public void onAnimationEnd(Animator animation) {
175// mContentView.removeView(tab);
176// }
177// });
178// animator.setInterpolator(new AccelerateInterpolator());
179// animator.start();
180// }
Michael Kolb27b08392010-10-04 12:49:23 -0700181
182 private void animateScroll(int newscroll) {
Chet Haaseb3a00ab2010-10-14 07:01:46 -0700183 ObjectAnimator animator = ObjectAnimator.ofInt(this, "scroll", getScrollX(), newscroll);
184 animator.setDuration(mAnimationDuration);
Michael Kolb27b08392010-10-04 12:49:23 -0700185 animator.start();
186 }
187
188 /**
189 * required for animation
190 */
191 public void setScroll(int newscroll) {
192 scrollTo(newscroll, getScrollY());
193 }
194
195 /**
196 * required for animation
197 */
198 public int getScroll() {
199 return getScrollX();
200 }
201
Romain Guye3989562011-01-27 12:06:29 -0800202 @Override
203 protected void onScrollChanged(int l, int t, int oldl, int oldt) {
204 super.onScrollChanged(l, t, oldl, oldt);
205
206 // TabViews base their drawing based on their absolute position within the
207 // window. When hardware accelerated, we need to recreate their display list
208 // when they scroll
209 if (isHardwareAccelerated()) {
210 int count = mContentView.getChildCount();
211 for (int i = 0; i < count; i++) {
212 mContentView.getChildAt(i).invalidate();
213 }
214 }
215 }
216
Michael Kolb2b5a13a2010-12-09 14:13:42 -0800217 class TabLayout extends LinearLayout {
218
219 public TabLayout(Context context) {
220 super(context);
221 setChildrenDrawingOrderEnabled(true);
222 }
223
224 @Override
225 protected void onMeasure(int hspec, int vspec) {
226 super.onMeasure(hspec, vspec);
227 int w = getMeasuredWidth();
228 w -= Math.max(0, mContentView.getChildCount() - 1) * mTabOverlap;
229 setMeasuredDimension(w, getMeasuredHeight());
230 }
231
232 @Override
233 protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
234 super.onLayout(changed, left, top, right, bottom);
235 if (getChildCount() > 1) {
236 int nextLeft = getChildAt(0).getRight() - mTabOverlap;
237 for (int i = 1; i < getChildCount(); i++) {
238 View tab = getChildAt(i);
239 int w = tab.getRight() - tab.getLeft();
240 tab.layout(nextLeft, tab.getTop(), nextLeft + w, tab.getBottom());
241 nextLeft += w - mTabOverlap;
242 }
243 }
244 }
245
246 @Override
247 protected int getChildDrawingOrder(int count, int i) {
248 int next = -1;
249 if ((i == (count - 1)) && (mSelected >= 0)) {
250 next = mSelected;
251 } else {
252 next = count - i - 1;
253 if (next <= mSelected) {
254 next--;
255 }
256 }
257 return next;
258 }
259
260 }
261
Michael Kolbfe251992010-07-08 15:41:55 -0700262}