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