blob: fa29e6e17ab9368630237f052a13de93e41961c7 [file] [log] [blame]
Adam Powellf8ac6b72011-05-23 18:14:09 -07001/*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package com.android.internal.widget;
17
Adam Powellb8139af2012-04-19 13:52:46 -070018import com.android.internal.view.ActionBarPolicy;
Adam Powellfaa6ffa2011-08-08 14:48:02 -070019
Adam Powellf6ce6a92011-06-29 10:25:01 -070020import android.animation.Animator;
21import android.animation.ObjectAnimator;
22import android.animation.TimeInterpolator;
Adam Powellf8ac6b72011-05-23 18:14:09 -070023import android.app.ActionBar;
24import android.content.Context;
Adam Powellfaa6ffa2011-08-08 14:48:02 -070025import android.content.res.Configuration;
Adam Powellc7752a32012-08-24 17:56:41 -070026import android.graphics.Rect;
Adam Powellf8ac6b72011-05-23 18:14:09 -070027import android.graphics.drawable.Drawable;
Adam Powellc7752a32012-08-24 17:56:41 -070028import android.text.TextUtils;
Adam Powellf8ac6b72011-05-23 18:14:09 -070029import android.text.TextUtils.TruncateAt;
30import android.view.Gravity;
31import android.view.View;
32import android.view.ViewGroup;
Adam Powell05c82772011-11-21 17:14:56 -080033import android.view.ViewParent;
Alan Viveretteb9f2e992013-04-15 16:16:11 -070034import android.view.accessibility.AccessibilityEvent;
35import android.view.accessibility.AccessibilityNodeInfo;
Adam Powellf6ce6a92011-06-29 10:25:01 -070036import android.view.animation.DecelerateInterpolator;
Adam Powellf5645cb2011-08-10 22:49:02 -070037import android.widget.AdapterView;
38import android.widget.BaseAdapter;
Adam Powellf8ac6b72011-05-23 18:14:09 -070039import android.widget.HorizontalScrollView;
40import android.widget.ImageView;
41import android.widget.LinearLayout;
Adam Powellf5645cb2011-08-10 22:49:02 -070042import android.widget.ListView;
43import android.widget.Spinner;
Adam Powellf8ac6b72011-05-23 18:14:09 -070044import android.widget.TextView;
Adam Powellc7752a32012-08-24 17:56:41 -070045import android.widget.Toast;
Adam Powellf8ac6b72011-05-23 18:14:09 -070046
Adam Powellf5645cb2011-08-10 22:49:02 -070047/**
48 * This widget implements the dynamic action bar tab behavior that can change
49 * across different configurations or circumstances.
50 */
51public class ScrollingTabContainerView extends HorizontalScrollView
Adam Powellc4e57e22012-02-24 19:24:26 -080052 implements AdapterView.OnItemClickListener {
Adam Powellf5645cb2011-08-10 22:49:02 -070053 private static final String TAG = "ScrollingTabContainerView";
Adam Powellf8ac6b72011-05-23 18:14:09 -070054 Runnable mTabSelector;
55 private TabClickListener mTabClickListener;
56
57 private LinearLayout mTabLayout;
Adam Powellf5645cb2011-08-10 22:49:02 -070058 private Spinner mTabSpinner;
59 private boolean mAllowCollapse;
Adam Powellf8ac6b72011-05-23 18:14:09 -070060
61 int mMaxTabWidth;
Adam Powellb8139af2012-04-19 13:52:46 -070062 int mStackedTabMaxWidth;
Adam Powellf5645cb2011-08-10 22:49:02 -070063 private int mContentHeight;
64 private int mSelectedTabIndex;
Adam Powellf8ac6b72011-05-23 18:14:09 -070065
Adam Powellf6ce6a92011-06-29 10:25:01 -070066 protected Animator mVisibilityAnim;
67 protected final VisibilityAnimListener mVisAnimListener = new VisibilityAnimListener();
68
69 private static final TimeInterpolator sAlphaInterpolator = new DecelerateInterpolator();
70
71 private static final int FADE_DURATION = 200;
72
Adam Powellf8ac6b72011-05-23 18:14:09 -070073 public ScrollingTabContainerView(Context context) {
74 super(context);
75 setHorizontalScrollBarEnabled(false);
Adam Powellf5645cb2011-08-10 22:49:02 -070076
Adam Powellb8139af2012-04-19 13:52:46 -070077 ActionBarPolicy abp = ActionBarPolicy.get(context);
78 setContentHeight(abp.getTabContainerHeight());
79 mStackedTabMaxWidth = abp.getStackedTabMaxWidth();
Adam Powellaf6b97e2011-08-11 17:40:57 -070080
Adam Powellf5645cb2011-08-10 22:49:02 -070081 mTabLayout = createTabLayout();
82 addView(mTabLayout, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
83 ViewGroup.LayoutParams.MATCH_PARENT));
Adam Powellf8ac6b72011-05-23 18:14:09 -070084 }
85
86 @Override
87 public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
88 final int widthMode = MeasureSpec.getMode(widthMeasureSpec);
Adam Powellf5645cb2011-08-10 22:49:02 -070089 final boolean lockedExpanded = widthMode == MeasureSpec.EXACTLY;
90 setFillViewport(lockedExpanded);
Adam Powellf8ac6b72011-05-23 18:14:09 -070091
Adam Powellf5645cb2011-08-10 22:49:02 -070092 final int childCount = mTabLayout.getChildCount();
Adam Powellf8ac6b72011-05-23 18:14:09 -070093 if (childCount > 1 &&
94 (widthMode == MeasureSpec.EXACTLY || widthMode == MeasureSpec.AT_MOST)) {
95 if (childCount > 2) {
96 mMaxTabWidth = (int) (MeasureSpec.getSize(widthMeasureSpec) * 0.4f);
97 } else {
98 mMaxTabWidth = MeasureSpec.getSize(widthMeasureSpec) / 2;
99 }
Adam Powellb8139af2012-04-19 13:52:46 -0700100 mMaxTabWidth = Math.min(mMaxTabWidth, mStackedTabMaxWidth);
Adam Powellf8ac6b72011-05-23 18:14:09 -0700101 } else {
102 mMaxTabWidth = -1;
103 }
104
Adam Powellaf6b97e2011-08-11 17:40:57 -0700105 heightMeasureSpec = MeasureSpec.makeMeasureSpec(mContentHeight, MeasureSpec.EXACTLY);
Adam Powellf5645cb2011-08-10 22:49:02 -0700106
107 final boolean canCollapse = !lockedExpanded && mAllowCollapse;
108
109 if (canCollapse) {
110 // See if we should expand
111 mTabLayout.measure(MeasureSpec.UNSPECIFIED, heightMeasureSpec);
112 if (mTabLayout.getMeasuredWidth() > MeasureSpec.getSize(widthMeasureSpec)) {
113 performCollapse();
114 } else {
115 performExpand();
116 }
117 } else {
118 performExpand();
119 }
120
121 final int oldWidth = getMeasuredWidth();
Adam Powellf8ac6b72011-05-23 18:14:09 -0700122 super.onMeasure(widthMeasureSpec, heightMeasureSpec);
Adam Powellf5645cb2011-08-10 22:49:02 -0700123 final int newWidth = getMeasuredWidth();
124
125 if (lockedExpanded && oldWidth != newWidth) {
126 // Recenter the tab display if we're at a new (scrollable) size.
127 setTabSelected(mSelectedTabIndex);
128 }
129 }
130
131 /**
132 * Indicates whether this view is collapsed into a dropdown menu instead
133 * of traditional tabs.
134 * @return true if showing as a spinner
135 */
136 private boolean isCollapsed() {
137 return mTabSpinner != null && mTabSpinner.getParent() == this;
138 }
139
140 public void setAllowCollapse(boolean allowCollapse) {
141 mAllowCollapse = allowCollapse;
142 }
143
144 private void performCollapse() {
145 if (isCollapsed()) return;
146
147 if (mTabSpinner == null) {
148 mTabSpinner = createSpinner();
149 }
150 removeView(mTabLayout);
151 addView(mTabSpinner, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
152 ViewGroup.LayoutParams.MATCH_PARENT));
153 if (mTabSpinner.getAdapter() == null) {
154 mTabSpinner.setAdapter(new TabAdapter());
155 }
156 if (mTabSelector != null) {
157 removeCallbacks(mTabSelector);
158 mTabSelector = null;
159 }
160 mTabSpinner.setSelection(mSelectedTabIndex);
161 }
162
163 private boolean performExpand() {
164 if (!isCollapsed()) return false;
165
166 removeView(mTabSpinner);
167 addView(mTabLayout, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
168 ViewGroup.LayoutParams.MATCH_PARENT));
169 setTabSelected(mTabSpinner.getSelectedItemPosition());
170 return false;
Adam Powellf8ac6b72011-05-23 18:14:09 -0700171 }
172
173 public void setTabSelected(int position) {
Adam Powellf5645cb2011-08-10 22:49:02 -0700174 mSelectedTabIndex = position;
Adam Powellf8ac6b72011-05-23 18:14:09 -0700175 final int tabCount = mTabLayout.getChildCount();
176 for (int i = 0; i < tabCount; i++) {
177 final View child = mTabLayout.getChildAt(i);
178 final boolean isSelected = i == position;
179 child.setSelected(isSelected);
180 if (isSelected) {
181 animateToTab(position);
182 }
183 }
Adam Powelldaa1d562013-04-09 13:57:22 -0700184 if (mTabSpinner != null && position >= 0) {
185 mTabSpinner.setSelection(position);
186 }
Adam Powellf8ac6b72011-05-23 18:14:09 -0700187 }
188
Adam Powell45c0b192011-07-28 15:11:57 -0700189 public void setContentHeight(int contentHeight) {
Adam Powellf5645cb2011-08-10 22:49:02 -0700190 mContentHeight = contentHeight;
Adam Powell45c0b192011-07-28 15:11:57 -0700191 requestLayout();
192 }
193
Adam Powellf5645cb2011-08-10 22:49:02 -0700194 private LinearLayout createTabLayout() {
195 final LinearLayout tabLayout = new LinearLayout(getContext(), null,
196 com.android.internal.R.attr.actionBarTabBarStyle);
197 tabLayout.setMeasureWithLargestChildEnabled(true);
Adam Powellb8139af2012-04-19 13:52:46 -0700198 tabLayout.setGravity(Gravity.CENTER);
Adam Powellf5645cb2011-08-10 22:49:02 -0700199 tabLayout.setLayoutParams(new LinearLayout.LayoutParams(
200 LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.MATCH_PARENT));
201 return tabLayout;
202 }
203
204 private Spinner createSpinner() {
205 final Spinner spinner = new Spinner(getContext(), null,
206 com.android.internal.R.attr.actionDropDownStyle);
207 spinner.setLayoutParams(new LinearLayout.LayoutParams(
208 LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.MATCH_PARENT));
Adam Powellc4e57e22012-02-24 19:24:26 -0800209 spinner.setOnItemClickListenerInt(this);
Adam Powellf5645cb2011-08-10 22:49:02 -0700210 return spinner;
211 }
212
Adam Powellfaa6ffa2011-08-08 14:48:02 -0700213 @Override
214 protected void onConfigurationChanged(Configuration newConfig) {
215 super.onConfigurationChanged(newConfig);
216
Adam Powellb8139af2012-04-19 13:52:46 -0700217 ActionBarPolicy abp = ActionBarPolicy.get(getContext());
Adam Powellfaa6ffa2011-08-08 14:48:02 -0700218 // Action bar can change size on configuration changes.
219 // Reread the desired height from the theme-specified style.
Adam Powellb8139af2012-04-19 13:52:46 -0700220 setContentHeight(abp.getTabContainerHeight());
221 mStackedTabMaxWidth = abp.getStackedTabMaxWidth();
Adam Powellfaa6ffa2011-08-08 14:48:02 -0700222 }
223
Adam Powellf6ce6a92011-06-29 10:25:01 -0700224 public void animateToVisibility(int visibility) {
225 if (mVisibilityAnim != null) {
226 mVisibilityAnim.cancel();
227 }
228 if (visibility == VISIBLE) {
229 if (getVisibility() != VISIBLE) {
230 setAlpha(0);
231 }
232 ObjectAnimator anim = ObjectAnimator.ofFloat(this, "alpha", 1);
233 anim.setDuration(FADE_DURATION);
234 anim.setInterpolator(sAlphaInterpolator);
235
236 anim.addListener(mVisAnimListener.withFinalVisibility(visibility));
237 anim.start();
238 } else {
239 ObjectAnimator anim = ObjectAnimator.ofFloat(this, "alpha", 0);
240 anim.setDuration(FADE_DURATION);
241 anim.setInterpolator(sAlphaInterpolator);
242
243 anim.addListener(mVisAnimListener.withFinalVisibility(visibility));
244 anim.start();
245 }
246 }
247
Adam Powellf5645cb2011-08-10 22:49:02 -0700248 public void animateToTab(final int position) {
Adam Powellf8ac6b72011-05-23 18:14:09 -0700249 final View tabView = mTabLayout.getChildAt(position);
250 if (mTabSelector != null) {
251 removeCallbacks(mTabSelector);
252 }
253 mTabSelector = new Runnable() {
254 public void run() {
255 final int scrollPos = tabView.getLeft() - (getWidth() - tabView.getWidth()) / 2;
256 smoothScrollTo(scrollPos, 0);
257 mTabSelector = null;
258 }
259 };
260 post(mTabSelector);
261 }
262
Adam Powellf5645cb2011-08-10 22:49:02 -0700263 @Override
264 public void onAttachedToWindow() {
265 super.onAttachedToWindow();
266 if (mTabSelector != null) {
267 // Re-post the selector we saved
268 post(mTabSelector);
Adam Powellf8ac6b72011-05-23 18:14:09 -0700269 }
270 }
271
Adam Powellf8ac6b72011-05-23 18:14:09 -0700272 @Override
273 public void onDetachedFromWindow() {
274 super.onDetachedFromWindow();
275 if (mTabSelector != null) {
276 removeCallbacks(mTabSelector);
277 }
278 }
279
Adam Powellf5645cb2011-08-10 22:49:02 -0700280 private TabView createTabView(ActionBar.Tab tab, boolean forAdapter) {
281 final TabView tabView = new TabView(getContext(), tab, forAdapter);
282 if (forAdapter) {
283 tabView.setBackgroundDrawable(null);
284 tabView.setLayoutParams(new ListView.LayoutParams(ListView.LayoutParams.MATCH_PARENT,
285 mContentHeight));
286 } else {
287 tabView.setFocusable(true);
Adam Powellf8ac6b72011-05-23 18:14:09 -0700288
Adam Powellf5645cb2011-08-10 22:49:02 -0700289 if (mTabClickListener == null) {
290 mTabClickListener = new TabClickListener();
291 }
292 tabView.setOnClickListener(mTabClickListener);
Adam Powellf8ac6b72011-05-23 18:14:09 -0700293 }
Adam Powellf8ac6b72011-05-23 18:14:09 -0700294 return tabView;
295 }
296
297 public void addTab(ActionBar.Tab tab, boolean setSelected) {
Adam Powellf5645cb2011-08-10 22:49:02 -0700298 TabView tabView = createTabView(tab, false);
Adam Powellf8ac6b72011-05-23 18:14:09 -0700299 mTabLayout.addView(tabView, new LinearLayout.LayoutParams(0,
300 LayoutParams.MATCH_PARENT, 1));
Adam Powellf5645cb2011-08-10 22:49:02 -0700301 if (mTabSpinner != null) {
302 ((TabAdapter) mTabSpinner.getAdapter()).notifyDataSetChanged();
303 }
Adam Powellf8ac6b72011-05-23 18:14:09 -0700304 if (setSelected) {
305 tabView.setSelected(true);
306 }
Adam Powellf5645cb2011-08-10 22:49:02 -0700307 if (mAllowCollapse) {
308 requestLayout();
309 }
Adam Powellf8ac6b72011-05-23 18:14:09 -0700310 }
311
312 public void addTab(ActionBar.Tab tab, int position, boolean setSelected) {
Adam Powellf5645cb2011-08-10 22:49:02 -0700313 final TabView tabView = createTabView(tab, false);
Adam Powellf8ac6b72011-05-23 18:14:09 -0700314 mTabLayout.addView(tabView, position, new LinearLayout.LayoutParams(
315 0, LayoutParams.MATCH_PARENT, 1));
Adam Powellf5645cb2011-08-10 22:49:02 -0700316 if (mTabSpinner != null) {
317 ((TabAdapter) mTabSpinner.getAdapter()).notifyDataSetChanged();
318 }
Adam Powellf8ac6b72011-05-23 18:14:09 -0700319 if (setSelected) {
320 tabView.setSelected(true);
321 }
Adam Powellf5645cb2011-08-10 22:49:02 -0700322 if (mAllowCollapse) {
323 requestLayout();
324 }
Adam Powellf8ac6b72011-05-23 18:14:09 -0700325 }
326
327 public void updateTab(int position) {
328 ((TabView) mTabLayout.getChildAt(position)).update();
Adam Powellf5645cb2011-08-10 22:49:02 -0700329 if (mTabSpinner != null) {
330 ((TabAdapter) mTabSpinner.getAdapter()).notifyDataSetChanged();
331 }
332 if (mAllowCollapse) {
333 requestLayout();
334 }
Adam Powellf8ac6b72011-05-23 18:14:09 -0700335 }
336
337 public void removeTabAt(int position) {
Adam Powellf5645cb2011-08-10 22:49:02 -0700338 mTabLayout.removeViewAt(position);
339 if (mTabSpinner != null) {
340 ((TabAdapter) mTabSpinner.getAdapter()).notifyDataSetChanged();
341 }
342 if (mAllowCollapse) {
343 requestLayout();
Adam Powellf8ac6b72011-05-23 18:14:09 -0700344 }
345 }
346
347 public void removeAllTabs() {
Adam Powellf5645cb2011-08-10 22:49:02 -0700348 mTabLayout.removeAllViews();
349 if (mTabSpinner != null) {
350 ((TabAdapter) mTabSpinner.getAdapter()).notifyDataSetChanged();
Adam Powellf8ac6b72011-05-23 18:14:09 -0700351 }
Adam Powellf5645cb2011-08-10 22:49:02 -0700352 if (mAllowCollapse) {
353 requestLayout();
354 }
355 }
356
357 @Override
Adam Powellc4e57e22012-02-24 19:24:26 -0800358 public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Adam Powellf5645cb2011-08-10 22:49:02 -0700359 TabView tabView = (TabView) view;
360 tabView.getTab().select();
361 }
362
Adam Powellc7752a32012-08-24 17:56:41 -0700363 private class TabView extends LinearLayout implements OnLongClickListener {
Adam Powellf8ac6b72011-05-23 18:14:09 -0700364 private ActionBar.Tab mTab;
365 private TextView mTextView;
366 private ImageView mIconView;
367 private View mCustomView;
368
Adam Powellf5645cb2011-08-10 22:49:02 -0700369 public TabView(Context context, ActionBar.Tab tab, boolean forList) {
Adam Powellf8ac6b72011-05-23 18:14:09 -0700370 super(context, null, com.android.internal.R.attr.actionBarTabStyle);
371 mTab = tab;
372
Adam Powellf5645cb2011-08-10 22:49:02 -0700373 if (forList) {
Fabrice Di Meglioaac0d4e2012-07-19 19:21:26 -0700374 setGravity(Gravity.START | Gravity.CENTER_VERTICAL);
Adam Powellf5645cb2011-08-10 22:49:02 -0700375 }
376
377 update();
378 }
379
380 public void bindTab(ActionBar.Tab tab) {
381 mTab = tab;
Adam Powellf8ac6b72011-05-23 18:14:09 -0700382 update();
383 }
384
385 @Override
Alan Viveretteb9f2e992013-04-15 16:16:11 -0700386 public void setSelected(boolean selected) {
387 final boolean changed = (isSelected() != selected);
388 super.setSelected(selected);
389 if (changed && selected) {
390 sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED);
391 }
392 }
393
394 @Override
395 public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
396 super.onInitializeAccessibilityEvent(event);
397 // This view masquerades as an action bar tab.
398 event.setClassName(ActionBar.Tab.class.getName());
399 }
400
401 @Override
402 public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
403 super.onInitializeAccessibilityNodeInfo(info);
404 // This view masquerades as an action bar tab.
405 info.setClassName(ActionBar.Tab.class.getName());
406 }
407
408 @Override
Adam Powellf8ac6b72011-05-23 18:14:09 -0700409 public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
410 super.onMeasure(widthMeasureSpec, heightMeasureSpec);
411
412 // Re-measure if we went beyond our maximum size.
413 if (mMaxTabWidth > 0 && getMeasuredWidth() > mMaxTabWidth) {
414 super.onMeasure(MeasureSpec.makeMeasureSpec(mMaxTabWidth, MeasureSpec.EXACTLY),
415 heightMeasureSpec);
416 }
417 }
418
419 public void update() {
420 final ActionBar.Tab tab = mTab;
421 final View custom = tab.getCustomView();
422 if (custom != null) {
Adam Powell05c82772011-11-21 17:14:56 -0800423 final ViewParent customParent = custom.getParent();
424 if (customParent != this) {
425 if (customParent != null) ((ViewGroup) customParent).removeView(custom);
426 addView(custom);
427 }
Adam Powellf8ac6b72011-05-23 18:14:09 -0700428 mCustomView = custom;
429 if (mTextView != null) mTextView.setVisibility(GONE);
430 if (mIconView != null) {
431 mIconView.setVisibility(GONE);
432 mIconView.setImageDrawable(null);
433 }
434 } else {
435 if (mCustomView != null) {
436 removeView(mCustomView);
437 mCustomView = null;
438 }
439
440 final Drawable icon = tab.getIcon();
441 final CharSequence text = tab.getText();
442
443 if (icon != null) {
444 if (mIconView == null) {
445 ImageView iconView = new ImageView(getContext());
446 LayoutParams lp = new LayoutParams(LayoutParams.WRAP_CONTENT,
447 LayoutParams.WRAP_CONTENT);
448 lp.gravity = Gravity.CENTER_VERTICAL;
449 iconView.setLayoutParams(lp);
450 addView(iconView, 0);
451 mIconView = iconView;
452 }
453 mIconView.setImageDrawable(icon);
454 mIconView.setVisibility(VISIBLE);
455 } else if (mIconView != null) {
456 mIconView.setVisibility(GONE);
457 mIconView.setImageDrawable(null);
458 }
459
Adam Powellc7752a32012-08-24 17:56:41 -0700460 final boolean hasText = !TextUtils.isEmpty(text);
461 if (hasText) {
Adam Powellf8ac6b72011-05-23 18:14:09 -0700462 if (mTextView == null) {
463 TextView textView = new TextView(getContext(), null,
464 com.android.internal.R.attr.actionBarTabTextStyle);
Adam Powellf8ac6b72011-05-23 18:14:09 -0700465 textView.setEllipsize(TruncateAt.END);
466 LayoutParams lp = new LayoutParams(LayoutParams.WRAP_CONTENT,
467 LayoutParams.WRAP_CONTENT);
468 lp.gravity = Gravity.CENTER_VERTICAL;
469 textView.setLayoutParams(lp);
470 addView(textView);
471 mTextView = textView;
472 }
473 mTextView.setText(text);
474 mTextView.setVisibility(VISIBLE);
Adam Powell251df772011-06-14 20:24:34 -0700475 } else if (mTextView != null) {
Adam Powellf8ac6b72011-05-23 18:14:09 -0700476 mTextView.setVisibility(GONE);
Adam Powell251df772011-06-14 20:24:34 -0700477 mTextView.setText(null);
Adam Powellf8ac6b72011-05-23 18:14:09 -0700478 }
Adam Powell94e56ef2011-09-06 21:22:22 -0700479
Adam Powell65d57042011-09-08 12:18:14 -0700480 if (mIconView != null) {
481 mIconView.setContentDescription(tab.getContentDescription());
482 }
Adam Powellc7752a32012-08-24 17:56:41 -0700483
484 if (!hasText && !TextUtils.isEmpty(tab.getContentDescription())) {
485 setOnLongClickListener(this);
486 } else {
487 setOnLongClickListener(null);
488 setLongClickable(false);
489 }
Adam Powellf8ac6b72011-05-23 18:14:09 -0700490 }
491 }
492
Adam Powellc7752a32012-08-24 17:56:41 -0700493 public boolean onLongClick(View v) {
494 final int[] screenPos = new int[2];
495 getLocationOnScreen(screenPos);
496
497 final Context context = getContext();
498 final int width = getWidth();
499 final int height = getHeight();
500 final int screenWidth = context.getResources().getDisplayMetrics().widthPixels;
501
502 Toast cheatSheet = Toast.makeText(context, mTab.getContentDescription(),
503 Toast.LENGTH_SHORT);
504 // Show under the tab
505 cheatSheet.setGravity(Gravity.TOP | Gravity.CENTER_HORIZONTAL,
506 (screenPos[0] + width / 2) - screenWidth / 2, height);
507
508 cheatSheet.show();
509 return true;
510 }
511
Adam Powellf8ac6b72011-05-23 18:14:09 -0700512 public ActionBar.Tab getTab() {
513 return mTab;
514 }
515 }
516
Adam Powellf5645cb2011-08-10 22:49:02 -0700517 private class TabAdapter extends BaseAdapter {
518 @Override
519 public int getCount() {
520 return mTabLayout.getChildCount();
521 }
522
523 @Override
524 public Object getItem(int position) {
525 return ((TabView) mTabLayout.getChildAt(position)).getTab();
526 }
527
528 @Override
529 public long getItemId(int position) {
530 return position;
531 }
532
533 @Override
534 public View getView(int position, View convertView, ViewGroup parent) {
535 if (convertView == null) {
536 convertView = createTabView((ActionBar.Tab) getItem(position), true);
537 } else {
538 ((TabView) convertView).bindTab((ActionBar.Tab) getItem(position));
539 }
540 return convertView;
541 }
542 }
543
Adam Powellf8ac6b72011-05-23 18:14:09 -0700544 private class TabClickListener implements OnClickListener {
545 public void onClick(View view) {
546 TabView tabView = (TabView) view;
547 tabView.getTab().select();
548 final int tabCount = mTabLayout.getChildCount();
549 for (int i = 0; i < tabCount; i++) {
550 final View child = mTabLayout.getChildAt(i);
551 child.setSelected(child == view);
552 }
553 }
554 }
Adam Powellf6ce6a92011-06-29 10:25:01 -0700555
556 protected class VisibilityAnimListener implements Animator.AnimatorListener {
557 private boolean mCanceled = false;
558 private int mFinalVisibility;
559
560 public VisibilityAnimListener withFinalVisibility(int visibility) {
561 mFinalVisibility = visibility;
562 return this;
563 }
564
565 @Override
566 public void onAnimationStart(Animator animation) {
567 setVisibility(VISIBLE);
568 mVisibilityAnim = animation;
569 mCanceled = false;
570 }
571
572 @Override
573 public void onAnimationEnd(Animator animation) {
574 if (mCanceled) return;
575
576 mVisibilityAnim = null;
577 setVisibility(mFinalVisibility);
578 }
579
580 @Override
581 public void onAnimationCancel(Animator animation) {
582 mCanceled = true;
583 }
584
585 @Override
586 public void onAnimationRepeat(Animator animation) {
587 }
588 }
Adam Powellf8ac6b72011-05-23 18:14:09 -0700589}