I'm trying to create an Android application which contains a single activity with a container and a navigation drawer. The initialy empty container loads fragments which has a ViewPager inside a tab layout in which I load a frgment with a FragmentTransaction:
public static void replaceFragmentInContainer(FragmentManager fragmentManager, Fragment fragmentToShow,
boolean addToBackStack)
{
FragmentTransaction transaction = fragmentManager.beginTransaction();
if (addToBackStack)
{
transaction.addToBackStack(null);
}
transaction.replace(R.id.container, fragmentToShow);
transaction.commit();
}
The problem I'm facing is with the backstack. When a fragment is added to the backstack and I press the back button, the app does go back to the previous fragment like I want to and I do see the tabs layout itself, but the content of the tabs is empty like there was nothing loaded to that tab. When it happens, I manage to reload the tab's content only when choosing that screen again with the navigational drawer.
After debugging I saw that the pager adapter's getItem method is not getting called when pressing the back button. The adapter itself is FragmentStatePagerAdapter.
I tried overriding the getItemPosition method:
public int getItemPosition(Object object)
{
return POSITION_NONE;
}
but that method wasn't called either when pressing the back button so I end up seeing empty tabs.
And this is the tabs adapter which is also the ViewPager adapter:
public static class TabsAdapter extends FragmentStatePagerAdapter implements TabHost.OnTabChangeListener,
ViewPager.OnPageChangeListener
{
private final Context mContext;
private final TabHost mTabHost;
private final ViewPager mViewPager;
private final ArrayList<TabInfo> mTabs = new ArrayList<TabInfo>();
public TabsAdapter(final FragmentActivity activity, final TabHost tabHost, final ViewPager pager)
{
super(activity.getSupportFragmentManager());
mContext = activity;
mTabHost = tabHost;
mViewPager = pager;
mTabHost.setOnTabChangedListener(this);
mViewPager.setAdapter(this);
mViewPager.setOnPageChangeListener(this);
}
public ViewPager getViewPager()
{
return mViewPager;
}
static final class TabInfo
{
private final String tag;
private final Class<?> clss;
private final Bundle args;
TabInfo(final String _tag, final Class<?> _class, final Bundle _args)
{
tag = _tag;
clss = _class;
args = _args;
}
}
static class TabFactory implements TabHost.TabContentFactory
{
private final Context mContext;
public TabFactory(final Context context)
{
mContext = context;
}
#Override
public View createTabContent(final String tag)
{
final View v = new View(mContext);
v.setMinimumWidth(0);
v.setMinimumHeight(0);
return v;
}
}
public void addTab(final TabHost.TabSpec tabSpec, final Class<?> clss, final Bundle args)
{
tabSpec.setContent(new TabFactory(mContext));
final String tag = tabSpec.getTag();
final TabInfo info = new TabInfo(tag, clss, args);
mTabs.add(info);
mTabHost.addTab(tabSpec);
notifyDataSetChanged();
}
#Override
public int getCount()
{
return mTabs.size();
}
#Override
public Fragment getItem(final int position)
{
final TabInfo info = mTabs.get(position);
return Fragment.instantiate(mContext, info.clss.getName(), info.args);
}
// #Override
// public Object instantiateItem(ViewGroup container, int position)
// {
//
// // Inflate a new layout from the resources.
// View view = ((Activity) mContext).getLayoutInflater().inflate(
// R.layout.fragment_single_conversation, container, false);
// // Add the newly created View to the ViewPager
// container.addView(view);
//
// // Populate the GUI and views now
// return view;
// }
#Override
public int getItemPosition(Object object)
{
return POSITION_NONE;
}
#Override
public void onTabChanged(final String tabId)
{
final int position = mTabHost.getCurrentTab();
mViewPager.setCurrentItem(position);
}
#Override
public void onPageScrolled(final int position, final float positionOffset,
final int positionOffsetPixels)
{
}
#Override
public void onPageSelected(final int position)
{
// Unfortunately when TabHost changes the current tab, it kindly
// also takes care of putting focus on it when not in touch mode.
// The jerk.
// This hack tries to prevent this from pulling focus out of our
// ViewPager.
final TabWidget widget = mTabHost.getTabWidget();
final int oldFocusability = widget.getDescendantFocusability();
widget.setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS);
mTabHost.setCurrentTab(position);
widget.setDescendantFocusability(oldFocusability);
}
#Override
public void onPageScrollStateChanged(final int state)
{
}
}
How can this issue be solved?
Related
I am using a custom FragmentPagerAdapter that in the beggining has a certain number of fragments in it by using a tabHost:
public class TabsAdapter extends FragmentPagerAdapter implements TabHost.OnTabChangeListener, ViewPager.OnPageChangeListener
{
private final Context mcon;
private final TabHost mTabHost;
private final ViewPager mViewPager;
private final ArrayList<TabInfo> mTabs = new ArrayList<TabInfo>();
final class TabInfo
{
private final String tag;
private final Class<?> clss;
private final Bundle args;
TabInfo(String _tag, Class<?> _class, Bundle _args)
{
tag = _tag;
clss = _class;
args = _args;
}
}
class DummyTabFactory implements TabHost.TabContentFactory
{
private final Context mcon;
public DummyTabFactory(Context context)
{
mcon = context;
}
public View createTabContent(String tag)
{
View v = new View(mcon);
v.setMinimumWidth(0);
v.setMinimumHeight(0);
return v;
}
}
public TabsAdapter(Fragment fragment, TabHost tabHost, ViewPager pager) {
super(fragment.getChildFragmentManager());
mcon = fragment.getActivity();
mTabHost = tabHost;
mViewPager = pager;
mTabHost.setOnTabChangedListener(this);
mViewPager.setAdapter(this);
mViewPager.setOnPageChangeListener(this);
}
public void addTab(TabHost.TabSpec tabSpec, Class<?> clss, Bundle args)
{
tabSpec.setContent(new DummyTabFactory(mcon));
String tag = tabSpec.getTag();
TabInfo info = new TabInfo(tag, clss, args);
mTabs.add(info);
notifyDataSetChanged();
mTabHost.addTab(tabSpec);
}
#Override
public int getCount()
{
return mTabs.size();
}
#Override
public Fragment getItem(int position)
{
TabInfo info = mTabs.get(position);
return Fragment.instantiate(mcon, info.clss.getName(), info.args);
}
public void onTabChanged(String tabId)
{
int position = mTabHost.getCurrentTab();
mViewPager.setCurrentItem(position);
}
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
View tabView = mTabHost.getTabWidget().getChildAt(position);
if (tabView != null)
{
final int width = mHorizontalScroll.getWidth();
final int scrollPos = tabView.getLeft() - (width - tabView.getWidth()) / 2;
mHorizontalScroll.scrollTo(scrollPos, 0);
} else {
mHorizontalScroll.scrollBy(positionOffsetPixels, 0);
}
}
public void onPageSelected(int position)
{
// Unfortunately when TabHost changes the current tab, it kindly
// also takes care of putting focus on it when not in touch mode.
// The jerk.
// This hack tries to prevent this from pulling focus out of our
// ViewPager.
TabWidget widget = mTabHost.getTabWidget();
int oldFocusability = widget.getDescendantFocusability();
widget.setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS);
mTabHost.setCurrentTab(position);
widget.setDescendantFocusability(oldFocusability);
}
public void onPageScrollStateChanged(int state)
{
}
}
Every fragment is created in the beggining by:
mTabsAdapter.addTab(mTabHost.newTabSpec("tab1").setIndicator("tab1")), InsideFragment.class, gargs);
What I want to do is to update the number of fragments (add/remove fragment) from inside one of the InsideFragments, after it has been initialized. How could I do that?
I didn't test it but maybe you could pass an interface from the MainFragment to the ChildFragment. Then in the ChildFragment you would call a method of this interface like, listener.refreshParent().
Take a look at this answer: https://stackoverflow.com/a/18585247/3465623
I have implemented NavigationDrawer which has static types of items in it. And I have added ViewPager and Tabs in one of the many fragments. Everything is working fine till now. But now I want to open specific tabs and ViewPagers onClick of the items of that NavigationDrawer. I'm trying to set the current item and tab from the adapter class of the NavigationDrawer but not getting proper result.
TabsAdapter.java
public static class TabsAdapter extends FragmentPagerAdapter implements TabHost.OnTabChangeListener, ViewPager.OnPageChangeListener {
private final Context mContext;
private final TabHost mTabHost;
private final ViewPager mViewPager;
private final ArrayList<TabInfo> mTabs = new ArrayList<TabInfo>();
static final class TabInfo {
private final String tag;
private final Class<?> clss;
private final Bundle args;
TabInfo(String _tag, Class<?> _class, Bundle _args) {
tag = _tag;
clss = _class;
args = _args;
}
}
static class DummyTabFactory implements TabHost.TabContentFactory {
private final Context mContext;
public DummyTabFactory(Context context) {
mContext = context;
}
public View createTabContent(String tag) {
View v = new View(mContext);
v.setMinimumWidth(0);
v.setMinimumHeight(0);
return v;
}
}
public TabsAdapter(FragmentActivity activity, TabHost tabHost, ViewPager pager) {
super(activity.getSupportFragmentManager());
mContext = activity;
mTabHost = tabHost;
mViewPager = pager;
mTabHost.setOnTabChangedListener(this);
mViewPager.setAdapter(this);
mViewPager.setOnPageChangeListener(this);
}
public void addTab(TabHost.TabSpec tabSpec, Class<?> clss, Bundle args) {
tabSpec.setContent(new DummyTabFactory(mContext));
String tag = tabSpec.getTag();
TabInfo info = new TabInfo(tag, clss, args);
mTabs.add(info);
mTabHost.addTab(tabSpec);
notifyDataSetChanged();
}
#Override
public int getCount() {
return mTabs.size();
}
#Override
public Fragment getItem(int position) {
TabInfo info = mTabs.get(position);
return Fragment.instantiate(mContext, info.clss.getName(), info.args);
}
public void onTabChanged(String tabId) {
int position = mTabHost.getCurrentTab();
mViewPager.setCurrentItem(position);
}
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
public void onPageSelected(int position) {
// Unfortunately when TabHost changes the current tab, it kindly
// also takes care of putting focus on it when not in touch mode.
// The jerk.
// This hack tries to prevent this from pulling focus out of our
// ViewPager.
TabWidget widget = mTabHost.getTabWidget();
int oldFocusability = widget.getDescendantFocusability();
widget.setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS);
mTabHost.setCurrentTab(position);
widget.setDescendantFocusability(oldFocusability);
}
public void onPageScrollStateChanged(int state) {
}
}
Can anyone please help me in it?
You are implementing nested fragments.
Can you try to replace your activity.getSupportFragmentManager() with activity.getChildSupportFragmentManager().
I have a fragment activity with TabHost and ViewPager inside it.
There are two tabs for the activity: the List tab and the Map tab.
On the List tab I've got list of my data (some institutions) and on the Map tab (using Google Maps API) I am displaying that institutions on the map with markers.
When activity is opened default tab is List. Swiping from right to left, or selecting Map tab brings me to the Map with markers.
The problem is, when I'm selecting the List tab again I've got a black content in stead of ListView and it's items. However, when from the List tab I select the Map tab again, Map shows correctly.
Here is activity source:
public class Institutions extends FragmentActivity {
public static final int TAB_LIST = 0;
public static final int TAB_MAP = 1;
private TabHost mTabHost;
private ViewPager mViewPager;
private TabsAdapter mTabsAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.institutions);
mTabHost = (TabHost) findViewById(android.R.id.tabhost);
mTabHost.setup();
mViewPager = (ViewPager) findViewById(R.id.pager);
mViewPager.setOffscreenPageLimit(1);
mTabsAdapter = new TabsAdapter(this, mTabHost, mViewPager);
View v = createTab(TAB_LIST);
mTabsAdapter.addTab(mTabHost.newTabSpec("list").setIndicator(v),
InstitutionList.class, null);
v = createTab(TAB_MAP);
mTabsAdapter.addTab(mTabHost.newTabSpec("map").setIndicator(v),
InstitutionMap.class, null);
TextView activity_title = (TextView) findViewById(R.id.activity_title);
activity_title.setText(getIntent().getStringExtra(
Institution.INSTITUTION_TITLE));
}
private View createTab(int type) {
View v = getLayoutInflater().inflate(R.layout.tab, null);
TextView label = (TextView) v.findViewById(R.id.label);
ImageView icon = (ImageView) v.findViewById(R.id.icon);
icon.setVisibility(View.GONE);
icon.getLayoutParams().width = 1;
icon.getLayoutParams().height = 1;
switch (type) {
case TAB_LIST:
label.setText(getString(R.string.list_title));
break;
case TAB_MAP:
label.setText(getString(R.string.map_title));
break;
default:
break;
}
return v;
}
}
Here is the source for TabsAdapter:
public class TabsAdapter extends FragmentStatePagerAdapter implements
TabHost.OnTabChangeListener, ViewPager.OnPageChangeListener {
private final Context mContext;
private final TabHost mTabHost;
private final ViewPager mViewPager;
private final ArrayList<TabInfo> mTabs = new ArrayList<TabInfo>();
static final class TabInfo {
private final Class<? extends Fragment> clss;
private final Bundle args;
private Tab tab;
TabInfo(Class<? extends Fragment> _class, Bundle _args) {
clss = _class;
args = _args;
tab = null;
}
}
static class TabFactory implements TabHost.TabContentFactory {
private final Context mContext;
public TabFactory(Context context) {
mContext = context;
}
#Override
public View createTabContent(String tag) {
View v = new View(mContext);
v.setMinimumWidth(0);
v.setMinimumHeight(0);
return v;
}
}
public TabsAdapter(FragmentActivity activity, TabHost tabHost,
ViewPager pager) {
super(activity.getSupportFragmentManager());
mContext = activity;
mTabHost = tabHost;
mViewPager = pager;
mTabHost.setOnTabChangedListener(this);
mViewPager.setAdapter(this);
mViewPager.setOnPageChangeListener(this);
}
public void addTab(TabHost.TabSpec tabSpec, Class<? extends Fragment> clss,
Bundle args) {
tabSpec.setContent(new TabFactory(mContext));
TabInfo info = new TabInfo(clss, args);
mTabs.add(info);
mTabHost.addTab(tabSpec);
notifyDataSetChanged();
}
#Override
public int getItemPosition(Object object) {
return POSITION_NONE;
}
#Override
public int getCount() {
return mTabs.size();
}
#Override
public Fragment getItem(int position) {
TabInfo info = mTabs.get(position);
if (info.tab == null) {
info.tab = (Tab) Fragment.instantiate(mContext,
info.clss.getName(), info.args);
}
return info.tab;
}
#Override
public void onTabChanged(String tabId) {
int position = mTabHost.getCurrentTab();
mViewPager.setCurrentItem(position);
for (int i = 0; i < getCount(); i++) {
if (i == position)
continue;
Tab t = mTabs.get(i).tab;
if (t != null) {
t.onTabUnselected();
}
}
}
#Override
public void onPageScrolled(int position, float positionOffset,
int positionOffsetPixels) {
}
#Override
public void onPageSelected(int position) {
TabWidget widget = mTabHost.getTabWidget();
int oldFocusability = widget.getDescendantFocusability();
widget.setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS);
mTabHost.setCurrentTab(position);
widget.setDescendantFocusability(oldFocusability);
}
#Override
public void onPageScrollStateChanged(int state) {
}
}
I have an Activity which scrapes a webpage in a CustomLoader.
When loader finished I want to update the contents of 3 tabs with the data retrieved.
I'm using the sample code provided by android dev samples to implement the Viewpager/Tabs/Fragments on the activity.
When the fragment is created for the tab the onCreateView is correctly called, all the widgets on the view are correctly located and mapped to the variables.
However, when I attempt to find the fragment from the Activity and call a method on the fragment to update its contents the variables are null. Furthermore, calling getView also returns null - The instance of the fragment I'm retrieving from the TabsAdapter is not the correct instantiated instance ?
I've cut the code down to a single tab fragment, code in question is the call from onLoaderFinished to update the fragment.
All 3 tab fragments will be populated with data from a single loader, hence the loader being on the activity, not on the fragments. I just need a way to tell the fragments to paint their new data.
public class InfoBloodStocksActivity extends SherlockFragmentActivity
implements LoaderManager.LoaderCallbacks<BloodStocksLoaderResponse> {
TabHost mTabHost;
ViewPager mViewPager;
TabsAdapter mTabsAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.info_bloodstocks_tabpager);
mTabHost = (TabHost)findViewById(android.R.id.tabhost);
mTabHost.setup();
mViewPager = (ViewPager)findViewById(R.id.infoBloodStocksTabPager);
mViewPager.setOffscreenPageLimit(3);
mTabsAdapter = new TabsAdapter(this, mTabHost, mViewPager);
mTabsAdapter.addTab(mTabHost.newTabSpec("Daily stock").setIndicator("Daily stocks"),
InfoBloodStocksPageFragment.class, null);
if (savedInstanceState != null) {
mTabHost.setCurrentTabByTag(savedInstanceState.getString("tab"));
}
loadStockDetailsFromWebsite();
}
private void loadStockDetailsFromWebsite() {
// Prepare the loader. Either re-connect with an existing one,
// or start a new one.
getSupportLoaderManager().initLoader(0, null, this);
}
#Override
public Loader<BloodStocksLoaderResponse> onCreateLoader(int arg0, Bundle arg1) {
// This is called when a new Loader needs to be created. This
// sample only has one Loader with no arguments, so it is simple.
return new BloodStocksCustomLoader(this);
}
#Override
public void onLoadFinished(Loader<BloodStocksLoaderResponse> loader, BloodStocksLoaderResponse response) {
if (response.isNewStocksLoaded()) {
InfoBloodStocksPageFragment fragment = (InfoBloodStocksPageFragment) mTabsAdapter.getItem(0);
fragment.setNewImage(response.getDailyStocksImageURL());
}
}
#Override
public void onLoaderReset(Loader<BloodStocksLoaderResponse> arg0) {
// TODO Auto-generated method stub
}
#Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putString("tab", mTabHost.getCurrentTabTag());
}
/**
* This is a helper class that implements the management of tabs and all
* details of connecting a ViewPager with associated TabHost. It relies on a
* trick. Normally a tab host has a simple API for supplying a View or
* Intent that each tab will show. This is not sufficient for switching
* between pages. So instead we make the content part of the tab host
* 0dp high (it is not shown) and the TabsAdapter supplies its own dummy
* view to show as the tab content. It listens to changes in tabs, and takes
* care of switch to the correct paged in the ViewPager whenever the selected
* tab changes.
*/
public static class TabsAdapter extends FragmentPagerAdapter
implements TabHost.OnTabChangeListener, ViewPager.OnPageChangeListener {
private final Context mContext;
private final TabHost mTabHost;
private final ViewPager mViewPager;
private final ArrayList<TabInfo> mTabs = new ArrayList<TabInfo>();
static final class TabInfo {
private final String tag;
private final Class<?> clss;
private final Bundle args;
TabInfo(String _tag, Class<?> _class, Bundle _args) {
tag = _tag;
clss = _class;
args = _args;
}
}
static class DummyTabFactory implements TabHost.TabContentFactory {
private final Context mContext;
public DummyTabFactory(Context context) {
mContext = context;
}
#Override
public View createTabContent(String tag) {
View v = new View(mContext);
v.setMinimumWidth(0);
v.setMinimumHeight(0);
return v;
}
}
public TabsAdapter(FragmentActivity activity, TabHost tabHost, ViewPager pager) {
super(activity.getSupportFragmentManager());
mContext = activity;
mTabHost = tabHost;
mViewPager = pager;
mTabHost.setOnTabChangedListener(this);
mViewPager.setAdapter(this);
mViewPager.setOnPageChangeListener(this);
}
public void addTab(TabHost.TabSpec tabSpec, Class<?> clss, Bundle args) {
tabSpec.setContent(new DummyTabFactory(mContext));
String tag = tabSpec.getTag();
TabInfo info = new TabInfo(tag, clss, args);
mTabs.add(info);
mTabHost.addTab(tabSpec);
notifyDataSetChanged();
}
#Override
public int getCount() {
return mTabs.size();
}
#Override
public Fragment getItem(int position) {
TabInfo info = mTabs.get(position);
return Fragment.instantiate(mContext, info.clss.getName(), info.args);
}
#Override
public void onTabChanged(String tabId) {
int position = mTabHost.getCurrentTab();
mViewPager.setCurrentItem(position);
}
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
#Override
public void onPageSelected(int position) {
// Unfortunately when TabHost changes the current tab, it kindly
// also takes care of putting focus on it when not in touch mode.
// The jerk.
// This hack tries to prevent this from pulling focus out of our
// ViewPager.
TabWidget widget = mTabHost.getTabWidget();
int oldFocusability = widget.getDescendantFocusability();
widget.setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS);
mTabHost.setCurrentTab(position);
widget.setDescendantFocusability(oldFocusability);
}
#Override
public void onPageScrollStateChanged(int state) {
}
}
}
I'm calling setNewImage from the activity.
public class InfoBloodStocksPageFragment extends SherlockFragment {
private ImageView mImageView;
private ProgressBar mProgress;
private TextView mTitle;
private TextView mDescriptionText;
private String mImageURL;
private ImageLoader mImageLoader = ImageLoader.getInstance();
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.info_bloodstocks_page, container, false);
mImageView = (ImageView)view.findViewById(R.id.bloodStocksPageImage);
mProgress = (ProgressBar)view.findViewById(R.id.bloodStocksPageProgress);
mTitle = (TextView)view.findViewById(R.id.bloodStockPageTitle);
mDescriptionText = (TextView)view.findViewById(R.id.bloodStocksPageText);
mProgress.setVisibility(View.VISIBLE);
mDescriptionText.setVisibility(View.GONE);
return view;
}
public void setNewImage(String imageURL) {
// why is mImageView null here ?
// why does getView() return null here ?
View view = getView();
mImageView = (ImageView)view.findViewById(R.id.bloodStocksPageImage);
DisplayImageOptions displayImageOptions = new DisplayImageOptions.Builder()
.showImageForEmptyUri(R.drawable.loading_stock_figures)
.cacheOnDisc()
.imageScaleType(ImageScaleType.EXACT)
.build();
mImageLoader.displayImage(imageURL, mImageView, displayImageOptions, new ImageLoadingListener() {
#Override
public void onLoadingStarted() {
mProgress.setVisibility(View.VISIBLE);
}
#Override
public void onLoadingFailed(FailReason failReason) {
String message = null;
switch (failReason) {
case IO_ERROR:
message = "Input/Output error";
break;
case OUT_OF_MEMORY:
message = "Out Of Memory error";
break;
case UNKNOWN:
message = "Unknown error";
break;
}
mProgress.setVisibility(View.GONE);
mImageView.setImageResource(android.R.drawable.ic_delete);
}
#Override
public void onLoadingComplete() {
mProgress.setVisibility(View.GONE);
Animation anim = AnimationUtils.loadAnimation(getActivity(), R.anim.fade_in);
mImageView.setAnimation(anim);
anim.start();
}
#Override
public void onLoadingCancelled() {
// Do nothing
}
});
}
}
I've just started using http://square.github.com/otto/ for doing this. The documentation on the site should be enough to get you started with it.
I am trying to keep a view pager inside a fragment. And the View pager itself contains 3 other fragment. This is the Root fragment which contain the view pager
import android.support.v13.app.FragmentPagerAdapter;
import android.support.v13.app.FragmentStatePagerAdapter;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import com.android.browser1.UI.ComboViews;
public class MyFragment extends Fragment implements
TabHost.OnTabChangeListener, ViewPager.OnPageChangeListener, CombinedBookmarksCallbacks {
private TabHost mTabHost;
private ViewPager mViewPager;
public static final String EXTRA_COMBO_ARGS = "combo_args";
Bundle bundle;
Bundle extra;
public static final String EXTRA_INITIAL_VIEW = "initial_view";
public static BookmarkFragment bookmarkFragmentForPageA = null;
public static BookmarkFragment bookmarkFragmentForPageB = null;
Controller controller;
TabsAdapter mTabsAdapter;
FirstFragment first;
SecondFragment seconde;
ThirdFragment third;
public void setBundle(Bundle bundle) {
extra = bundle;// getActivity().getIntent().getExtras();
this.bundle = extra.getBundle(EXTRA_COMBO_ARGS);
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
mTabHost.setup();
mViewPager.setOffscreenPageLimit(2);
mTabsAdapter = new TabsAdapter(getActivity(), mTabHost, mViewPager);
new setAdapterTask().execute();
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.bookmark_view_pager, null);
mTabHost = (TabHost) view.findViewById(R.id.tabHost);
mViewPager = (ViewPager) view.findViewById(R.id.viewpager);
view.setBackgroundColor(Color.BLACK);
return view;
}
private class setAdapterTask extends AsyncTask<Void, Void, Void> {
protected Void doInBackground(Void... params) {
return null;
}
#Override
protected void onPostExecute(Void result) {
String bookmark = getResources().getString(R.string.tab_bookmarks);
String history = getResources().getString(R.string.tab_history);
String scrapmemo = getResources().getString(R.string.tab_snapshots);
mTabsAdapter.addTab(
mTabHost.newTabSpec(bookmark).setIndicator(bookmark), BrowserBookmarksPage.class, null);
mTabsAdapter.addTab(
mTabHost.newTabSpec(history).setIndicator(history), BrowserHistoryPage.class, null);
mTabsAdapter.addTab(
mTabHost.newTabSpec(scrapmemo).setIndicator(scrapmemo), BrowserSnapshotPage.class, null);
String svStr = extra.getString(EXTRA_INITIAL_VIEW, null);
ComboViews startingView = svStr != null ? ComboViews.valueOf(svStr)
: ComboViews.Bookmarks;
switch (startingView) {
case Bookmarks:
mTabHost.setCurrentTab(0);
mViewPager.setCurrentItem(0);
break;
case History:
mTabHost.setCurrentTab(1);
mViewPager.setCurrentItem(1);
break;
case ScrapMemo:
mTabHost.setCurrentTab(2);
mViewPager.setCurrentItem(2);
break;
}
}
}
public void onTabChanged(String tag) {
ComboViews startingView = tag != null ? ComboViews.valueOf(tag)
: ComboViews.Bookmarks;
switch (startingView) {
case First:
mTabHost.setCurrentTab(0);
break;
case Second:
mTabHost.setCurrentTab(1);
break;
case Third:
mTabHost.setCurrentTab(2);
break;
}
}
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
#Override
public void onPageSelected(int position) {
this.mTabHost.setCurrentTab(position);
}
#Override
public void onPageScrollStateChanged(int state) {
}
public class TabsAdapter extends FragmentStatePagerAdapter
implements TabHost.OnTabChangeListener, ViewPager.OnPageChangeListener {
private final Context mContext;
private final TabHost mTabHost;
private final ViewPager mViewPager;
private final ArrayList<TabInfo> mTabs = new ArrayList<TabInfo>();
final class TabInfo {
private final String tag;
private final Class clss;
private final Bundle args;
TabInfo(String _tag, Class _class, Bundle _args) {
tag = _tag;
clss = _class;
args = _args;
}
}
class DummyTabFactory implements TabHost.TabContentFactory {
private final Context mContext;
public DummyTabFactory(Context context) {
mContext = context;
}
#Override
public View createTabContent(String tag) {
View v = new View(mContext);
v.setMinimumWidth(0);
v.setMinimumHeight(0);
return v;
}
}
public TabsAdapter(Activity activity, TabHost tabHost, ViewPager pager) {
super(activity.getFragmentManager());
mContext = activity;
mTabHost = tabHost;
mViewPager = pager;
mTabHost.setOnTabChangedListener(this);
mViewPager.setAdapter(this);
mViewPager.setOnPageChangeListener(this);
mViewPager.setOffscreenPageLimit(3);
}
public void addTab(TabHost.TabSpec tabSpec, Class clss, Bundle args) {
tabSpec.setContent(new DummyTabFactory(mContext));
String tag = tabSpec.getTag();
TabInfo info = new TabInfo(tag, clss, args);
mTabs.add(info);
mTabHost.addTab(tabSpec);
notifyDataSetChanged();
getItem(0);
}
#Override
public int getCount() {
return mTabs.size();
}
#Override
public Fragment getItem(int position) {
Fragment fr = null;
TabInfo info = mTabs.get(position);
// Create a new fragment if necessary.
switch (position) {
case 0:
fr = new FirstFragment();
fr.setArguments(info.args);
break;
case 1:
fr = new SecondFragment ();
fr.setArguments(info.args);
break;
case 2:
fr = new ThirdFragment ();
fr.setArguments(info.args);
break;
default:
fr = new FirstFragment ();
fr.setArguments(info.args);
break;
}
return fr;
}
#Override
public int getItemPosition(Object object) {
if (object instanceof FirstFragment
|| object instanceof SecondFragment
|| object instanceof ThirdFragment )
return POSITION_NONE;
return POSITION_UNCHANGED;
}
#Override
public void onTabChanged(String tabId) {
// called when the user clicks on a tab.
int position = mTabHost.getCurrentTab();
mViewPager.setCurrentItem(position);
}
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
#Override
public void onPageSelected(int position) {
// Unfortunately when TabHost changes the current tab, it kindly
// also takes care of putting focus on it when not in touch mode.
// The jerk.
// This hack tries to prevent this from pulling focus out of our
// ViewPager.
TabWidget widget = mTabHost.getTabWidget();
int oldFocusability = widget.getDescendantFocusability();
widget.setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS);
mTabHost.setCurrentTab(position);
widget.setDescendantFocusability(oldFocusability);
}
#Override
public void onPageScrollStateChanged(int state) {
}
}
}
And when I attach this fragment in my activity for the first time we can see all the three fragment by swiping but after the back press we remove the fragment. After that again I attach the fragment in the same activity at run time but only first 2 fragments are visible and the content of 3rd one is empty.
I am trying to keep a view pager inside a fragment. And the View pager itself contains 3 other fragment.
Sorry, but fragments inside of other fragments is officially not supported, as indicated by Dianne Hackborn, a core Android team member.