blob: 1df88cc806abc8c1f2cbe1f6bbf6c064d93a5912 [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
Bijan Amirzada41242f22014-03-21 12:12:18 -070017package com.android.browser;
Michael Kolbfe251992010-07-08 15:41:55 -070018
Bijan Amirzada41242f22014-03-21 12:12:18 -070019import com.android.browser.R;
20import com.android.browser.TabBar.TabView;
Michael Kolb678afc82011-05-17 14:52:41 -070021
Michael Kolb27b08392010-10-04 12:49:23 -070022import android.animation.ObjectAnimator;
Michael Kolbfe251992010-07-08 15:41:55 -070023import android.content.Context;
24import android.util.AttributeSet;
25import android.view.View;
26import android.widget.HorizontalScrollView;
27import android.widget.LinearLayout;
28
29/**
30 * custom view for displaying tabs in the tabbed title bar
31 */
32public class TabScrollView extends HorizontalScrollView {
33
Michael Kolbfe251992010-07-08 15:41:55 -070034 private LinearLayout mContentView;
Michael Kolbfe251992010-07-08 15:41:55 -070035 private int mSelected;
Michael Kolb27b08392010-10-04 12:49:23 -070036 private int mAnimationDuration;
Michael Kolb2b5a13a2010-12-09 14:13:42 -080037 private int mTabOverlap;
Michael Kolbfe251992010-07-08 15:41:55 -070038
39 /**
40 * @param context
41 * @param attrs
42 * @param defStyle
43 */
44 public TabScrollView(Context context, AttributeSet attrs, int defStyle) {
45 super(context, attrs, defStyle);
46 init(context);
47 }
48
49 /**
50 * @param context
51 * @param attrs
52 */
53 public TabScrollView(Context context, AttributeSet attrs) {
54 super(context, attrs);
55 init(context);
56 }
57
58 /**
59 * @param context
60 */
61 public TabScrollView(Context context) {
62 super(context);
63 init(context);
64 }
65
66 private void init(Context ctx) {
Michael Kolb27b08392010-10-04 12:49:23 -070067 mAnimationDuration = ctx.getResources().getInteger(
68 R.integer.tab_animation_duration);
Michael Kolb2b5a13a2010-12-09 14:13:42 -080069 mTabOverlap = (int) ctx.getResources().getDimension(R.dimen.tab_overlap);
Michael Kolbfe251992010-07-08 15:41:55 -070070 setHorizontalScrollBarEnabled(false);
Michael Kolb2b5a13a2010-12-09 14:13:42 -080071 setOverScrollMode(OVER_SCROLL_NEVER);
Romain Guye3989562011-01-27 12:06:29 -080072 mContentView = new TabLayout(ctx);
Michael Kolbfe251992010-07-08 15:41:55 -070073 mContentView.setOrientation(LinearLayout.HORIZONTAL);
Michael Kolb27b08392010-10-04 12:49:23 -070074 mContentView.setLayoutParams(
75 new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT));
Michael Kolbf558f0d2011-01-13 19:24:18 -080076 mContentView.setPadding(
77 (int) ctx.getResources().getDimension(R.dimen.tab_first_padding_left),
78 0, 0, 0);
Michael Kolbfe251992010-07-08 15:41:55 -070079 addView(mContentView);
80 mSelected = -1;
Michael Kolb27b08392010-10-04 12:49:23 -070081 // prevent ProGuard from removing the property methods
82 setScroll(getScroll());
Michael Kolbfe251992010-07-08 15:41:55 -070083 }
84
85 @Override
86 protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
87 super.onLayout(changed, left, top, right, bottom);
88 ensureChildVisible(getSelectedTab());
89 }
90
Michael Kolb678afc82011-05-17 14:52:41 -070091 // in case of a configuration change, adjust tab width
92 protected void updateLayout() {
93 final int count = mContentView.getChildCount();
94 for (int i = 0; i < count; i++) {
95 final TabView tv = (TabView) mContentView.getChildAt(i);
96 tv.updateLayoutParams();
97 }
98 ensureChildVisible(getSelectedTab());
99 }
100
Michael Kolbfe251992010-07-08 15:41:55 -0700101 void setSelectedTab(int position) {
102 View v = getSelectedTab();
103 if (v != null) {
Michael Kolbb7b115e2010-09-25 16:59:37 -0700104 v.setActivated(false);
Michael Kolbfe251992010-07-08 15:41:55 -0700105 }
106 mSelected = position;
107 v = getSelectedTab();
108 if (v != null) {
Michael Kolbb7b115e2010-09-25 16:59:37 -0700109 v.setActivated(true);
Michael Kolbfe251992010-07-08 15:41:55 -0700110 }
111 requestLayout();
112 }
113
Michael Kolbebba8b42010-09-30 12:57:59 -0700114 int getChildIndex(View v) {
115 return mContentView.indexOfChild(v);
116 }
117
Michael Kolbfe251992010-07-08 15:41:55 -0700118 View getSelectedTab() {
119 if ((mSelected >= 0) && (mSelected < mContentView.getChildCount())) {
120 return mContentView.getChildAt(mSelected);
121 } else {
122 return null;
123 }
124 }
125
126 void clearTabs() {
127 mContentView.removeAllViews();
128 }
129
130 void addTab(View tab) {
131 mContentView.addView(tab);
Michael Kolbb7b115e2010-09-25 16:59:37 -0700132 tab.setActivated(false);
Michael Kolbfe251992010-07-08 15:41:55 -0700133 }
134
Michael Kolbfe251992010-07-08 15:41:55 -0700135 void removeTab(View tab) {
Michael Kolbbdc2a242010-09-07 13:48:07 -0700136 int ix = mContentView.indexOfChild(tab);
137 if (ix == mSelected) {
138 mSelected = -1;
139 } else if (ix < mSelected) {
140 mSelected--;
141 }
John Reck599e9102011-01-06 20:37:31 -0800142 mContentView.removeView(tab);
Michael Kolbfe251992010-07-08 15:41:55 -0700143 }
144
Michael Kolb27b08392010-10-04 12:49:23 -0700145 private void ensureChildVisible(View child) {
Michael Kolbfe251992010-07-08 15:41:55 -0700146 if (child != null) {
147 int childl = child.getLeft();
148 int childr = childl + child.getWidth();
149 int viewl = getScrollX();
150 int viewr = viewl + getWidth();
151 if (childl < viewl) {
152 // need scrolling to left
Michael Kolb27b08392010-10-04 12:49:23 -0700153 animateScroll(childl);
Michael Kolbfe251992010-07-08 15:41:55 -0700154 } else if (childr > viewr) {
155 // need scrolling to right
Michael Kolb27b08392010-10-04 12:49:23 -0700156 animateScroll(childr - viewr + viewl);
Michael Kolbfe251992010-07-08 15:41:55 -0700157 }
158 }
159 }
160
John Reck599e9102011-01-06 20:37:31 -0800161// TODO: These animations are broken and don't work correctly, removing for now
162// as animateOut is actually causing issues
163// private void animateIn(View tab) {
164// ObjectAnimator animator = ObjectAnimator.ofInt(tab, "TranslationX", 500, 0);
165// animator.setDuration(mAnimationDuration);
166// animator.start();
167// }
168//
169// private void animateOut(final View tab) {
170// ObjectAnimator animator = ObjectAnimator.ofInt(
171// tab, "TranslationX", 0, getScrollX() - tab.getRight());
172// animator.setDuration(mAnimationDuration);
173// animator.addListener(new AnimatorListenerAdapter() {
174// @Override
175// public void onAnimationEnd(Animator animation) {
176// mContentView.removeView(tab);
177// }
178// });
179// animator.setInterpolator(new AccelerateInterpolator());
180// animator.start();
181// }
Michael Kolb27b08392010-10-04 12:49:23 -0700182
183 private void animateScroll(int newscroll) {
Chet Haaseb3a00ab2010-10-14 07:01:46 -0700184 ObjectAnimator animator = ObjectAnimator.ofInt(this, "scroll", getScrollX(), newscroll);
185 animator.setDuration(mAnimationDuration);
Michael Kolb27b08392010-10-04 12:49:23 -0700186 animator.start();
187 }
188
189 /**
190 * required for animation
191 */
192 public void setScroll(int newscroll) {
193 scrollTo(newscroll, getScrollY());
194 }
195
196 /**
197 * required for animation
198 */
199 public int getScroll() {
200 return getScrollX();
201 }
202
Romain Guye3989562011-01-27 12:06:29 -0800203 @Override
204 protected void onScrollChanged(int l, int t, int oldl, int oldt) {
205 super.onScrollChanged(l, t, oldl, oldt);
206
207 // TabViews base their drawing based on their absolute position within the
208 // window. When hardware accelerated, we need to recreate their display list
209 // when they scroll
210 if (isHardwareAccelerated()) {
211 int count = mContentView.getChildCount();
212 for (int i = 0; i < count; i++) {
213 mContentView.getChildAt(i).invalidate();
214 }
215 }
216 }
217
Michael Kolb2b5a13a2010-12-09 14:13:42 -0800218 class TabLayout extends LinearLayout {
219
220 public TabLayout(Context context) {
221 super(context);
222 setChildrenDrawingOrderEnabled(true);
223 }
224
225 @Override
226 protected void onMeasure(int hspec, int vspec) {
227 super.onMeasure(hspec, vspec);
228 int w = getMeasuredWidth();
229 w -= Math.max(0, mContentView.getChildCount() - 1) * mTabOverlap;
230 setMeasuredDimension(w, getMeasuredHeight());
231 }
232
233 @Override
234 protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
235 super.onLayout(changed, left, top, right, bottom);
236 if (getChildCount() > 1) {
237 int nextLeft = getChildAt(0).getRight() - mTabOverlap;
238 for (int i = 1; i < getChildCount(); i++) {
239 View tab = getChildAt(i);
240 int w = tab.getRight() - tab.getLeft();
241 tab.layout(nextLeft, tab.getTop(), nextLeft + w, tab.getBottom());
242 nextLeft += w - mTabOverlap;
243 }
244 }
245 }
246
247 @Override
248 protected int getChildDrawingOrder(int count, int i) {
249 int next = -1;
Mathew Inwood075d4932011-06-29 15:38:18 +0100250 if ((i == (count - 1)) && (mSelected >= 0) && (mSelected < count)) {
Michael Kolb2b5a13a2010-12-09 14:13:42 -0800251 next = mSelected;
252 } else {
253 next = count - i - 1;
Mathew Inwood075d4932011-06-29 15:38:18 +0100254 if (next <= mSelected && next > 0) {
Michael Kolb2b5a13a2010-12-09 14:13:42 -0800255 next--;
256 }
257 }
258 return next;
259 }
260
261 }
262
Michael Kolbfe251992010-07-08 15:41:55 -0700263}