FragmentTabsPager.java revision 865abe20dd1a639efe9a013240e61613a52b6648
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.example.android.supportv4.app;
17
18import com.example.android.supportv4.R;
19
20import android.content.Context;
21import android.os.Bundle;
22import android.support.v4.app.Fragment;
23import android.support.v4.app.FragmentActivity;
24import android.support.v4.app.FragmentPagerAdapter;
25import android.support.v4.view.ViewPager;
26import android.view.View;
27import android.view.ViewGroup;
28import android.widget.TabHost;
29import android.widget.TabWidget;
30
31import java.util.ArrayList;
32
33/**
34 * Demonstrates combining a TabHost with a ViewPager to implement a tab UI
35 * that switches between tabs and also allows the user to perform horizontal
36 * flicks to move between the tabs.
37 */
38public class FragmentTabsPager extends FragmentActivity {
39    TabHost mTabHost;
40    ViewPager  mViewPager;
41    TabsAdapter mTabsAdapter;
42
43    @Override
44    protected void onCreate(Bundle savedInstanceState) {
45        super.onCreate(savedInstanceState);
46
47        setContentView(R.layout.fragment_tabs_pager);
48        mTabHost = (TabHost)findViewById(android.R.id.tabhost);
49        mTabHost.setup();
50
51        mViewPager = (ViewPager)findViewById(R.id.pager);
52
53        mTabsAdapter = new TabsAdapter(this, mTabHost, mViewPager);
54
55        mTabsAdapter.addTab(mTabHost.newTabSpec("simple").setIndicator("Simple"),
56                FragmentStackSupport.CountingFragment.class, null);
57        mTabsAdapter.addTab(mTabHost.newTabSpec("contacts").setIndicator("Contacts"),
58                LoaderCursorSupport.CursorLoaderListFragment.class, null);
59        mTabsAdapter.addTab(mTabHost.newTabSpec("custom").setIndicator("Custom"),
60                LoaderCustomSupport.AppListFragment.class, null);
61        mTabsAdapter.addTab(mTabHost.newTabSpec("throttle").setIndicator("Throttle"),
62                LoaderThrottleSupport.ThrottledLoaderListFragment.class, null);
63
64        if (savedInstanceState != null) {
65            mTabHost.setCurrentTabByTag(savedInstanceState.getString("tab"));
66        }
67    }
68
69    @Override
70    protected void onSaveInstanceState(Bundle outState) {
71        super.onSaveInstanceState(outState);
72        outState.putString("tab", mTabHost.getCurrentTabTag());
73    }
74
75    /**
76     * This is a helper class that implements the management of tabs and all
77     * details of connecting a ViewPager with associated TabHost.  It relies on a
78     * trick.  Normally a tab host has a simple API for supplying a View or
79     * Intent that each tab will show.  This is not sufficient for switching
80     * between pages.  So instead we make the content part of the tab host
81     * 0dp high (it is not shown) and the TabsAdapter supplies its own dummy
82     * view to show as the tab content.  It listens to changes in tabs, and takes
83     * care of switch to the correct paged in the ViewPager whenever the selected
84     * tab changes.
85     */
86    public static class TabsAdapter extends FragmentPagerAdapter
87            implements TabHost.OnTabChangeListener, ViewPager.OnPageChangeListener {
88        private final Context mContext;
89        private final TabHost mTabHost;
90        private final ViewPager mViewPager;
91        private final ArrayList<TabInfo> mTabs = new ArrayList<TabInfo>();
92
93        static final class TabInfo {
94            private final String tag;
95            private final Class<?> clss;
96            private final Bundle args;
97
98            TabInfo(String _tag, Class<?> _class, Bundle _args) {
99                tag = _tag;
100                clss = _class;
101                args = _args;
102            }
103        }
104
105        static class DummyTabFactory implements TabHost.TabContentFactory {
106            private final Context mContext;
107
108            public DummyTabFactory(Context context) {
109                mContext = context;
110            }
111
112            @Override
113            public View createTabContent(String tag) {
114                View v = new View(mContext);
115                v.setMinimumWidth(0);
116                v.setMinimumHeight(0);
117                return v;
118            }
119        }
120
121        public TabsAdapter(FragmentActivity activity, TabHost tabHost, ViewPager pager) {
122            super(activity.getSupportFragmentManager());
123            mContext = activity;
124            mTabHost = tabHost;
125            mViewPager = pager;
126            mTabHost.setOnTabChangedListener(this);
127            mViewPager.setAdapter(this);
128            mViewPager.setOnPageChangeListener(this);
129        }
130
131        public void addTab(TabHost.TabSpec tabSpec, Class<?> clss, Bundle args) {
132            tabSpec.setContent(new DummyTabFactory(mContext));
133            String tag = tabSpec.getTag();
134
135            TabInfo info = new TabInfo(tag, clss, args);
136            mTabs.add(info);
137            mTabHost.addTab(tabSpec);
138            notifyDataSetChanged();
139        }
140
141        @Override
142        public int getCount() {
143            return mTabs.size();
144        }
145
146        @Override
147        public Fragment getItem(int position) {
148            TabInfo info = mTabs.get(position);
149            return Fragment.instantiate(mContext, info.clss.getName(), info.args);
150        }
151
152        @Override
153        public void onTabChanged(String tabId) {
154            int position = mTabHost.getCurrentTab();
155            mViewPager.setCurrentItem(position);
156        }
157
158        @Override
159        public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
160        }
161
162        @Override
163        public void onPageSelected(int position) {
164            // Unfortunately when TabHost changes the current tab, it kindly
165            // also takes care of putting focus on it when not in touch mode.
166            // The jerk.
167            // This hack tries to prevent this from pulling focus out of our
168            // ViewPager.
169            TabWidget widget = mTabHost.getTabWidget();
170            int oldFocusability = widget.getDescendantFocusability();
171            widget.setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS);
172            mTabHost.setCurrentTab(position);
173            widget.setDescendantFocusability(oldFocusability);
174        }
175
176        @Override
177        public void onPageScrollStateChanged(int state) {
178        }
179    }
180}
181