Search code examples
javaandroidandroid-listviewandroid-listfragment

How to use ListFragment in Android Swipe Tabs?


I have used this code before for a swipe tab view with two layouts and it works fine.

public class MainActivity extends FragmentActivity {
/**
 * The {@link android.support.v4.view.PagerAdapter} that will provide
 * fragments for each of the sections. We use a
 * {@link android.support.v4.app.FragmentPagerAdapter} derivative, which
 * will keep every loaded fragment in memory. If this becomes too memory
 * intensive, it may be best to switch to a
 * {@link android.support.v4.app.FragmentStatePagerAdapter}.
 */
SectionsPagerAdapter mSectionsPagerAdapter;

/**
 * The {@link ViewPager} that will host the section contents.
 */
ViewPager mViewPager;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    // Create the adapter that will return a fragment for each of the three
    // primary sections of the app.
    mSectionsPagerAdapter = new SectionsPagerAdapter(
            getSupportFragmentManager());

    // Set up the ViewPager with the sections adapter.
    mViewPager = (ViewPager) findViewById(R.id.pager);
    mViewPager.setAdapter(mSectionsPagerAdapter);




}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.main, menu);
    return true;
}

/**
 * A {@link FragmentPagerAdapter} that returns a fragment corresponding to
 * one of the sections/tabs/pages.
 */
public class SectionsPagerAdapter extends FragmentPagerAdapter {

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

    @Override
    public Fragment getItem(int position) {
        // getItem is called to instantiate the fragment for the given page.
        // Return a DummySectionFragment (defined as a static inner class
        // below) with the page number as its lone argument.
        Fragment fragment = new DummySectionFragment();
        Bundle args = new Bundle();
        args.putInt(DummySectionFragment.ARG_OBJECT, position);
        fragment.setArguments(args);
        return fragment;
    }

    @Override
    public int getCount() {
        // Show 2 total pages.
        return 2;
    }

    @Override
    public CharSequence getPageTitle(int position) {
        Locale l = Locale.getDefault();
        switch (position) {
        case 0:
            return getString(R.string.title_section1).toUpperCase(l);
        case 1:
            return getString(R.string.title_section2).toUpperCase(l);
        }
        return null;
    }
}

/**
 * A dummy fragment representing a section of the app, but that simply
 * displays dummy text.
 */
public static class DummySectionFragment extends Fragment {
    /**
     * The fragment argument representing the section number for this
     * fragment.
     */
    public static final String ARG_SECTION_NUMBER = "section_number";
    public static final String ARG_OBJECT = "object";
    public DummySectionFragment() {
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        Bundle args = getArguments();
        int position = args.getInt(ARG_OBJECT);

        int tabLayout = 0;
        switch (position) {
        case 0:
        tabLayout = R.layout.tab_new;
        break;
        case 1:
        tabLayout = R.layout.tab_summary;
        break;

        }

        View rootView = inflater.inflate(tabLayout, container, false);

        return rootView;
    }
}
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {

    case R.id.action_settings:
        Intent i = new Intent(this, SettingsActivity.class);
        startActivity(i);
    }

    return true;
}

}

For that, I simply created 2 xml files and initialized them when the tabs are positioned correctly; however, now I want to have 2 tabs but the second one has to be a list. I'm not sure how to do that. I tried extending listFragment, but it crashed with resource not found. I've been stuck for a long time now, someone please help? I googled a lot and looked at all the examples but none of them show me how to make a list within a tab and how to call that.

Here's what I have right now MainActivity

public class MainActivity extends FragmentActivity {
SimpleListFragment x = new SimpleListFragment();
/**
 * The {@link android.support.v4.view.PagerAdapter} that will provide
 * fragments for each of the sections. We use a
 * {@link android.support.v4.app.FragmentPagerAdapter} derivative, which
 * will keep every loaded fragment in memory. If this becomes too memory
 * intensive, it may be best to switch to a
 * {@link android.support.v4.app.FragmentStatePagerAdapter}.
 */
SectionsPagerAdapter mSectionsPagerAdapter;

/**
 * The {@link ViewPager} that will host the section contents.
 */
ViewPager mViewPager;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    // Create the adapter that will return a fragment for each of the three
    // primary sections of the app.
    mSectionsPagerAdapter = new SectionsPagerAdapter(
            getSupportFragmentManager());

    // Set up the ViewPager with the sections adapter.
    mViewPager = (ViewPager) findViewById(R.id.pager);
    mViewPager.setAdapter(mSectionsPagerAdapter);

}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.main, menu);
    return true;
}

/**
 * A {@link FragmentPagerAdapter} that returns a fragment corresponding to
 * one of the sections/tabs/pages.
 */
public class SectionsPagerAdapter extends FragmentPagerAdapter {

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

    @Override
    public Fragment getItem(int position) {
        // getItem is called to instantiate the fragment for the given page.
        // Return a DummySectionFragment (defined as a static inner class
        // below) with the page number as its lone argument.
        Fragment fragment = new DummySectionFragment();
        Bundle args = new Bundle();
        args.putInt(DummySectionFragment.ARG_OBJECT, position + 1);
        fragment.setArguments(args);
        return fragment;
    }

    @Override
    public int getCount() {
        // Show 3 total pages.
        return 2;
    }

    @Override
    public CharSequence getPageTitle(int position) {
        Locale l = Locale.getDefault();
        switch (position) {
        case 0:
            return getString(R.string.title_section1).toUpperCase(l);
        case 1:
            return getString(R.string.title_section2).toUpperCase(l);
        }
        return null;
    }
}

/**
 * A dummy fragment representing a section of the app, but that simply
 * displays dummy text.
 */
public static class DummySectionFragment extends Fragment {
    /**
     * The fragment argument representing the section number for this
     * fragment.
     */
    public static final String ARG_SECTION_NUMBER = "section_number";
    public static final String ARG_OBJECT = "object";
    public DummySectionFragment() {
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        Bundle args = getArguments();
        int position = args.getInt(ARG_OBJECT);

        int tabLayout = 0;
        switch (position) {
        case 0:
        tabLayout = R.layout.tab_home;
        break;
        case 1:
            SimpleListFragment simpleListFragment = new SimpleListFragment();

        break;

        }

        View rootView = inflater.inflate(tabLayout, container, false);

        return rootView;
    }
}

}


Solution

  • ATM you are creating your ListFragment in the DummySectionFragment. Thats not right.

    Here is one way of doing it. Not the best but one thats good to understand.

    Create the fragments in the main activity and pass them to the adapter. The DummyListFragment is a new class derived from ListFragment. Important here is that the XML layout that it uses contains a ListView that has the id @android:id/list. (so the fragment is able to understand which listview it has to / can use.

    public class MainActivity extends FragmentActivity {
    
    SectionsPagerAdapter mSectionsPagerAdapter;
    
    ViewPager mViewPager;
    
    List<Fragment> mFragments;
    
    
    @Override protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    
     mFragments = new ArrayList<Fragment>();
     mFragments.add(new DummySectionFragment();
     mFragments.add(new DummyListFragment();
    
      mSectionsPagerAdapter = new SectionsPagerAdapter(
            getSupportFragmentManager(), mFragments);
    

    ...

    public class SectionsPagerAdapter extends FragmentPagerAdapter {
    
        List<Fragment> fragmentList;
    
        public SectionsPagerAdapter(FragmentManager fm, List<Fragment> fragments) {
            super(fm);
            fragmentList = fragments;
        }
    
    @Override
    public int getCount() {
        return fragmentList.size();
    }
    
        @Override
        public Fragment getItem(int position) {
            Fragment fragment = fragmentList.get(position);        
            return fragment;
        }
    

    . .

    public static class DummyListFragment extends ListFragment {
    
    public DummyListFragment() {
    }
    
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        return inflater.inflate(R.layout.my_list_fragment, container, false);
    }