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