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