blob: 7268ddcf479032c9795fc22043236fa2ef6942e2 [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;
Chet Haaseb3a00ab2010-10-14 07:01:46 -070021import android.animation.AnimatorListenerAdapter;
Michael Kolb27b08392010-10-04 12:49:23 -070022import android.animation.ObjectAnimator;
23import android.animation.PropertyValuesHolder;
Michael Kolbfe251992010-07-08 15:41:55 -070024import android.content.Context;
Michael Kolbc3503762010-10-03 14:45:11 -070025import android.graphics.Canvas;
26import android.graphics.drawable.Drawable;
Michael Kolbfe251992010-07-08 15:41:55 -070027import android.util.AttributeSet;
28import android.view.View;
Michael Kolb27b08392010-10-04 12:49:23 -070029import android.view.animation.AccelerateInterpolator;
Michael Kolbfe251992010-07-08 15:41:55 -070030import android.widget.HorizontalScrollView;
31import android.widget.LinearLayout;
32
33/**
34 * custom view for displaying tabs in the tabbed title bar
35 */
36public class TabScrollView extends HorizontalScrollView {
37
Michael Kolbebba8b42010-09-30 12:57:59 -070038 private BrowserActivity mBrowserActivity;
Michael Kolbfe251992010-07-08 15:41:55 -070039 private LinearLayout mContentView;
Michael Kolbfe251992010-07-08 15:41:55 -070040 private int mSelected;
Michael Kolbc3503762010-10-03 14:45:11 -070041 private Drawable mArrowLeft;
42 private Drawable mArrowRight;
Michael Kolb27b08392010-10-04 12:49:23 -070043 private int mAnimationDuration;
Michael Kolbfe251992010-07-08 15:41:55 -070044
45 /**
46 * @param context
47 * @param attrs
48 * @param defStyle
49 */
50 public TabScrollView(Context context, AttributeSet attrs, int defStyle) {
51 super(context, attrs, defStyle);
52 init(context);
53 }
54
55 /**
56 * @param context
57 * @param attrs
58 */
59 public TabScrollView(Context context, AttributeSet attrs) {
60 super(context, attrs);
61 init(context);
62 }
63
64 /**
65 * @param context
66 */
67 public TabScrollView(Context context) {
68 super(context);
69 init(context);
70 }
71
72 private void init(Context ctx) {
Michael Kolb27b08392010-10-04 12:49:23 -070073 mBrowserActivity = (BrowserActivity) ctx;
74 mAnimationDuration = ctx.getResources().getInteger(
75 R.integer.tab_animation_duration);
Michael Kolbfe251992010-07-08 15:41:55 -070076 setHorizontalScrollBarEnabled(false);
Michael Kolbebba8b42010-09-30 12:57:59 -070077 mContentView = new LinearLayout(mBrowserActivity);
Michael Kolbfe251992010-07-08 15:41:55 -070078 mContentView.setOrientation(LinearLayout.HORIZONTAL);
Michael Kolb27b08392010-10-04 12:49:23 -070079 mContentView.setLayoutParams(
80 new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT));
Michael Kolbfe251992010-07-08 15:41:55 -070081 addView(mContentView);
82 mSelected = -1;
Michael Kolbc3503762010-10-03 14:45:11 -070083 mArrowLeft = ctx.getResources().getDrawable(R.drawable.ic_arrow_left);
84 mArrowRight = ctx.getResources().getDrawable(R.drawable.ic_arrow_right);
Michael Kolb27b08392010-10-04 12:49:23 -070085 // prevent ProGuard from removing the property methods
86 setScroll(getScroll());
Michael Kolbfe251992010-07-08 15:41:55 -070087 }
88
89 @Override
90 protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
91 super.onLayout(changed, left, top, right, bottom);
92 ensureChildVisible(getSelectedTab());
93 }
94
95 void setSelectedTab(int position) {
96 View v = getSelectedTab();
97 if (v != null) {
Michael Kolbb7b115e2010-09-25 16:59:37 -070098 v.setActivated(false);
Michael Kolbfe251992010-07-08 15:41:55 -070099 }
100 mSelected = position;
101 v = getSelectedTab();
102 if (v != null) {
Michael Kolbb7b115e2010-09-25 16:59:37 -0700103 v.setActivated(true);
Michael Kolbfe251992010-07-08 15:41:55 -0700104 }
105 requestLayout();
106 }
107
Michael Kolbebba8b42010-09-30 12:57:59 -0700108 int getChildIndex(View v) {
109 return mContentView.indexOfChild(v);
110 }
111
Michael Kolbfe251992010-07-08 15:41:55 -0700112 View getSelectedTab() {
113 if ((mSelected >= 0) && (mSelected < mContentView.getChildCount())) {
114 return mContentView.getChildAt(mSelected);
115 } else {
116 return null;
117 }
118 }
119
120 void clearTabs() {
121 mContentView.removeAllViews();
122 }
123
124 void addTab(View tab) {
125 mContentView.addView(tab);
Michael Kolb27b08392010-10-04 12:49:23 -0700126 animateIn(tab);
Michael Kolbb7b115e2010-09-25 16:59:37 -0700127 tab.setActivated(false);
Michael Kolbfe251992010-07-08 15:41:55 -0700128 }
129
Michael Kolbfe251992010-07-08 15:41:55 -0700130 void removeTab(View tab) {
Michael Kolbbdc2a242010-09-07 13:48:07 -0700131 int ix = mContentView.indexOfChild(tab);
132 if (ix == mSelected) {
133 mSelected = -1;
134 } else if (ix < mSelected) {
135 mSelected--;
136 }
Michael Kolb27b08392010-10-04 12:49:23 -0700137 animateOut(tab);
Michael Kolbfe251992010-07-08 15:41:55 -0700138 }
139
Michael Kolb27b08392010-10-04 12:49:23 -0700140 private void ensureChildVisible(View child) {
Michael Kolbfe251992010-07-08 15:41:55 -0700141 if (child != null) {
142 int childl = child.getLeft();
143 int childr = childl + child.getWidth();
144 int viewl = getScrollX();
145 int viewr = viewl + getWidth();
146 if (childl < viewl) {
147 // need scrolling to left
Michael Kolb27b08392010-10-04 12:49:23 -0700148 animateScroll(childl);
Michael Kolbfe251992010-07-08 15:41:55 -0700149 } else if (childr > viewr) {
150 // need scrolling to right
Michael Kolb27b08392010-10-04 12:49:23 -0700151 animateScroll(childr - viewr + viewl);
Michael Kolbfe251992010-07-08 15:41:55 -0700152 }
153 }
154 }
155
Michael Kolbc3503762010-10-03 14:45:11 -0700156 @Override
157 protected void dispatchDraw(Canvas canvas) {
158 super.dispatchDraw(canvas);
159 int l = getScrollX();
160 int r = l + getWidth();
161 int dis = 8;
162 if (l > 0) {
163 int aw = mArrowLeft.getIntrinsicWidth();
164 mArrowLeft.setBounds(l + dis, 0, l + dis + aw, getHeight());
165 mArrowLeft.draw(canvas);
166 }
167 if (r < mContentView.getWidth()) {
168 int aw = mArrowRight.getIntrinsicWidth();
169 mArrowRight.setBounds(r - dis - aw, 0, r - dis, getHeight());
170 mArrowRight.draw(canvas);
171 }
172 }
173
Michael Kolb27b08392010-10-04 12:49:23 -0700174 private void animateIn(View tab) {
Chet Haaseb3a00ab2010-10-14 07:01:46 -0700175 ObjectAnimator animator = ObjectAnimator.ofInt(tab, "TranslationX", 500, 0);
176 animator.setDuration(mAnimationDuration);
Michael Kolb27b08392010-10-04 12:49:23 -0700177 animator.start();
178 }
179
180 private void animateOut(final View tab) {
Chet Haaseb3a00ab2010-10-14 07:01:46 -0700181 ObjectAnimator animator = ObjectAnimator.ofInt(
182 tab, "TranslationX", 0, getScrollX() - tab.getRight());
183 animator.setDuration(mAnimationDuration);
184 animator.addListener(new AnimatorListenerAdapter() {
Michael Kolb27b08392010-10-04 12:49:23 -0700185 @Override
186 public void onAnimationEnd(Animator animation) {
187 mContentView.removeView(tab);
188 }
Michael Kolb27b08392010-10-04 12:49:23 -0700189 });
190 animator.setInterpolator(new AccelerateInterpolator());
191 animator.start();
192 }
193
194 private void animateScroll(int newscroll) {
Chet Haaseb3a00ab2010-10-14 07:01:46 -0700195 ObjectAnimator animator = ObjectAnimator.ofInt(this, "scroll", getScrollX(), newscroll);
196 animator.setDuration(mAnimationDuration);
Michael Kolb27b08392010-10-04 12:49:23 -0700197 animator.start();
198 }
199
200 /**
201 * required for animation
202 */
203 public void setScroll(int newscroll) {
204 scrollTo(newscroll, getScrollY());
205 }
206
207 /**
208 * required for animation
209 */
210 public int getScroll() {
211 return getScrollX();
212 }
213
Michael Kolbfe251992010-07-08 15:41:55 -0700214}