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;
27c7752a312adfe108c3b0e9143122152f2470be31Adam Powellimport android.text.TextUtils;
28f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powellimport android.text.TextUtils.TruncateAt;
29f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powellimport android.view.Gravity;
30f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powellimport android.view.View;
31f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powellimport android.view.ViewGroup;
3205c8277f3423fd57196b3878d27ac0f1995101a8Adam Powellimport android.view.ViewParent;
33b9f2e99f26c5cd3546235a183bb3402a2f1e82f8Alan Viveretteimport android.view.accessibility.AccessibilityEvent;
34f6ce6a9bacbb220c6ea7b552c481237f23e64ae7Adam Powellimport android.view.animation.DecelerateInterpolator;
35f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powellimport android.widget.AdapterView;
36f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powellimport android.widget.BaseAdapter;
37f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powellimport android.widget.HorizontalScrollView;
38f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powellimport android.widget.ImageView;
39f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powellimport android.widget.LinearLayout;
40f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powellimport android.widget.ListView;
41f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powellimport android.widget.Spinner;
42f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powellimport android.widget.TextView;
43f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell
44f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell/**
45f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell * This widget implements the dynamic action bar tab behavior that can change
46f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell * across different configurations or circumstances.
47f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell */
48f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powellpublic class ScrollingTabContainerView extends HorizontalScrollView
49c4e57e23f99f4cea6fcca870a95f7f20a6edfaf2Adam Powell        implements AdapterView.OnItemClickListener {
50f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell    private static final String TAG = "ScrollingTabContainerView";
51f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell    Runnable mTabSelector;
52f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell    private TabClickListener mTabClickListener;
53f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell
54f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell    private LinearLayout mTabLayout;
55f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell    private Spinner mTabSpinner;
56f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell    private boolean mAllowCollapse;
57f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell
58f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell    int mMaxTabWidth;
59b8139af3dcae80c0030afd0354dc424a7c72c3d9Adam Powell    int mStackedTabMaxWidth;
60f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell    private int mContentHeight;
61f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell    private int mSelectedTabIndex;
62f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell
63f6ce6a9bacbb220c6ea7b552c481237f23e64ae7Adam Powell    protected Animator mVisibilityAnim;
64f6ce6a9bacbb220c6ea7b552c481237f23e64ae7Adam Powell    protected final VisibilityAnimListener mVisAnimListener = new VisibilityAnimListener();
65f6ce6a9bacbb220c6ea7b552c481237f23e64ae7Adam Powell
66f6ce6a9bacbb220c6ea7b552c481237f23e64ae7Adam Powell    private static final TimeInterpolator sAlphaInterpolator = new DecelerateInterpolator();
67f6ce6a9bacbb220c6ea7b552c481237f23e64ae7Adam Powell
68f6ce6a9bacbb220c6ea7b552c481237f23e64ae7Adam Powell    private static final int FADE_DURATION = 200;
69f6ce6a9bacbb220c6ea7b552c481237f23e64ae7Adam Powell
70f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell    public ScrollingTabContainerView(Context context) {
71f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell        super(context);
72f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell        setHorizontalScrollBarEnabled(false);
73f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell
74b8139af3dcae80c0030afd0354dc424a7c72c3d9Adam Powell        ActionBarPolicy abp = ActionBarPolicy.get(context);
75b8139af3dcae80c0030afd0354dc424a7c72c3d9Adam Powell        setContentHeight(abp.getTabContainerHeight());
76b8139af3dcae80c0030afd0354dc424a7c72c3d9Adam Powell        mStackedTabMaxWidth = abp.getStackedTabMaxWidth();
77af6b97ebe0e6a67d1691c4d7789c7bc312c1e13eAdam Powell
78f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        mTabLayout = createTabLayout();
79f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        addView(mTabLayout, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
80f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell                ViewGroup.LayoutParams.MATCH_PARENT));
81f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell    }
82f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell
83f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell    @Override
84f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell    public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
85f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell        final int widthMode = MeasureSpec.getMode(widthMeasureSpec);
86f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        final boolean lockedExpanded = widthMode == MeasureSpec.EXACTLY;
87f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        setFillViewport(lockedExpanded);
88f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell
89f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        final int childCount = mTabLayout.getChildCount();
90f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell        if (childCount > 1 &&
91f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell                (widthMode == MeasureSpec.EXACTLY || widthMode == MeasureSpec.AT_MOST)) {
92f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell            if (childCount > 2) {
93f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell                mMaxTabWidth = (int) (MeasureSpec.getSize(widthMeasureSpec) * 0.4f);
94f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell            } else {
95f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell                mMaxTabWidth = MeasureSpec.getSize(widthMeasureSpec) / 2;
96f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell            }
97b8139af3dcae80c0030afd0354dc424a7c72c3d9Adam Powell            mMaxTabWidth = Math.min(mMaxTabWidth, mStackedTabMaxWidth);
98f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell        } else {
99f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell            mMaxTabWidth = -1;
100f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell        }
101f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell
102af6b97ebe0e6a67d1691c4d7789c7bc312c1e13eAdam Powell        heightMeasureSpec = MeasureSpec.makeMeasureSpec(mContentHeight, MeasureSpec.EXACTLY);
103f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell
104f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        final boolean canCollapse = !lockedExpanded && mAllowCollapse;
105f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell
106f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        if (canCollapse) {
107f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell            // See if we should expand
108f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell            mTabLayout.measure(MeasureSpec.UNSPECIFIED, heightMeasureSpec);
109f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell            if (mTabLayout.getMeasuredWidth() > MeasureSpec.getSize(widthMeasureSpec)) {
110f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell                performCollapse();
111f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell            } else {
112f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell                performExpand();
113f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell            }
114f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        } else {
115f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell            performExpand();
116f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        }
117f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell
118f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        final int oldWidth = getMeasuredWidth();
119f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
120f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        final int newWidth = getMeasuredWidth();
121f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell
122f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        if (lockedExpanded && oldWidth != newWidth) {
123f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell            // Recenter the tab display if we're at a new (scrollable) size.
124f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell            setTabSelected(mSelectedTabIndex);
125f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        }
126f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell    }
127f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell
128f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell    /**
129f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell     * Indicates whether this view is collapsed into a dropdown menu instead
130f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell     * of traditional tabs.
131f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell     * @return true if showing as a spinner
132f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell     */
133f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell    private boolean isCollapsed() {
134f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        return mTabSpinner != null && mTabSpinner.getParent() == this;
135f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell    }
136f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell
137f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell    public void setAllowCollapse(boolean allowCollapse) {
138f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        mAllowCollapse = allowCollapse;
139f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell    }
140f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell
141f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell    private void performCollapse() {
142f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        if (isCollapsed()) return;
143f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell
144f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        if (mTabSpinner == null) {
145f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell            mTabSpinner = createSpinner();
146f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell        }
147f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        removeView(mTabLayout);
148f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        addView(mTabSpinner, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
149f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell                ViewGroup.LayoutParams.MATCH_PARENT));
150f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        if (mTabSpinner.getAdapter() == null) {
151b9ead4a91599ca63e947f74f83b67a58bda64a82Alan Viverette            final TabAdapter adapter = new TabAdapter(mContext);
152b9ead4a91599ca63e947f74f83b67a58bda64a82Alan Viverette            adapter.setDropDownViewContext(mTabSpinner.getPopupContext());
153b9ead4a91599ca63e947f74f83b67a58bda64a82Alan Viverette            mTabSpinner.setAdapter(adapter);
154f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        }
155f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        if (mTabSelector != null) {
156f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell            removeCallbacks(mTabSelector);
157f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell            mTabSelector = null;
158f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        }
159f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        mTabSpinner.setSelection(mSelectedTabIndex);
160f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell    }
161f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell
162f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell    private boolean performExpand() {
163f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        if (!isCollapsed()) return false;
164f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell
165f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        removeView(mTabSpinner);
166f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        addView(mTabLayout, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
167f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell                ViewGroup.LayoutParams.MATCH_PARENT));
168f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        setTabSelected(mTabSpinner.getSelectedItemPosition());
169f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        return false;
170f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell    }
171f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell
172f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell    public void setTabSelected(int position) {
173f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        mSelectedTabIndex = position;
174f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell        final int tabCount = mTabLayout.getChildCount();
175f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell        for (int i = 0; i < tabCount; i++) {
176f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell            final View child = mTabLayout.getChildAt(i);
177f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell            final boolean isSelected = i == position;
178f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell            child.setSelected(isSelected);
179f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell            if (isSelected) {
180f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell                animateToTab(position);
181f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell            }
182f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell        }
183daa1d56726358c4db476dff75c7fd0be201c64c5Adam Powell        if (mTabSpinner != null && position >= 0) {
184daa1d56726358c4db476dff75c7fd0be201c64c5Adam Powell            mTabSpinner.setSelection(position);
185daa1d56726358c4db476dff75c7fd0be201c64c5Adam Powell        }
186f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell    }
187f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell
18845c0b1954d7dfa6e2590ed76b915a98ae971414cAdam Powell    public void setContentHeight(int contentHeight) {
189f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        mContentHeight = contentHeight;
19045c0b1954d7dfa6e2590ed76b915a98ae971414cAdam Powell        requestLayout();
19145c0b1954d7dfa6e2590ed76b915a98ae971414cAdam Powell    }
19245c0b1954d7dfa6e2590ed76b915a98ae971414cAdam Powell
193f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell    private LinearLayout createTabLayout() {
194f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        final LinearLayout tabLayout = new LinearLayout(getContext(), null,
195f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell                com.android.internal.R.attr.actionBarTabBarStyle);
196f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        tabLayout.setMeasureWithLargestChildEnabled(true);
197b8139af3dcae80c0030afd0354dc424a7c72c3d9Adam Powell        tabLayout.setGravity(Gravity.CENTER);
198f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        tabLayout.setLayoutParams(new LinearLayout.LayoutParams(
199f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell                LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.MATCH_PARENT));
200f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        return tabLayout;
201f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell    }
202f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell
203f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell    private Spinner createSpinner() {
204f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        final Spinner spinner = new Spinner(getContext(), null,
205f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell                com.android.internal.R.attr.actionDropDownStyle);
206f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        spinner.setLayoutParams(new LinearLayout.LayoutParams(
207f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell                LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.MATCH_PARENT));
208c4e57e23f99f4cea6fcca870a95f7f20a6edfaf2Adam Powell        spinner.setOnItemClickListenerInt(this);
209f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        return spinner;
210f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell    }
211f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell
212faa6ffa484f6f2a334c8bf2c7a9dc693a61608f3Adam Powell    @Override
213faa6ffa484f6f2a334c8bf2c7a9dc693a61608f3Adam Powell    protected void onConfigurationChanged(Configuration newConfig) {
214faa6ffa484f6f2a334c8bf2c7a9dc693a61608f3Adam Powell        super.onConfigurationChanged(newConfig);
215faa6ffa484f6f2a334c8bf2c7a9dc693a61608f3Adam Powell
216b8139af3dcae80c0030afd0354dc424a7c72c3d9Adam Powell        ActionBarPolicy abp = ActionBarPolicy.get(getContext());
217faa6ffa484f6f2a334c8bf2c7a9dc693a61608f3Adam Powell        // Action bar can change size on configuration changes.
218faa6ffa484f6f2a334c8bf2c7a9dc693a61608f3Adam Powell        // Reread the desired height from the theme-specified style.
219b8139af3dcae80c0030afd0354dc424a7c72c3d9Adam Powell        setContentHeight(abp.getTabContainerHeight());
220b8139af3dcae80c0030afd0354dc424a7c72c3d9Adam Powell        mStackedTabMaxWidth = abp.getStackedTabMaxWidth();
221faa6ffa484f6f2a334c8bf2c7a9dc693a61608f3Adam Powell    }
222faa6ffa484f6f2a334c8bf2c7a9dc693a61608f3Adam Powell
223f6ce6a9bacbb220c6ea7b552c481237f23e64ae7Adam Powell    public void animateToVisibility(int visibility) {
224f6ce6a9bacbb220c6ea7b552c481237f23e64ae7Adam Powell        if (mVisibilityAnim != null) {
225f6ce6a9bacbb220c6ea7b552c481237f23e64ae7Adam Powell            mVisibilityAnim.cancel();
226f6ce6a9bacbb220c6ea7b552c481237f23e64ae7Adam Powell        }
227f6ce6a9bacbb220c6ea7b552c481237f23e64ae7Adam Powell        if (visibility == VISIBLE) {
228f6ce6a9bacbb220c6ea7b552c481237f23e64ae7Adam Powell            if (getVisibility() != VISIBLE) {
229f6ce6a9bacbb220c6ea7b552c481237f23e64ae7Adam Powell                setAlpha(0);
230f6ce6a9bacbb220c6ea7b552c481237f23e64ae7Adam Powell            }
231f6ce6a9bacbb220c6ea7b552c481237f23e64ae7Adam Powell            ObjectAnimator anim = ObjectAnimator.ofFloat(this, "alpha", 1);
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        } else {
238f6ce6a9bacbb220c6ea7b552c481237f23e64ae7Adam Powell            ObjectAnimator anim = ObjectAnimator.ofFloat(this, "alpha", 0);
239f6ce6a9bacbb220c6ea7b552c481237f23e64ae7Adam Powell            anim.setDuration(FADE_DURATION);
240f6ce6a9bacbb220c6ea7b552c481237f23e64ae7Adam Powell            anim.setInterpolator(sAlphaInterpolator);
241f6ce6a9bacbb220c6ea7b552c481237f23e64ae7Adam Powell
242f6ce6a9bacbb220c6ea7b552c481237f23e64ae7Adam Powell            anim.addListener(mVisAnimListener.withFinalVisibility(visibility));
243f6ce6a9bacbb220c6ea7b552c481237f23e64ae7Adam Powell            anim.start();
244f6ce6a9bacbb220c6ea7b552c481237f23e64ae7Adam Powell        }
245f6ce6a9bacbb220c6ea7b552c481237f23e64ae7Adam Powell    }
246f6ce6a9bacbb220c6ea7b552c481237f23e64ae7Adam Powell
247f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell    public void animateToTab(final int position) {
248f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell        final View tabView = mTabLayout.getChildAt(position);
249f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell        if (mTabSelector != null) {
250f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell            removeCallbacks(mTabSelector);
251f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell        }
252f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell        mTabSelector = new Runnable() {
253f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell            public void run() {
254f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell                final int scrollPos = tabView.getLeft() - (getWidth() - tabView.getWidth()) / 2;
255f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell                smoothScrollTo(scrollPos, 0);
256f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell                mTabSelector = null;
257f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell            }
258f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell        };
259f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell        post(mTabSelector);
260f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell    }
261f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell
262f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell    @Override
263f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell    public void onAttachedToWindow() {
264f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        super.onAttachedToWindow();
265f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        if (mTabSelector != null) {
266f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell            // Re-post the selector we saved
267f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell            post(mTabSelector);
268f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell        }
269f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell    }
270f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell
271f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell    @Override
272f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell    public void onDetachedFromWindow() {
273f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell        super.onDetachedFromWindow();
274f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell        if (mTabSelector != null) {
275f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell            removeCallbacks(mTabSelector);
276f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell        }
277f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell    }
278f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell
279b9ead4a91599ca63e947f74f83b67a58bda64a82Alan Viverette    private TabView createTabView(Context context, ActionBar.Tab tab, boolean forAdapter) {
280b9ead4a91599ca63e947f74f83b67a58bda64a82Alan Viverette        final TabView tabView = new TabView(context, tab, forAdapter);
281f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        if (forAdapter) {
282f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell            tabView.setBackgroundDrawable(null);
283f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell            tabView.setLayoutParams(new ListView.LayoutParams(ListView.LayoutParams.MATCH_PARENT,
284f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell                    mContentHeight));
285f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        } else {
286f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell            tabView.setFocusable(true);
287f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell
288f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell            if (mTabClickListener == null) {
289f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell                mTabClickListener = new TabClickListener();
290f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell            }
291f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell            tabView.setOnClickListener(mTabClickListener);
292f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell        }
293f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell        return tabView;
294f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell    }
295f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell
296f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell    public void addTab(ActionBar.Tab tab, boolean setSelected) {
297b9ead4a91599ca63e947f74f83b67a58bda64a82Alan Viverette        TabView tabView = createTabView(mContext, tab, false);
298f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell        mTabLayout.addView(tabView, new LinearLayout.LayoutParams(0,
299f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell                LayoutParams.MATCH_PARENT, 1));
300f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        if (mTabSpinner != null) {
301f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell            ((TabAdapter) mTabSpinner.getAdapter()).notifyDataSetChanged();
302f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        }
303f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell        if (setSelected) {
304f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell            tabView.setSelected(true);
305f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell        }
306f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        if (mAllowCollapse) {
307f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell            requestLayout();
308f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        }
309f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell    }
310f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell
311f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell    public void addTab(ActionBar.Tab tab, int position, boolean setSelected) {
312b9ead4a91599ca63e947f74f83b67a58bda64a82Alan Viverette        final TabView tabView = createTabView(mContext, tab, false);
313f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell        mTabLayout.addView(tabView, position, new LinearLayout.LayoutParams(
314f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell                0, LayoutParams.MATCH_PARENT, 1));
315f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        if (mTabSpinner != null) {
316f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell            ((TabAdapter) mTabSpinner.getAdapter()).notifyDataSetChanged();
317f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        }
318f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell        if (setSelected) {
319f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell            tabView.setSelected(true);
320f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell        }
321f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        if (mAllowCollapse) {
322f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell            requestLayout();
323f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        }
324f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell    }
325f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell
326f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell    public void updateTab(int position) {
327f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell        ((TabView) mTabLayout.getChildAt(position)).update();
328f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        if (mTabSpinner != null) {
329f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell            ((TabAdapter) mTabSpinner.getAdapter()).notifyDataSetChanged();
330f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        }
331f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        if (mAllowCollapse) {
332f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell            requestLayout();
333f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        }
334f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell    }
335f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell
336f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell    public void removeTabAt(int position) {
337f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        mTabLayout.removeViewAt(position);
338f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        if (mTabSpinner != null) {
339f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell            ((TabAdapter) mTabSpinner.getAdapter()).notifyDataSetChanged();
340f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        }
341f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        if (mAllowCollapse) {
342f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell            requestLayout();
343f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell        }
344f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell    }
345f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell
346f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell    public void removeAllTabs() {
347f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        mTabLayout.removeAllViews();
348f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        if (mTabSpinner != null) {
349f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell            ((TabAdapter) mTabSpinner.getAdapter()).notifyDataSetChanged();
350f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        }
351f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        if (mAllowCollapse) {
352f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell            requestLayout();
353f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell        }
354f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell    }
355f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell
356f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell    @Override
357c4e57e23f99f4cea6fcca870a95f7f20a6edfaf2Adam Powell    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
358f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        TabView tabView = (TabView) view;
359f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        tabView.getTab().select();
360f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell    }
361f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell
362b265617b810082ec743389fa0468d1df91d66f68Vladislav Kaznacheev    private class TabView extends LinearLayout {
363f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell        private ActionBar.Tab mTab;
364f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell        private TextView mTextView;
365f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell        private ImageView mIconView;
366f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell        private View mCustomView;
367f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell
368f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        public TabView(Context context, ActionBar.Tab tab, boolean forList) {
369f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell            super(context, null, com.android.internal.R.attr.actionBarTabStyle);
370f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell            mTab = tab;
371f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell
372f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell            if (forList) {
373aac0d4ed026d1cfbcf3fa81c6e4eb96f4347ca17Fabrice Di Meglio                setGravity(Gravity.START | Gravity.CENTER_VERTICAL);
374f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell            }
375f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell
376f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell            update();
377f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        }
378f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell
379f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        public void bindTab(ActionBar.Tab tab) {
380f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell            mTab = tab;
381f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell            update();
382f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell        }
383f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell
384f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell        @Override
385b9f2e99f26c5cd3546235a183bb3402a2f1e82f8Alan Viverette        public void setSelected(boolean selected) {
386b9f2e99f26c5cd3546235a183bb3402a2f1e82f8Alan Viverette            final boolean changed = (isSelected() != selected);
387b9f2e99f26c5cd3546235a183bb3402a2f1e82f8Alan Viverette            super.setSelected(selected);
388b9f2e99f26c5cd3546235a183bb3402a2f1e82f8Alan Viverette            if (changed && selected) {
389b9f2e99f26c5cd3546235a183bb3402a2f1e82f8Alan Viverette                sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED);
390b9f2e99f26c5cd3546235a183bb3402a2f1e82f8Alan Viverette            }
391b9f2e99f26c5cd3546235a183bb3402a2f1e82f8Alan Viverette        }
392b9f2e99f26c5cd3546235a183bb3402a2f1e82f8Alan Viverette
393b9f2e99f26c5cd3546235a183bb3402a2f1e82f8Alan Viverette        @Override
394a7bb6fbeab933326d58aa806d8194b7b13239d34Dianne Hackborn        public CharSequence getAccessibilityClassName() {
395b9f2e99f26c5cd3546235a183bb3402a2f1e82f8Alan Viverette            // This view masquerades as an action bar tab.
396a7bb6fbeab933326d58aa806d8194b7b13239d34Dianne Hackborn            return ActionBar.Tab.class.getName();
397b9f2e99f26c5cd3546235a183bb3402a2f1e82f8Alan Viverette        }
398b9f2e99f26c5cd3546235a183bb3402a2f1e82f8Alan Viverette
399b9f2e99f26c5cd3546235a183bb3402a2f1e82f8Alan Viverette        @Override
400f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell        public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
401f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
402f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell
403f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell            // Re-measure if we went beyond our maximum size.
404f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell            if (mMaxTabWidth > 0 && getMeasuredWidth() > mMaxTabWidth) {
405f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell                super.onMeasure(MeasureSpec.makeMeasureSpec(mMaxTabWidth, MeasureSpec.EXACTLY),
406f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell                        heightMeasureSpec);
407f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell            }
408f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell        }
409f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell
410f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell        public void update() {
411f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell            final ActionBar.Tab tab = mTab;
412f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell            final View custom = tab.getCustomView();
413f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell            if (custom != null) {
41405c8277f3423fd57196b3878d27ac0f1995101a8Adam Powell                final ViewParent customParent = custom.getParent();
41505c8277f3423fd57196b3878d27ac0f1995101a8Adam Powell                if (customParent != this) {
41605c8277f3423fd57196b3878d27ac0f1995101a8Adam Powell                    if (customParent != null) ((ViewGroup) customParent).removeView(custom);
41705c8277f3423fd57196b3878d27ac0f1995101a8Adam Powell                    addView(custom);
41805c8277f3423fd57196b3878d27ac0f1995101a8Adam Powell                }
419f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell                mCustomView = custom;
420f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell                if (mTextView != null) mTextView.setVisibility(GONE);
421f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell                if (mIconView != null) {
422f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell                    mIconView.setVisibility(GONE);
423f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell                    mIconView.setImageDrawable(null);
424f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell                }
425f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell            } else {
426f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell                if (mCustomView != null) {
427f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell                    removeView(mCustomView);
428f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell                    mCustomView = null;
429f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell                }
430f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell
431f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell                final Drawable icon = tab.getIcon();
432f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell                final CharSequence text = tab.getText();
433f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell
434f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell                if (icon != null) {
435f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell                    if (mIconView == null) {
436f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell                        ImageView iconView = new ImageView(getContext());
437f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell                        LayoutParams lp = new LayoutParams(LayoutParams.WRAP_CONTENT,
438f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell                                LayoutParams.WRAP_CONTENT);
439f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell                        lp.gravity = Gravity.CENTER_VERTICAL;
440f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell                        iconView.setLayoutParams(lp);
441f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell                        addView(iconView, 0);
442f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell                        mIconView = iconView;
443f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell                    }
444f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell                    mIconView.setImageDrawable(icon);
445f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell                    mIconView.setVisibility(VISIBLE);
446f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell                } else if (mIconView != null) {
447f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell                    mIconView.setVisibility(GONE);
448f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell                    mIconView.setImageDrawable(null);
449f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell                }
450f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell
451c7752a312adfe108c3b0e9143122152f2470be31Adam Powell                final boolean hasText = !TextUtils.isEmpty(text);
452c7752a312adfe108c3b0e9143122152f2470be31Adam Powell                if (hasText) {
453f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell                    if (mTextView == null) {
454f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell                        TextView textView = new TextView(getContext(), null,
455f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell                                com.android.internal.R.attr.actionBarTabTextStyle);
456f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell                        textView.setEllipsize(TruncateAt.END);
457f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell                        LayoutParams lp = new LayoutParams(LayoutParams.WRAP_CONTENT,
458f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell                                LayoutParams.WRAP_CONTENT);
459f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell                        lp.gravity = Gravity.CENTER_VERTICAL;
460f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell                        textView.setLayoutParams(lp);
461f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell                        addView(textView);
462f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell                        mTextView = textView;
463f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell                    }
464f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell                    mTextView.setText(text);
465f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell                    mTextView.setVisibility(VISIBLE);
466251df77861525cca79d38bcee7c45c16c6752e40Adam Powell                } else if (mTextView != null) {
467f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell                    mTextView.setVisibility(GONE);
468251df77861525cca79d38bcee7c45c16c6752e40Adam Powell                    mTextView.setText(null);
469f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell                }
47094e56ef3b8de6ed485546b462559ac862c10eabfAdam Powell
47165d570447641d1575aa59d511591402e431fdd2eAdam Powell                if (mIconView != null) {
47265d570447641d1575aa59d511591402e431fdd2eAdam Powell                    mIconView.setContentDescription(tab.getContentDescription());
47365d570447641d1575aa59d511591402e431fdd2eAdam Powell                }
4746a944ca17547e520ed4988125ee4c1f172c87946Vladislav Kaznacheev                setTooltipText(hasText? null : tab.getContentDescription());
475f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell            }
476f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell        }
477f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell
478f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell        public ActionBar.Tab getTab() {
479f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell            return mTab;
480f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell        }
481f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell    }
482f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell
483f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell    private class TabAdapter extends BaseAdapter {
484b9ead4a91599ca63e947f74f83b67a58bda64a82Alan Viverette        private Context mDropDownContext;
485b9ead4a91599ca63e947f74f83b67a58bda64a82Alan Viverette
486b9ead4a91599ca63e947f74f83b67a58bda64a82Alan Viverette        public TabAdapter(Context context) {
487b9ead4a91599ca63e947f74f83b67a58bda64a82Alan Viverette            setDropDownViewContext(context);
488b9ead4a91599ca63e947f74f83b67a58bda64a82Alan Viverette        }
489b9ead4a91599ca63e947f74f83b67a58bda64a82Alan Viverette
490b9ead4a91599ca63e947f74f83b67a58bda64a82Alan Viverette        public void setDropDownViewContext(Context context) {
491b9ead4a91599ca63e947f74f83b67a58bda64a82Alan Viverette            mDropDownContext = context;
492b9ead4a91599ca63e947f74f83b67a58bda64a82Alan Viverette        }
493b9ead4a91599ca63e947f74f83b67a58bda64a82Alan Viverette
494f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        @Override
495f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        public int getCount() {
496f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell            return mTabLayout.getChildCount();
497f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        }
498f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell
499f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        @Override
500f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        public Object getItem(int position) {
501f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell            return ((TabView) mTabLayout.getChildAt(position)).getTab();
502f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        }
503f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell
504f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        @Override
505f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        public long getItemId(int position) {
506f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell            return position;
507f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        }
508f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell
509f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        @Override
510f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        public View getView(int position, View convertView, ViewGroup parent) {
511f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell            if (convertView == null) {
512b9ead4a91599ca63e947f74f83b67a58bda64a82Alan Viverette                convertView = createTabView(mContext, (ActionBar.Tab) getItem(position), true);
513b9ead4a91599ca63e947f74f83b67a58bda64a82Alan Viverette            } else {
514b9ead4a91599ca63e947f74f83b67a58bda64a82Alan Viverette                ((TabView) convertView).bindTab((ActionBar.Tab) getItem(position));
515b9ead4a91599ca63e947f74f83b67a58bda64a82Alan Viverette            }
516b9ead4a91599ca63e947f74f83b67a58bda64a82Alan Viverette            return convertView;
517b9ead4a91599ca63e947f74f83b67a58bda64a82Alan Viverette        }
518b9ead4a91599ca63e947f74f83b67a58bda64a82Alan Viverette
519b9ead4a91599ca63e947f74f83b67a58bda64a82Alan Viverette        @Override
520b9ead4a91599ca63e947f74f83b67a58bda64a82Alan Viverette        public View getDropDownView(int position, View convertView, ViewGroup parent) {
521b9ead4a91599ca63e947f74f83b67a58bda64a82Alan Viverette            if (convertView == null) {
522b9ead4a91599ca63e947f74f83b67a58bda64a82Alan Viverette                convertView = createTabView(mDropDownContext,
523b9ead4a91599ca63e947f74f83b67a58bda64a82Alan Viverette                        (ActionBar.Tab) getItem(position), true);
524f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell            } else {
525f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell                ((TabView) convertView).bindTab((ActionBar.Tab) getItem(position));
526f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell            }
527f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell            return convertView;
528f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell        }
529f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell    }
530f5645cbafe7eed33452d888f16726bee8a0cd9feAdam Powell
531f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell    private class TabClickListener implements OnClickListener {
532f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell        public void onClick(View view) {
533f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell            TabView tabView = (TabView) view;
534f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell            tabView.getTab().select();
535f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell            final int tabCount = mTabLayout.getChildCount();
536f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell            for (int i = 0; i < tabCount; i++) {
537f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell                final View child = mTabLayout.getChildAt(i);
538f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell                child.setSelected(child == view);
539f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell            }
540f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell        }
541f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell    }
542f6ce6a9bacbb220c6ea7b552c481237f23e64ae7Adam Powell
543f6ce6a9bacbb220c6ea7b552c481237f23e64ae7Adam Powell    protected class VisibilityAnimListener implements Animator.AnimatorListener {
544f6ce6a9bacbb220c6ea7b552c481237f23e64ae7Adam Powell        private boolean mCanceled = false;
545f6ce6a9bacbb220c6ea7b552c481237f23e64ae7Adam Powell        private int mFinalVisibility;
546f6ce6a9bacbb220c6ea7b552c481237f23e64ae7Adam Powell
547f6ce6a9bacbb220c6ea7b552c481237f23e64ae7Adam Powell        public VisibilityAnimListener withFinalVisibility(int visibility) {
548f6ce6a9bacbb220c6ea7b552c481237f23e64ae7Adam Powell            mFinalVisibility = visibility;
549f6ce6a9bacbb220c6ea7b552c481237f23e64ae7Adam Powell            return this;
550f6ce6a9bacbb220c6ea7b552c481237f23e64ae7Adam Powell        }
551f6ce6a9bacbb220c6ea7b552c481237f23e64ae7Adam Powell
552f6ce6a9bacbb220c6ea7b552c481237f23e64ae7Adam Powell        @Override
553f6ce6a9bacbb220c6ea7b552c481237f23e64ae7Adam Powell        public void onAnimationStart(Animator animation) {
554f6ce6a9bacbb220c6ea7b552c481237f23e64ae7Adam Powell            setVisibility(VISIBLE);
555f6ce6a9bacbb220c6ea7b552c481237f23e64ae7Adam Powell            mVisibilityAnim = animation;
556f6ce6a9bacbb220c6ea7b552c481237f23e64ae7Adam Powell            mCanceled = false;
557f6ce6a9bacbb220c6ea7b552c481237f23e64ae7Adam Powell        }
558f6ce6a9bacbb220c6ea7b552c481237f23e64ae7Adam Powell
559f6ce6a9bacbb220c6ea7b552c481237f23e64ae7Adam Powell        @Override
560f6ce6a9bacbb220c6ea7b552c481237f23e64ae7Adam Powell        public void onAnimationEnd(Animator animation) {
561f6ce6a9bacbb220c6ea7b552c481237f23e64ae7Adam Powell            if (mCanceled) return;
562f6ce6a9bacbb220c6ea7b552c481237f23e64ae7Adam Powell
563f6ce6a9bacbb220c6ea7b552c481237f23e64ae7Adam Powell            mVisibilityAnim = null;
564f6ce6a9bacbb220c6ea7b552c481237f23e64ae7Adam Powell            setVisibility(mFinalVisibility);
565f6ce6a9bacbb220c6ea7b552c481237f23e64ae7Adam Powell        }
566f6ce6a9bacbb220c6ea7b552c481237f23e64ae7Adam Powell
567f6ce6a9bacbb220c6ea7b552c481237f23e64ae7Adam Powell        @Override
568f6ce6a9bacbb220c6ea7b552c481237f23e64ae7Adam Powell        public void onAnimationCancel(Animator animation) {
569f6ce6a9bacbb220c6ea7b552c481237f23e64ae7Adam Powell            mCanceled = true;
570f6ce6a9bacbb220c6ea7b552c481237f23e64ae7Adam Powell        }
571f6ce6a9bacbb220c6ea7b552c481237f23e64ae7Adam Powell
572f6ce6a9bacbb220c6ea7b552c481237f23e64ae7Adam Powell        @Override
573f6ce6a9bacbb220c6ea7b552c481237f23e64ae7Adam Powell        public void onAnimationRepeat(Animator animation) {
574f6ce6a9bacbb220c6ea7b552c481237f23e64ae7Adam Powell        }
575f6ce6a9bacbb220c6ea7b552c481237f23e64ae7Adam Powell    }
576f8ac6b7394cfd37f01471bb35475ff2930eee140Adam Powell}
577