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