ScrollingTabContainerView.java revision b8139af3dcae80c0030afd0354dc424a7c72c3d9
1f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell/*
2f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell * Copyright (C) 2011 The Android Open Source Project
3f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell *
4f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell * Licensed under the Apache License, Version 2.0 (the "License");
5f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell * you may not use this file except in compliance with the License.
6f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell * You may obtain a copy of the License at
7f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell *
8f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell *      http://www.apache.org/licenses/LICENSE-2.0
9f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell *
10f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell * Unless required by applicable law or agreed to in writing, software
11f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell * distributed under the License is distributed on an "AS IS" BASIS,
12f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell * See the License for the specific language governing permissions and
14f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell * limitations under the License.
15f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell */
16f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powellpackage com.android.internal.widget;
17f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell
18b8139af3dcae80c0030afd0354dc424a7c72c3d9Adam Powellimport com.android.internal.view.ActionBarPolicy;
19faa6ffa484f6f2a334c8bf2c7a9dc693a61608f3Adam Powell
20f6ce6a9bacbb220c6ea7b552c481237f23e64ae7Adam Powellimport android.animation.Animator;
21f6ce6a9bacbb220c6ea7b552c481237f23e64ae7Adam Powellimport android.animation.ObjectAnimator;
22f6ce6a9bacbb220c6ea7b552c481237f23e64ae7Adam Powellimport android.animation.TimeInterpolator;
23f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powellimport android.app.ActionBar;
24f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powellimport android.content.Context;
25faa6ffa484f6f2a334c8bf2c7a9dc693a61608f3Adam Powellimport android.content.res.Configuration;
26f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powellimport android.graphics.drawable.Drawable;
27f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powellimport android.text.TextUtils.TruncateAt;
28f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powellimport android.view.Gravity;
29f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powellimport android.view.View;
30f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powellimport android.view.ViewGroup;
3105c8277f3423fd57196b3878d27ac0f1995101a8Adam Powellimport android.view.ViewParent;
32f6ce6a9bacbb220c6ea7b552c481237f23e64ae7Adam Powellimport android.view.animation.DecelerateInterpolator;
33f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powellimport android.widget.AdapterView;
34f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powellimport android.widget.BaseAdapter;
35f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powellimport android.widget.HorizontalScrollView;
36f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powellimport android.widget.ImageView;
37f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powellimport android.widget.LinearLayout;
38f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powellimport android.widget.ListView;
39f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powellimport android.widget.Spinner;
40f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powellimport android.widget.TextView;
41f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell
42f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell/**
43f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell * This widget implements the dynamic action bar tab behavior that can change
44f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell * across different configurations or circumstances.
45f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell */
46f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powellpublic class ScrollingTabContainerView extends HorizontalScrollView
47c4e57e23f99f4cea6fcca870a95f7f20a6edfaf2Adam Powell        implements AdapterView.OnItemClickListener {
48f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell    private static final String TAG = "ScrollingTabContainerView";
49f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell    Runnable mTabSelector;
50f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell    private TabClickListener mTabClickListener;
51f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell
52f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell    private LinearLayout mTabLayout;
53f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell    private Spinner mTabSpinner;
54f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell    private boolean mAllowCollapse;
55f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell
56f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell    int mMaxTabWidth;
57b8139af3dcae80c0030afd0354dc424a7c72c3d9Adam Powell    int mStackedTabMaxWidth;
58f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell    private int mContentHeight;
59f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell    private int mSelectedTabIndex;
60f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell
61f6ce6a9bacbb220c6ea7b552c481237f23e64ae7Adam Powell    protected Animator mVisibilityAnim;
62f6ce6a9bacbb220c6ea7b552c481237f23e64ae7Adam Powell    protected final VisibilityAnimListener mVisAnimListener = new VisibilityAnimListener();
63f6ce6a9bacbb220c6ea7b552c481237f23e64ae7Adam Powell
64f6ce6a9bacbb220c6ea7b552c481237f23e64ae7Adam Powell    private static final TimeInterpolator sAlphaInterpolator = new DecelerateInterpolator();
65f6ce6a9bacbb220c6ea7b552c481237f23e64ae7Adam Powell
66f6ce6a9bacbb220c6ea7b552c481237f23e64ae7Adam Powell    private static final int FADE_DURATION = 200;
67f6ce6a9bacbb220c6ea7b552c481237f23e64ae7Adam Powell
68f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell    public ScrollingTabContainerView(Context context) {
69f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell        super(context);
70f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell        setHorizontalScrollBarEnabled(false);
71f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell
72b8139af3dcae80c0030afd0354dc424a7c72c3d9Adam Powell        ActionBarPolicy abp = ActionBarPolicy.get(context);
73b8139af3dcae80c0030afd0354dc424a7c72c3d9Adam Powell        setContentHeight(abp.getTabContainerHeight());
74b8139af3dcae80c0030afd0354dc424a7c72c3d9Adam Powell        mStackedTabMaxWidth = abp.getStackedTabMaxWidth();
75af6b97ebe0e6a67d1691c4d7789c7bc312c1e13eAdam Powell
76f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        mTabLayout = createTabLayout();
77f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        addView(mTabLayout, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
78f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell                ViewGroup.LayoutParams.MATCH_PARENT));
79f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell    }
80f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell
81f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell    @Override
82f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell    public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
83f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell        final int widthMode = MeasureSpec.getMode(widthMeasureSpec);
84f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        final boolean lockedExpanded = widthMode == MeasureSpec.EXACTLY;
85f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        setFillViewport(lockedExpanded);
86f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell
87f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        final int childCount = mTabLayout.getChildCount();
88f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell        if (childCount > 1 &&
89f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell                (widthMode == MeasureSpec.EXACTLY || widthMode == MeasureSpec.AT_MOST)) {
90f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell            if (childCount > 2) {
91f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell                mMaxTabWidth = (int) (MeasureSpec.getSize(widthMeasureSpec) * 0.4f);
92f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell            } else {
93f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell                mMaxTabWidth = MeasureSpec.getSize(widthMeasureSpec) / 2;
94f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell            }
95b8139af3dcae80c0030afd0354dc424a7c72c3d9Adam Powell            mMaxTabWidth = Math.min(mMaxTabWidth, mStackedTabMaxWidth);
96f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell        } else {
97f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell            mMaxTabWidth = -1;
98f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell        }
99f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell
100af6b97ebe0e6a67d1691c4d7789c7bc312c1e13eAdam Powell        heightMeasureSpec = MeasureSpec.makeMeasureSpec(mContentHeight, MeasureSpec.EXACTLY);
101f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell
102f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        final boolean canCollapse = !lockedExpanded && mAllowCollapse;
103f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell
104f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        if (canCollapse) {
105f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell            // See if we should expand
106f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell            mTabLayout.measure(MeasureSpec.UNSPECIFIED, heightMeasureSpec);
107f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell            if (mTabLayout.getMeasuredWidth() > MeasureSpec.getSize(widthMeasureSpec)) {
108f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell                performCollapse();
109f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell            } else {
110f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell                performExpand();
111f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell            }
112f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        } else {
113f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell            performExpand();
114f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        }
115f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell
116f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        final int oldWidth = getMeasuredWidth();
117f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
118f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        final int newWidth = getMeasuredWidth();
119f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell
120f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        if (lockedExpanded && oldWidth != newWidth) {
121f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell            // Recenter the tab display if we're at a new (scrollable) size.
122f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell            setTabSelected(mSelectedTabIndex);
123f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        }
124f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell    }
125f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell
126f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell    /**
127f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell     * Indicates whether this view is collapsed into a dropdown menu instead
128f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell     * of traditional tabs.
129f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell     * @return true if showing as a spinner
130f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell     */
131f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell    private boolean isCollapsed() {
132f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        return mTabSpinner != null && mTabSpinner.getParent() == this;
133f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell    }
134f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell
135f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell    public void setAllowCollapse(boolean allowCollapse) {
136f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        mAllowCollapse = allowCollapse;
137f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell    }
138f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell
139f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell    private void performCollapse() {
140f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        if (isCollapsed()) return;
141f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell
142f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        if (mTabSpinner == null) {
143f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell            mTabSpinner = createSpinner();
144f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell        }
145f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        removeView(mTabLayout);
146f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        addView(mTabSpinner, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
147f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell                ViewGroup.LayoutParams.MATCH_PARENT));
148f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        if (mTabSpinner.getAdapter() == null) {
149f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell            mTabSpinner.setAdapter(new TabAdapter());
150f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        }
151f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        if (mTabSelector != null) {
152f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell            removeCallbacks(mTabSelector);
153f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell            mTabSelector = null;
154f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        }
155f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        mTabSpinner.setSelection(mSelectedTabIndex);
156f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell    }
157f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell
158f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell    private boolean performExpand() {
159f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        if (!isCollapsed()) return false;
160f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell
161f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        removeView(mTabSpinner);
162f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        addView(mTabLayout, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
163f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell                ViewGroup.LayoutParams.MATCH_PARENT));
164f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        setTabSelected(mTabSpinner.getSelectedItemPosition());
165f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        return false;
166f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell    }
167f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell
168f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell    public void setTabSelected(int position) {
169f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        mSelectedTabIndex = position;
170f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell        final int tabCount = mTabLayout.getChildCount();
171f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell        for (int i = 0; i < tabCount; i++) {
172f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell            final View child = mTabLayout.getChildAt(i);
173f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell            final boolean isSelected = i == position;
174f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell            child.setSelected(isSelected);
175f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell            if (isSelected) {
176f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell                animateToTab(position);
177f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell            }
178f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell        }
179f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell    }
180f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell
18145c0b1954d7dfa6e2590ed76b915a98ae971414cAdam Powell    public void setContentHeight(int contentHeight) {
182f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        mContentHeight = contentHeight;
18345c0b1954d7dfa6e2590ed76b915a98ae971414cAdam Powell        requestLayout();
18445c0b1954d7dfa6e2590ed76b915a98ae971414cAdam Powell    }
18545c0b1954d7dfa6e2590ed76b915a98ae971414cAdam Powell
186f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell    private LinearLayout createTabLayout() {
187f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        final LinearLayout tabLayout = new LinearLayout(getContext(), null,
188f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell                com.android.internal.R.attr.actionBarTabBarStyle);
189f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        tabLayout.setMeasureWithLargestChildEnabled(true);
190b8139af3dcae80c0030afd0354dc424a7c72c3d9Adam Powell        tabLayout.setGravity(Gravity.CENTER);
191f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        tabLayout.setLayoutParams(new LinearLayout.LayoutParams(
192f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell                LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.MATCH_PARENT));
193f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        return tabLayout;
194f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell    }
195f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell
196f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell    private Spinner createSpinner() {
197f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        final Spinner spinner = new Spinner(getContext(), null,
198f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell                com.android.internal.R.attr.actionDropDownStyle);
199f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        spinner.setLayoutParams(new LinearLayout.LayoutParams(
200f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell                LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.MATCH_PARENT));
201c4e57e23f99f4cea6fcca870a95f7f20a6edfaf2Adam Powell        spinner.setOnItemClickListenerInt(this);
202f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        return spinner;
203f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell    }
204f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell
205faa6ffa484f6f2a334c8bf2c7a9dc693a61608f3Adam Powell    @Override
206faa6ffa484f6f2a334c8bf2c7a9dc693a61608f3Adam Powell    protected void onConfigurationChanged(Configuration newConfig) {
207faa6ffa484f6f2a334c8bf2c7a9dc693a61608f3Adam Powell        super.onConfigurationChanged(newConfig);
208faa6ffa484f6f2a334c8bf2c7a9dc693a61608f3Adam Powell
209b8139af3dcae80c0030afd0354dc424a7c72c3d9Adam Powell        ActionBarPolicy abp = ActionBarPolicy.get(getContext());
210faa6ffa484f6f2a334c8bf2c7a9dc693a61608f3Adam Powell        // Action bar can change size on configuration changes.
211faa6ffa484f6f2a334c8bf2c7a9dc693a61608f3Adam Powell        // Reread the desired height from the theme-specified style.
212b8139af3dcae80c0030afd0354dc424a7c72c3d9Adam Powell        setContentHeight(abp.getTabContainerHeight());
213b8139af3dcae80c0030afd0354dc424a7c72c3d9Adam Powell        mStackedTabMaxWidth = abp.getStackedTabMaxWidth();
214faa6ffa484f6f2a334c8bf2c7a9dc693a61608f3Adam Powell    }
215faa6ffa484f6f2a334c8bf2c7a9dc693a61608f3Adam Powell
216f6ce6a9bacbb220c6ea7b552c481237f23e64ae7Adam Powell    public void animateToVisibility(int visibility) {
217f6ce6a9bacbb220c6ea7b552c481237f23e64ae7Adam Powell        if (mVisibilityAnim != null) {
218f6ce6a9bacbb220c6ea7b552c481237f23e64ae7Adam Powell            mVisibilityAnim.cancel();
219f6ce6a9bacbb220c6ea7b552c481237f23e64ae7Adam Powell        }
220f6ce6a9bacbb220c6ea7b552c481237f23e64ae7Adam Powell        if (visibility == VISIBLE) {
221f6ce6a9bacbb220c6ea7b552c481237f23e64ae7Adam Powell            if (getVisibility() != VISIBLE) {
222f6ce6a9bacbb220c6ea7b552c481237f23e64ae7Adam Powell                setAlpha(0);
223f6ce6a9bacbb220c6ea7b552c481237f23e64ae7Adam Powell            }
224f6ce6a9bacbb220c6ea7b552c481237f23e64ae7Adam Powell            ObjectAnimator anim = ObjectAnimator.ofFloat(this, "alpha", 1);
225f6ce6a9bacbb220c6ea7b552c481237f23e64ae7Adam Powell            anim.setDuration(FADE_DURATION);
226f6ce6a9bacbb220c6ea7b552c481237f23e64ae7Adam Powell            anim.setInterpolator(sAlphaInterpolator);
227f6ce6a9bacbb220c6ea7b552c481237f23e64ae7Adam Powell
228f6ce6a9bacbb220c6ea7b552c481237f23e64ae7Adam Powell            anim.addListener(mVisAnimListener.withFinalVisibility(visibility));
229f6ce6a9bacbb220c6ea7b552c481237f23e64ae7Adam Powell            anim.start();
230f6ce6a9bacbb220c6ea7b552c481237f23e64ae7Adam Powell        } else {
231f6ce6a9bacbb220c6ea7b552c481237f23e64ae7Adam Powell            ObjectAnimator anim = ObjectAnimator.ofFloat(this, "alpha", 0);
232f6ce6a9bacbb220c6ea7b552c481237f23e64ae7Adam Powell            anim.setDuration(FADE_DURATION);
233f6ce6a9bacbb220c6ea7b552c481237f23e64ae7Adam Powell            anim.setInterpolator(sAlphaInterpolator);
234f6ce6a9bacbb220c6ea7b552c481237f23e64ae7Adam Powell
235f6ce6a9bacbb220c6ea7b552c481237f23e64ae7Adam Powell            anim.addListener(mVisAnimListener.withFinalVisibility(visibility));
236f6ce6a9bacbb220c6ea7b552c481237f23e64ae7Adam Powell            anim.start();
237f6ce6a9bacbb220c6ea7b552c481237f23e64ae7Adam Powell        }
238f6ce6a9bacbb220c6ea7b552c481237f23e64ae7Adam Powell    }
239f6ce6a9bacbb220c6ea7b552c481237f23e64ae7Adam Powell
240f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell    public void animateToTab(final int position) {
241f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell        final View tabView = mTabLayout.getChildAt(position);
242f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell        if (mTabSelector != null) {
243f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell            removeCallbacks(mTabSelector);
244f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell        }
245f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell        mTabSelector = new Runnable() {
246f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell            public void run() {
247f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell                final int scrollPos = tabView.getLeft() - (getWidth() - tabView.getWidth()) / 2;
248f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell                smoothScrollTo(scrollPos, 0);
249f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell                mTabSelector = null;
250f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell            }
251f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell        };
252f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell        post(mTabSelector);
253f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell    }
254f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell
255f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell    @Override
256f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell    public void onAttachedToWindow() {
257f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        super.onAttachedToWindow();
258f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        if (mTabSelector != null) {
259f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell            // Re-post the selector we saved
260f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell            post(mTabSelector);
261f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell        }
262f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell    }
263f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell
264f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell    @Override
265f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell    public void onDetachedFromWindow() {
266f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell        super.onDetachedFromWindow();
267f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell        if (mTabSelector != null) {
268f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell            removeCallbacks(mTabSelector);
269f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell        }
270f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell    }
271f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell
272f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell    private TabView createTabView(ActionBar.Tab tab, boolean forAdapter) {
273f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        final TabView tabView = new TabView(getContext(), tab, forAdapter);
274f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        if (forAdapter) {
275f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell            tabView.setBackgroundDrawable(null);
276f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell            tabView.setLayoutParams(new ListView.LayoutParams(ListView.LayoutParams.MATCH_PARENT,
277f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell                    mContentHeight));
278f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        } else {
279f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell            tabView.setFocusable(true);
280f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell
281f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell            if (mTabClickListener == null) {
282f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell                mTabClickListener = new TabClickListener();
283f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell            }
284f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell            tabView.setOnClickListener(mTabClickListener);
285f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell        }
286f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell        return tabView;
287f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell    }
288f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell
289f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell    public void addTab(ActionBar.Tab tab, boolean setSelected) {
290f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        TabView tabView = createTabView(tab, false);
291f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell        mTabLayout.addView(tabView, new LinearLayout.LayoutParams(0,
292f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell                LayoutParams.MATCH_PARENT, 1));
293f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        if (mTabSpinner != null) {
294f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell            ((TabAdapter) mTabSpinner.getAdapter()).notifyDataSetChanged();
295f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        }
296f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell        if (setSelected) {
297f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell            tabView.setSelected(true);
298f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell        }
299f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        if (mAllowCollapse) {
300f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell            requestLayout();
301f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        }
302f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell    }
303f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell
304f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell    public void addTab(ActionBar.Tab tab, int position, boolean setSelected) {
305f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        final TabView tabView = createTabView(tab, false);
306f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell        mTabLayout.addView(tabView, position, new LinearLayout.LayoutParams(
307f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell                0, LayoutParams.MATCH_PARENT, 1));
308f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        if (mTabSpinner != null) {
309f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell            ((TabAdapter) mTabSpinner.getAdapter()).notifyDataSetChanged();
310f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        }
311f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell        if (setSelected) {
312f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell            tabView.setSelected(true);
313f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell        }
314f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        if (mAllowCollapse) {
315f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell            requestLayout();
316f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        }
317f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell    }
318f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell
319f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell    public void updateTab(int position) {
320f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell        ((TabView) mTabLayout.getChildAt(position)).update();
321f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        if (mTabSpinner != null) {
322f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell            ((TabAdapter) mTabSpinner.getAdapter()).notifyDataSetChanged();
323f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        }
324f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        if (mAllowCollapse) {
325f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell            requestLayout();
326f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        }
327f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell    }
328f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell
329f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell    public void removeTabAt(int position) {
330f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        mTabLayout.removeViewAt(position);
331f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        if (mTabSpinner != null) {
332f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell            ((TabAdapter) mTabSpinner.getAdapter()).notifyDataSetChanged();
333f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        }
334f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        if (mAllowCollapse) {
335f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell            requestLayout();
336f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell        }
337f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell    }
338f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell
339f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell    public void removeAllTabs() {
340f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        mTabLayout.removeAllViews();
341f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        if (mTabSpinner != null) {
342f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell            ((TabAdapter) mTabSpinner.getAdapter()).notifyDataSetChanged();
343f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        }
344f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        if (mAllowCollapse) {
345f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell            requestLayout();
346f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell        }
347f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell    }
348f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell
349f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell    @Override
350c4e57e23f99f4cea6fcca870a95f7f20a6edfaf2Adam Powell    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
351f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        TabView tabView = (TabView) view;
352f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        tabView.getTab().select();
353f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell    }
354f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell
355f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell    private class TabView extends LinearLayout {
356f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell        private ActionBar.Tab mTab;
357f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell        private TextView mTextView;
358f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell        private ImageView mIconView;
359f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell        private View mCustomView;
360f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell
361f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        public TabView(Context context, ActionBar.Tab tab, boolean forList) {
362f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell            super(context, null, com.android.internal.R.attr.actionBarTabStyle);
363f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell            mTab = tab;
364f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell
365f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell            if (forList) {
366f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell                setGravity(Gravity.LEFT | Gravity.CENTER_VERTICAL);
367f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell            }
368f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell
369f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell            update();
370f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        }
371f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell
372f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        public void bindTab(ActionBar.Tab tab) {
373f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell            mTab = tab;
374f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell            update();
375f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell        }
376f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell
377f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell        @Override
378f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell        public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
379f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
380f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell
381f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell            // Re-measure if we went beyond our maximum size.
382f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell            if (mMaxTabWidth > 0 && getMeasuredWidth() > mMaxTabWidth) {
383f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell                super.onMeasure(MeasureSpec.makeMeasureSpec(mMaxTabWidth, MeasureSpec.EXACTLY),
384f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell                        heightMeasureSpec);
385f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell            }
386f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell        }
387f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell
388f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell        public void update() {
389f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell            final ActionBar.Tab tab = mTab;
390f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell            final View custom = tab.getCustomView();
391f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell            if (custom != null) {
39205c8277f3423fd57196b3878d27ac0f1995101a8Adam Powell                final ViewParent customParent = custom.getParent();
39305c8277f3423fd57196b3878d27ac0f1995101a8Adam Powell                if (customParent != this) {
39405c8277f3423fd57196b3878d27ac0f1995101a8Adam Powell                    if (customParent != null) ((ViewGroup) customParent).removeView(custom);
39505c8277f3423fd57196b3878d27ac0f1995101a8Adam Powell                    addView(custom);
39605c8277f3423fd57196b3878d27ac0f1995101a8Adam Powell                }
397f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell                mCustomView = custom;
398f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell                if (mTextView != null) mTextView.setVisibility(GONE);
399f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell                if (mIconView != null) {
400f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell                    mIconView.setVisibility(GONE);
401f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell                    mIconView.setImageDrawable(null);
402f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell                }
403f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell            } else {
404f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell                if (mCustomView != null) {
405f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell                    removeView(mCustomView);
406f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell                    mCustomView = null;
407f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell                }
408f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell
409f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell                final Drawable icon = tab.getIcon();
410f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell                final CharSequence text = tab.getText();
411f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell
412f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell                if (icon != null) {
413f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell                    if (mIconView == null) {
414f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell                        ImageView iconView = new ImageView(getContext());
415f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell                        LayoutParams lp = new LayoutParams(LayoutParams.WRAP_CONTENT,
416f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell                                LayoutParams.WRAP_CONTENT);
417f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell                        lp.gravity = Gravity.CENTER_VERTICAL;
418f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell                        iconView.setLayoutParams(lp);
419f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell                        addView(iconView, 0);
420f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell                        mIconView = iconView;
421f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell                    }
422f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell                    mIconView.setImageDrawable(icon);
423f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell                    mIconView.setVisibility(VISIBLE);
424f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell                } else if (mIconView != null) {
425f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell                    mIconView.setVisibility(GONE);
426f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell                    mIconView.setImageDrawable(null);
427f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell                }
428f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell
429f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell                if (text != null) {
430f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell                    if (mTextView == null) {
431f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell                        TextView textView = new TextView(getContext(), null,
432f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell                                com.android.internal.R.attr.actionBarTabTextStyle);
433f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell                        textView.setEllipsize(TruncateAt.END);
434f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell                        LayoutParams lp = new LayoutParams(LayoutParams.WRAP_CONTENT,
435f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell                                LayoutParams.WRAP_CONTENT);
436f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell                        lp.gravity = Gravity.CENTER_VERTICAL;
437f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell                        textView.setLayoutParams(lp);
438f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell                        addView(textView);
439f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell                        mTextView = textView;
440f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell                    }
441f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell                    mTextView.setText(text);
442f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell                    mTextView.setVisibility(VISIBLE);
443251df77861525cca79d38bcee7c45c16c6752e40Adam Powell                } else if (mTextView != null) {
444f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell                    mTextView.setVisibility(GONE);
445251df77861525cca79d38bcee7c45c16c6752e40Adam Powell                    mTextView.setText(null);
446f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell                }
44794e56ef3b8de6ed485546b462559ac862c10eabfAdam Powell
44865d570447641d1575aa59d511591402e431fdd2eAdam Powell                if (mIconView != null) {
44965d570447641d1575aa59d511591402e431fdd2eAdam Powell                    mIconView.setContentDescription(tab.getContentDescription());
45065d570447641d1575aa59d511591402e431fdd2eAdam Powell                }
451f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell            }
452f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell        }
453f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell
454f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell        public ActionBar.Tab getTab() {
455f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell            return mTab;
456f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell        }
457f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell    }
458f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell
459f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell    private class TabAdapter extends BaseAdapter {
460f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        @Override
461f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        public int getCount() {
462f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell            return mTabLayout.getChildCount();
463f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        }
464f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell
465f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        @Override
466f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        public Object getItem(int position) {
467f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell            return ((TabView) mTabLayout.getChildAt(position)).getTab();
468f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        }
469f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell
470f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        @Override
471f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        public long getItemId(int position) {
472f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell            return position;
473f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        }
474f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell
475f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        @Override
476f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        public View getView(int position, View convertView, ViewGroup parent) {
477f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell            if (convertView == null) {
478f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell                convertView = createTabView((ActionBar.Tab) getItem(position), true);
479f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell            } else {
480f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell                ((TabView) convertView).bindTab((ActionBar.Tab) getItem(position));
481f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell            }
482f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell            return convertView;
483f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        }
484f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell    }
485f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell
486f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell    private class TabClickListener implements OnClickListener {
487f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell        public void onClick(View view) {
488f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell            TabView tabView = (TabView) view;
489f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell            tabView.getTab().select();
490f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell            final int tabCount = mTabLayout.getChildCount();
491f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell            for (int i = 0; i < tabCount; i++) {
492f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell                final View child = mTabLayout.getChildAt(i);
493f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell                child.setSelected(child == view);
494f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell            }
495f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell        }
496f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell    }
497f6ce6a9bacbb220c6ea7b552c481237f23e64ae7Adam Powell
498f6ce6a9bacbb220c6ea7b552c481237f23e64ae7Adam Powell    protected class VisibilityAnimListener implements Animator.AnimatorListener {
499f6ce6a9bacbb220c6ea7b552c481237f23e64ae7Adam Powell        private boolean mCanceled = false;
500f6ce6a9bacbb220c6ea7b552c481237f23e64ae7Adam Powell        private int mFinalVisibility;
501f6ce6a9bacbb220c6ea7b552c481237f23e64ae7Adam Powell
502f6ce6a9bacbb220c6ea7b552c481237f23e64ae7Adam Powell        public VisibilityAnimListener withFinalVisibility(int visibility) {
503f6ce6a9bacbb220c6ea7b552c481237f23e64ae7Adam Powell            mFinalVisibility = visibility;
504f6ce6a9bacbb220c6ea7b552c481237f23e64ae7Adam Powell            return this;
505f6ce6a9bacbb220c6ea7b552c481237f23e64ae7Adam Powell        }
506f6ce6a9bacbb220c6ea7b552c481237f23e64ae7Adam Powell
507f6ce6a9bacbb220c6ea7b552c481237f23e64ae7Adam Powell        @Override
508f6ce6a9bacbb220c6ea7b552c481237f23e64ae7Adam Powell        public void onAnimationStart(Animator animation) {
509f6ce6a9bacbb220c6ea7b552c481237f23e64ae7Adam Powell            setVisibility(VISIBLE);
510f6ce6a9bacbb220c6ea7b552c481237f23e64ae7Adam Powell            mVisibilityAnim = animation;
511f6ce6a9bacbb220c6ea7b552c481237f23e64ae7Adam Powell            mCanceled = false;
512f6ce6a9bacbb220c6ea7b552c481237f23e64ae7Adam Powell        }
513f6ce6a9bacbb220c6ea7b552c481237f23e64ae7Adam Powell
514f6ce6a9bacbb220c6ea7b552c481237f23e64ae7Adam Powell        @Override
515f6ce6a9bacbb220c6ea7b552c481237f23e64ae7Adam Powell        public void onAnimationEnd(Animator animation) {
516f6ce6a9bacbb220c6ea7b552c481237f23e64ae7Adam Powell            if (mCanceled) return;
517f6ce6a9bacbb220c6ea7b552c481237f23e64ae7Adam Powell
518f6ce6a9bacbb220c6ea7b552c481237f23e64ae7Adam Powell            mVisibilityAnim = null;
519f6ce6a9bacbb220c6ea7b552c481237f23e64ae7Adam Powell            setVisibility(mFinalVisibility);
520f6ce6a9bacbb220c6ea7b552c481237f23e64ae7Adam Powell        }
521f6ce6a9bacbb220c6ea7b552c481237f23e64ae7Adam Powell
522f6ce6a9bacbb220c6ea7b552c481237f23e64ae7Adam Powell        @Override
523f6ce6a9bacbb220c6ea7b552c481237f23e64ae7Adam Powell        public void onAnimationCancel(Animator animation) {
524f6ce6a9bacbb220c6ea7b552c481237f23e64ae7Adam Powell            mCanceled = true;
525f6ce6a9bacbb220c6ea7b552c481237f23e64ae7Adam Powell        }
526f6ce6a9bacbb220c6ea7b552c481237f23e64ae7Adam Powell
527f6ce6a9bacbb220c6ea7b552c481237f23e64ae7Adam Powell        @Override
528f6ce6a9bacbb220c6ea7b552c481237f23e64ae7Adam Powell        public void onAnimationRepeat(Animator animation) {
529f6ce6a9bacbb220c6ea7b552c481237f23e64ae7Adam Powell        }
530f6ce6a9bacbb220c6ea7b552c481237f23e64ae7Adam Powell    }
531f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell}
532