12

Can anyone point me to an example or show me how to create a simple Tabbed Dialog in Android where the contents of each tab are Fragments? All the examples/tutorials I have found are about Fragments and Tabs, but nothing specific to DialogFragments.

The documentation for FragmentTabHost shows how to create tabs within normal fragments using getChildFragmentManager(). I'm assuming this should also work when the fragment is a DialogFragment but when I try it I get:

java.lang.IllegalStateException: Fragment does not have a view at android.support.v4.app.Fragment$1.findViewById(Fragment.java:1425)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:901)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1088)
...

Here's my code for setting up the view (which is then passed to AlertDialog.setView()):

private void setupView(View v) {
    mTabHost = (FragmentTabHost) v.findViewById(android.R.id.tabhost);

   mTabHost.setup(getActivity(), getChildFragmentManager(), R.id.realtabcontent);

   mTabHost.addTab(mTabHost.newTabSpec("tab1").setIndicator("Tab1"),
            MyDialogFragment.class, null);
}
fllo
  • 11,595
  • 5
  • 39
  • 95
Paul Drummond
  • 5,843
  • 6
  • 27
  • 38

4 Answers4

12

Spent a lot of time to get it working, but no luck. The only solution I found is create dummy fragment tabhost and use viewpager with fragments instead of tabhost fragments

voters_dialog.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_height="match_parent"
        android:layout_width="match_parent"
        android:orientation="vertical"
        >

        <android.support.v4.app.FragmentTabHost
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:id="@+id/tabs"
                >
        </android.support.v4.app.FragmentTabHost>

        <android.support.v4.view.ViewPager
                android:id="@+id/pager"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:gravity="center"/>

</LinearLayout>

Dialog class, the trick is use onCreateView not onCreateDialog

public class VotersDialog extends DialogFragment {


    private FragmentTabHost mTabHost;
    private ViewPager viewPager;
    private VotersPagerAdapter adapter;


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

        getDialog().setTitle(getArguments().getString("title"));

        mTabHost = (FragmentTabHost) view.findViewById(R.id.tabs);

        mTabHost.setup(getActivity(), getChildFragmentManager());
        mTabHost.addTab(mTabHost.newTabSpec("tab1").setIndicator("Плюсов"), Fragment.class, null);
        mTabHost.addTab(mTabHost.newTabSpec("tab2").setIndicator("Минусов"), Fragment.class, null);


        adapter = new VotersPagerAdapter(getChildFragmentManager(), getArguments());
        adapter.setTitles(new String[]{"Плюсов", "Минусов"});

        viewPager = (ViewPager)view.findViewById(R.id.pager);
        viewPager.setAdapter(adapter);

        viewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
            @Override
            public void onPageScrolled(int i, float v, int i2) {
            }

            @Override
            public void onPageSelected(int i) {
                mTabHost.setCurrentTab(i);
            }

            @Override
            public void onPageScrollStateChanged(int i) {

            }
        });

        mTabHost.setOnTabChangedListener(new TabHost.OnTabChangeListener() {
            @Override
            public void onTabChanged(String s) {
                int i = mTabHost.getCurrentTab();
                viewPager.setCurrentItem(i);
            }
        });

        return view;
    }


    public class VotersPagerAdapter extends FragmentPagerAdapter {

        Bundle bundle;
        String [] titles;

        public VotersPagerAdapter(FragmentManager fm) {
            super(fm);
        }

        public VotersPagerAdapter(FragmentManager fm, Bundle bundle) {
            super(fm);
            this.bundle = bundle;
        }

        @Override
        public Fragment getItem(int num) {
            Fragment fragment = new VotersListFragment();
            Bundle args = new Bundle();
            args.putSerializable("voters",bundle.getSerializable( num == 0 ? "pros" : "cons"));
            fragment.setArguments(args);
            return fragment;
        }

        @Override
        public int getCount() {
            return 2;
        }

        @Override
        public CharSequence getPageTitle(int position) {
            return titles[position];
        }

        public void setTitles(String[] titles) {
            this.titles = titles;
        }
    }

    public static class VotersListFragment extends ListFragment {

        List<String> voters;

        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
            View view = inflater.inflate(R.layout.list_fragment, container, false);
            return view;
        }

        @Override
        public void onActivityCreated(Bundle savedInstanceState) {

            super.onActivityCreated(savedInstanceState);
            voters = (ArrayList) getArguments().getSerializable("voters");

            ArrayAdapter<String> adapter = new ArrayAdapter<String>(getActivity(), android.R.layout.simple_list_item_1, voters);
            setListAdapter(adapter);

            getListView().setOnItemClickListener(new AdapterView.OnItemClickListener() {
                @Override
                public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
                    Intent intent = new Intent(getActivity(), ProfileActivity_.class);
                    String login = voters.get(i);
                    intent.putExtra("login", Utils.encodeString(login.substring(0, login.indexOf("(")).trim()));
                    startActivity(intent);
                }
            });

        }

    }

}

Here is result, now you can press tabs or swipe fragments

enter image description here

Georgy Gobozov
  • 13,239
  • 8
  • 67
  • 75
  • This can really help my app, thank you for sharing. Would it be possible to post the underlying views? ie. voters_dialog.xml, Is there source code on github or related? – Sauron Feb 16 '15 at 00:18
  • @Sauron, xml file above exact is voters_dialog.xml, I just putted wrong name, fixed it now. – Georgy Gobozov Feb 16 '15 at 00:22
  • Thank you. I am having trouble getting the correct libraries so that the dialog does appear. At present I am calling: `FragmentManager manager = getSupportFragmentManager(); VotersDialog inviteFriend = new VotersDialog(); inviteFriend.show(manager,"ok");` But having no luck in getting it to work – Sauron Feb 16 '15 at 00:26
2

I was looking for the same solution but nothing worked out for me so I built my own Android tabbed dialog containing fragments. might be it may help someone.

you can checkout the complete source code from here

Min2
  • 9,561
  • 1
  • 17
  • 22
1

You should use a DialogFragment, TabLayout and ViewPager. For instance, your dialog fragment's view may look like this:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <android.support.design.widget.TabLayout
        android:id="@+id/tabLayout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

    <android.support.v4.view.ViewPager
        android:id="@+id/masterViewPager"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
</LinearLayout>

Build your adapter and make sure you override the getPageTitleMethod, e.g:

public class CustomAdapter extends FragmentPagerAdapter {  
   List<Fragment> mFragmentCollection = new ArrayList<>();  
   List<String> mTitleCollection = new ArrayList<>();  
   public CustomAdapter(FragmentManager fm) {  
     super(fm);  
   }  
   public void addFragment(String title, Fragment fragment)  
   {  
     mTitleCollection.add(title);  
     mFragmentCollection.add(fragment);  
   }  
   //Needed for  
   @Override  
   public CharSequence getPageTitle(int position) {  
     return mTitleCollection.get(position);  
   }  
   @Override  
   public Fragment getItem(int position) {  
     return mFragmentCollection.get(position);  
   }  
   @Override  
   public int getCount() {  
     return mFragmentCollection.size();  
   }  
 }

In the OnCreateView of your dialog, you should setup your viewpager with the tabLayout:

 public View onCreateView(LayoutInflater inflater,  ViewGroup container,  Bundle savedInstanceState) {  
     View rootview = inflater.inflate(R.layout.dialog_sample,container,false);  
     tabLayout = (TabLayout) rootview.findViewById(R.id.tabLayout);  
     viewPager = (ViewPager) rootview.findViewById(R.id.masterViewPager);  
     CustomAdapter adapter = new CustomAdapter(getChildFragmentManager());  
     adapter.addFragment("Boy",CustomFragment.createInstance("John"));  
     adapter.addFragment("Girl",CustomFragment.createInstance("Stacy"));  
     adapter.addFragment("Robot",CustomFragment.createInstance("Aeon"));  
     viewPager.setAdapter(adapter);  
     tabLayout.setupWithViewPager(viewPager);  
     return rootview;  
   } 

I have a blog post written on it here: here.

Betweenmatt
  • 339
  • 2
  • 15
kunmi
  • 672
  • 7
  • 6
0

Try using DialogFragment instead and on your dialogfragment layout include a LinearLayout for fragmentTransaction.

FragmentTransaction t = getSupportFragmentManager().beginTransaction();  
String Tag = fragment.getClass().getSimpleName(); 
t.replace(R.id.llTabFragmentContainer, fragment, Tag); 
t.commit(); 

fragment is your tab fragment. cheeers

ralphgabb
  • 9,100
  • 2
  • 41
  • 48