ScrollingTabContainerView.java revision f8ac6b7394cfd37f01471bb35475ff2930eee140
1/* 2 * Copyright (C) 2011 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16package com.android.internal.widget; 17 18import android.app.ActionBar; 19import android.content.Context; 20import android.graphics.drawable.Drawable; 21import android.text.TextUtils.TruncateAt; 22import android.view.Gravity; 23import android.view.View; 24import android.view.ViewGroup; 25import android.widget.HorizontalScrollView; 26import android.widget.ImageView; 27import android.widget.LinearLayout; 28import android.widget.TextView; 29 30public class ScrollingTabContainerView extends HorizontalScrollView { 31 Runnable mTabSelector; 32 private TabClickListener mTabClickListener; 33 34 private LinearLayout mTabLayout; 35 36 int mMaxTabWidth; 37 38 public ScrollingTabContainerView(Context context) { 39 super(context); 40 setHorizontalScrollBarEnabled(false); 41 } 42 43 @Override 44 public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 45 final int widthMode = MeasureSpec.getMode(widthMeasureSpec); 46 setFillViewport(widthMode == MeasureSpec.EXACTLY); 47 48 final int childCount = getChildCount(); 49 if (childCount > 1 && 50 (widthMode == MeasureSpec.EXACTLY || widthMode == MeasureSpec.AT_MOST)) { 51 if (childCount > 2) { 52 mMaxTabWidth = (int) (MeasureSpec.getSize(widthMeasureSpec) * 0.4f); 53 } else { 54 mMaxTabWidth = MeasureSpec.getSize(widthMeasureSpec) / 2; 55 } 56 } else { 57 mMaxTabWidth = -1; 58 } 59 60 super.onMeasure(widthMeasureSpec, heightMeasureSpec); 61 } 62 63 public void setTabSelected(int position) { 64 if (mTabLayout == null) { 65 return; 66 } 67 68 final int tabCount = mTabLayout.getChildCount(); 69 for (int i = 0; i < tabCount; i++) { 70 final View child = mTabLayout.getChildAt(i); 71 final boolean isSelected = i == position; 72 child.setSelected(isSelected); 73 if (isSelected) { 74 animateToTab(position); 75 } 76 } 77 } 78 79 public void animateToTab(int position) { 80 final View tabView = mTabLayout.getChildAt(position); 81 if (mTabSelector != null) { 82 removeCallbacks(mTabSelector); 83 } 84 mTabSelector = new Runnable() { 85 public void run() { 86 final int scrollPos = tabView.getLeft() - (getWidth() - tabView.getWidth()) / 2; 87 smoothScrollTo(scrollPos, 0); 88 mTabSelector = null; 89 } 90 }; 91 post(mTabSelector); 92 } 93 94 public void setTabLayout(LinearLayout tabLayout) { 95 if (mTabLayout != tabLayout) { 96 if (mTabLayout != null) { 97 ((ViewGroup) mTabLayout.getParent()).removeView(mTabLayout); 98 } 99 if (tabLayout != null) { 100 addView(tabLayout); 101 } 102 mTabLayout = tabLayout; 103 } 104 } 105 106 public LinearLayout getTabLayout() { 107 return mTabLayout; 108 } 109 110 @Override 111 public void onDetachedFromWindow() { 112 super.onDetachedFromWindow(); 113 if (mTabSelector != null) { 114 removeCallbacks(mTabSelector); 115 } 116 } 117 118 private TabView createTabView(ActionBar.Tab tab) { 119 final TabView tabView = new TabView(getContext(), tab); 120 tabView.setFocusable(true); 121 122 if (mTabClickListener == null) { 123 mTabClickListener = new TabClickListener(); 124 } 125 tabView.setOnClickListener(mTabClickListener); 126 return tabView; 127 } 128 129 public void addTab(ActionBar.Tab tab, boolean setSelected) { 130 View tabView = createTabView(tab); 131 mTabLayout.addView(tabView, new LinearLayout.LayoutParams(0, 132 LayoutParams.MATCH_PARENT, 1)); 133 if (setSelected) { 134 tabView.setSelected(true); 135 } 136 } 137 138 public void addTab(ActionBar.Tab tab, int position, boolean setSelected) { 139 final TabView tabView = createTabView(tab); 140 mTabLayout.addView(tabView, position, new LinearLayout.LayoutParams( 141 0, LayoutParams.MATCH_PARENT, 1)); 142 if (setSelected) { 143 tabView.setSelected(true); 144 } 145 } 146 147 public void updateTab(int position) { 148 ((TabView) mTabLayout.getChildAt(position)).update(); 149 } 150 151 public void removeTabAt(int position) { 152 if (mTabLayout != null) { 153 mTabLayout.removeViewAt(position); 154 } 155 } 156 157 public void removeAllTabs() { 158 if (mTabLayout != null) { 159 mTabLayout.removeAllViews(); 160 } 161 } 162 163 private class TabView extends LinearLayout { 164 private ActionBar.Tab mTab; 165 private TextView mTextView; 166 private ImageView mIconView; 167 private View mCustomView; 168 169 public TabView(Context context, ActionBar.Tab tab) { 170 super(context, null, com.android.internal.R.attr.actionBarTabStyle); 171 mTab = tab; 172 173 update(); 174 } 175 176 @Override 177 public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 178 super.onMeasure(widthMeasureSpec, heightMeasureSpec); 179 180 // Re-measure if we went beyond our maximum size. 181 if (mMaxTabWidth > 0 && getMeasuredWidth() > mMaxTabWidth) { 182 super.onMeasure(MeasureSpec.makeMeasureSpec(mMaxTabWidth, MeasureSpec.EXACTLY), 183 heightMeasureSpec); 184 } 185 } 186 187 public void update() { 188 final ActionBar.Tab tab = mTab; 189 final View custom = tab.getCustomView(); 190 if (custom != null) { 191 addView(custom); 192 mCustomView = custom; 193 if (mTextView != null) mTextView.setVisibility(GONE); 194 if (mIconView != null) { 195 mIconView.setVisibility(GONE); 196 mIconView.setImageDrawable(null); 197 } 198 } else { 199 if (mCustomView != null) { 200 removeView(mCustomView); 201 mCustomView = null; 202 } 203 204 final Drawable icon = tab.getIcon(); 205 final CharSequence text = tab.getText(); 206 207 if (icon != null) { 208 if (mIconView == null) { 209 ImageView iconView = new ImageView(getContext()); 210 LayoutParams lp = new LayoutParams(LayoutParams.WRAP_CONTENT, 211 LayoutParams.WRAP_CONTENT); 212 lp.gravity = Gravity.CENTER_VERTICAL; 213 iconView.setLayoutParams(lp); 214 addView(iconView, 0); 215 mIconView = iconView; 216 } 217 mIconView.setImageDrawable(icon); 218 mIconView.setVisibility(VISIBLE); 219 } else if (mIconView != null) { 220 mIconView.setVisibility(GONE); 221 mIconView.setImageDrawable(null); 222 } 223 224 if (text != null) { 225 if (mTextView == null) { 226 TextView textView = new TextView(getContext(), null, 227 com.android.internal.R.attr.actionBarTabTextStyle); 228 textView.setSingleLine(); 229 textView.setEllipsize(TruncateAt.END); 230 LayoutParams lp = new LayoutParams(LayoutParams.WRAP_CONTENT, 231 LayoutParams.WRAP_CONTENT); 232 lp.gravity = Gravity.CENTER_VERTICAL; 233 textView.setLayoutParams(lp); 234 addView(textView); 235 mTextView = textView; 236 } 237 mTextView.setText(text); 238 mTextView.setVisibility(VISIBLE); 239 } else { 240 mTextView.setVisibility(GONE); 241 } 242 } 243 } 244 245 public ActionBar.Tab getTab() { 246 return mTab; 247 } 248 } 249 250 private class TabClickListener implements OnClickListener { 251 public void onClick(View view) { 252 TabView tabView = (TabView) view; 253 tabView.getTab().select(); 254 final int tabCount = mTabLayout.getChildCount(); 255 for (int i = 0; i < tabCount; i++) { 256 final View child = mTabLayout.getChildAt(i); 257 child.setSelected(child == view); 258 } 259 } 260 } 261} 262