0

I got a ViewPager inside a TabHost with this adapter:

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {
    View v = inflater.inflate(R.layout.fragment_home, container, false);


    mTabHost = (TabHost) v.findViewById(android.R.id.tabhost);
    mTabHost.setup();

    mViewPager = (ViewPager) v.findViewById(R.id.pager_home);
    mTabsAdapter = new TabsAdapter(getActivity(), mTabHost, mViewPager);

    // Here we load the content for each tab. 
    mTabsAdapter.addTab(mTabHost.newTabSpec("one").setIndicator("Recently Viewed"), PageOne.class, null);
    mTabsAdapter.addTab(mTabHost.newTabSpec("two").setIndicator("Offers"), PageTwo.class, null);
    //mTabsAdapter.addTab(mTabHost.newTabSpec("two").setIndicator("Experiences"), ExperiencesTab.class, null);

    return v;
}

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)
    {
    }
}

PageOne is a fragment which contains a ListView. I want to click on a list item and then change the fragment into a new fragment and pass it information on where I clicked so the fragment will be opened with the data of which item list exactly have I pushed.

for now I'm stuck at just switching the fragments (even before also sending the information about the clicked list item). I've tried this:

myList.setOnItemClickListener(new OnItemClickListener()
    {

        @Override
        public void onItemClick(AdapterView<?> parent, View view, int position, long id)
        {
            FragmentManager fragmentManager = getActivity().getSupportFragmentManager();
            FragmentTransaction ft = fragmentManager.beginTransaction();
            Fragment f = new SingleConversationFragment();
            ft.replace(R.id.pager_home, f);
            ft.addToBackStack(null);
            ft.commit();

        }

    });

but then the tab remains empty and nothing is shown inside it. As you can see, I also need the new fragment to be at the back stack so when I press back, the previous fragment will be loaded again.

CodeMonkey
  • 11,196
  • 30
  • 112
  • 203
  • u can use mTabHost .setCurrentTab(1); – Ravi Sharma May 06 '15 at 12:57
  • The prolem is not when showing the initial fragment in the tab. I can see the fragment with the list view. The problem is how to switch a fragment INSIDE THE SAME TAB after clicking a list item. – CodeMonkey May 06 '15 at 13:00
  • The ViewPager should be responsible for the lifecycle of the fragments,I would change the `getItem(int position)` function to take into account a global variable you set on the onclick function to either create the fragment as you do now, or create the new fragment you want, and then refresh the adapter. – Evripidis Drakos May 06 '15 at 13:02
  • @EvripidisDrakos I need the fragment to be added to the back stack so when pressing the back button, the previous fragment will be loaded. Your solution doesn't sound like it's taking care of it. – CodeMonkey May 06 '15 at 13:08
  • then just override the back button to update that global var again and call notifyDataChanged on the adpater again (with its getItemPosition returning POSITION_NONE for it to work). That's what i would try anyway. If you dont want to go that way, you could try using `getChildFragmentManager()` instead of `getSupportFragmentManager()` – Evripidis Drakos May 06 '15 at 13:15
  • @EvripidisDrakos it sounds like a solution, but I'm not sure about it.. manually managing the order of the fragments which is also controled by the back buton instead of letting the back stack itself handle it? – CodeMonkey May 06 '15 at 13:17
  • What you want to achieve is counter intuitive to the android way anyway. To preserve the "proper" way you should just create a new activity on click. – Evripidis Drakos May 06 '15 at 13:27
  • If you could collect everything you said and add it as an answer with a code example and it'll work then I'll accept it. – CodeMonkey May 06 '15 at 13:30

1 Answers1

0
widget.getChildAt(0).setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        tHost.setCurrentTab(0);

        ((ViewPager) mViewPager).setCurrentItem(0);

        /// perform fragment transaction here
    }
});
Ziem
  • 6,579
  • 8
  • 53
  • 86
Ravi Sharma
  • 753
  • 1
  • 7
  • 13