blob: 09dddee44c0256298c4cedb793441e7edbe6e33c [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.ObjectAnimator;
Michael Kolbfe251992010-07-08 15:41:55 -070020import android.content.Context;
21import android.util.AttributeSet;
22import android.view.View;
23import android.widget.HorizontalScrollView;
24import android.widget.LinearLayout;
25
26/**
27 * custom view for displaying tabs in the tabbed title bar
28 */
29public class TabScrollView extends HorizontalScrollView {
30
Michael Kolb8233fac2010-10-26 16:08:53 -070031 private Context mContext;
Michael Kolbfe251992010-07-08 15:41:55 -070032 private LinearLayout mContentView;
Michael Kolbfe251992010-07-08 15:41:55 -070033 private int mSelected;
Michael Kolb27b08392010-10-04 12:49:23 -070034 private int mAnimationDuration;
Michael Kolb2b5a13a2010-12-09 14:13:42 -080035 private int mTabOverlap;
Michael Kolbfe251992010-07-08 15:41:55 -070036
37 /**
38 * @param context
39 * @param attrs
40 * @param defStyle
41 */
42 public TabScrollView(Context context, AttributeSet attrs, int defStyle) {
43 super(context, attrs, defStyle);
44 init(context);
45 }
46
47 /**
48 * @param context
49 * @param attrs
50 */
51 public TabScrollView(Context context, AttributeSet attrs) {
52 super(context, attrs);
53 init(context);
54 }
55
56 /**
57 * @param context
58 */
59 public TabScrollView(Context context) {
60 super(context);
61 init(context);
62 }
63
64 private void init(Context ctx) {
Michael Kolb8233fac2010-10-26 16:08:53 -070065 mContext = 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);
71 mContentView = new TabLayout(mContext);
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
90 void setSelectedTab(int position) {
91 View v = getSelectedTab();
92 if (v != null) {
Michael Kolbb7b115e2010-09-25 16:59:37 -070093 v.setActivated(false);
Michael Kolbfe251992010-07-08 15:41:55 -070094 }
95 mSelected = position;
96 v = getSelectedTab();
97 if (v != null) {
Michael Kolbb7b115e2010-09-25 16:59:37 -070098 v.setActivated(true);
Michael Kolbfe251992010-07-08 15:41:55 -070099 }
100 requestLayout();
101 }
102
Michael Kolbebba8b42010-09-30 12:57:59 -0700103 int getChildIndex(View v) {
104 return mContentView.indexOfChild(v);
105 }
106
Michael Kolbfe251992010-07-08 15:41:55 -0700107 View getSelectedTab() {
108 if ((mSelected >= 0) && (mSelected < mContentView.getChildCount())) {
109 return mContentView.getChildAt(mSelected);
110 } else {
111 return null;
112 }
113 }
114
115 void clearTabs() {
116 mContentView.removeAllViews();
117 }
118
119 void addTab(View tab) {
120 mContentView.addView(tab);
Michael Kolbb7b115e2010-09-25 16:59:37 -0700121 tab.setActivated(false);
Michael Kolbfe251992010-07-08 15:41:55 -0700122 }
123
Michael Kolbfe251992010-07-08 15:41:55 -0700124 void removeTab(View tab) {
Michael Kolbbdc2a242010-09-07 13:48:07 -0700125 int ix = mContentView.indexOfChild(tab);
126 if (ix == mSelected) {
127 mSelected = -1;
128 } else if (ix < mSelected) {
129 mSelected--;
130 }
John Reck599e9102011-01-06 20:37:31 -0800131 mContentView.removeView(tab);
Michael Kolbfe251992010-07-08 15:41:55 -0700132 }
133
Michael Kolb27b08392010-10-04 12:49:23 -0700134 private void ensureChildVisible(View child) {
Michael Kolbfe251992010-07-08 15:41:55 -0700135 if (child != null) {
136 int childl = child.getLeft();
137 int childr = childl + child.getWidth();
138 int viewl = getScrollX();
139 int viewr = viewl + getWidth();
140 if (childl < viewl) {
141 // need scrolling to left
Michael Kolb27b08392010-10-04 12:49:23 -0700142 animateScroll(childl);
Michael Kolbfe251992010-07-08 15:41:55 -0700143 } else if (childr > viewr) {
144 // need scrolling to right
Michael Kolb27b08392010-10-04 12:49:23 -0700145 animateScroll(childr - viewr + viewl);
Michael Kolbfe251992010-07-08 15:41:55 -0700146 }
147 }
148 }
149
John Reck599e9102011-01-06 20:37:31 -0800150// TODO: These animations are broken and don't work correctly, removing for now
151// as animateOut is actually causing issues
152// private void animateIn(View tab) {
153// ObjectAnimator animator = ObjectAnimator.ofInt(tab, "TranslationX", 500, 0);
154// animator.setDuration(mAnimationDuration);
155// animator.start();
156// }
157//
158// private void animateOut(final View tab) {
159// ObjectAnimator animator = ObjectAnimator.ofInt(
160// tab, "TranslationX", 0, getScrollX() - tab.getRight());
161// animator.setDuration(mAnimationDuration);
162// animator.addListener(new AnimatorListenerAdapter() {
163// @Override
164// public void onAnimationEnd(Animator animation) {
165// mContentView.removeView(tab);
166// }
167// });
168// animator.setInterpolator(new AccelerateInterpolator());
169// animator.start();
170// }
Michael Kolb27b08392010-10-04 12:49:23 -0700171
172 private void animateScroll(int newscroll) {
Chet Haaseb3a00ab2010-10-14 07:01:46 -0700173 ObjectAnimator animator = ObjectAnimator.ofInt(this, "scroll", getScrollX(), newscroll);
174 animator.setDuration(mAnimationDuration);
Michael Kolb27b08392010-10-04 12:49:23 -0700175 animator.start();
176 }
177
178 /**
179 * required for animation
180 */
181 public void setScroll(int newscroll) {
182 scrollTo(newscroll, getScrollY());
183 }
184
185 /**
186 * required for animation
187 */
188 public int getScroll() {
189 return getScrollX();
190 }
191
Michael Kolb2b5a13a2010-12-09 14:13:42 -0800192 class TabLayout extends LinearLayout {
193
194 public TabLayout(Context context) {
195 super(context);
196 setChildrenDrawingOrderEnabled(true);
197 }
198
199 @Override
200 protected void onMeasure(int hspec, int vspec) {
201 super.onMeasure(hspec, vspec);
202 int w = getMeasuredWidth();
203 w -= Math.max(0, mContentView.getChildCount() - 1) * mTabOverlap;
204 setMeasuredDimension(w, getMeasuredHeight());
205 }
206
207 @Override
208 protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
209 super.onLayout(changed, left, top, right, bottom);
210 if (getChildCount() > 1) {
211 int nextLeft = getChildAt(0).getRight() - mTabOverlap;
212 for (int i = 1; i < getChildCount(); i++) {
213 View tab = getChildAt(i);
214 int w = tab.getRight() - tab.getLeft();
215 tab.layout(nextLeft, tab.getTop(), nextLeft + w, tab.getBottom());
216 nextLeft += w - mTabOverlap;
217 }
218 }
219 }
220
221 @Override
222 protected int getChildDrawingOrder(int count, int i) {
223 int next = -1;
224 if ((i == (count - 1)) && (mSelected >= 0)) {
225 next = mSelected;
226 } else {
227 next = count - i - 1;
228 if (next <= mSelected) {
229 next--;
230 }
231 }
232 return next;
233 }
234
235 }
236
Michael Kolbfe251992010-07-08 15:41:55 -0700237}