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