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