How do I use FragmentPagerAdapter to have tabs with different content?
Asked Answered
C

4

19

I want to have different tabs, where you can swipe through like in the android market. Each tab should use one fragment and use one method for it.

This is my FragmentPagerAdapter class:

public class SectionsPagerAdapter extends FragmentPagerAdapter {

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

    @Override
    public Fragment getItem(int position) {
        Fragment fragment =null;
        switch (position) {
            case 0:
                fragment = new ConnectionFragment();
                break;
            case 1:
                fragment = new DataFragment();
                break;              
            case 2:
                fragment = new GraphFragment();
                break;          }
        return fragment;    
    }
    @Override
    public int getCount() {
        // Show 3 total pages.
        return 3;
    }
}

And I have three classes for each fragment type/tab:

public static class ConnectionFragment extends Fragment {
    public static final String ARG_SECTION_NUMBER = "section_number";
    public String stringConnectionStatus = "Offline";
    public String stringWiflyIp = "0.0.0.0";

    public ConnectionFragment() {}

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        View connectionView = inflater.inflate(R.layout.fragment_connection,
                container, false);
        TextView statusView = (TextView) connectionView.findViewById(R.id.status_label);
        statusView.setText("Connection status: " + stringConnectionStatus);
        TextView ipView = (TextView) connectionView.findViewById(R.id.ip_label);
        ipView.setText("WiFly IP: " + stringWiflyIp);
        /**TextView sectionBarView = (TextView) connectionView
                .findViewById(R.id.section_label);
        sectionBarView.setText("pups");"*/

        return connectionView;
    }
}

public static class DataFragment extends Fragment {

    public DataFragment() {}

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        View dataView = inflater.inflate(R.layout.fragment_data,
                container, false);
        TextView sectionBarView = (TextView) dataView
                .findViewById(R.id.section_label);
        sectionBarView.setText("pups2");
        return dataView;
    }
}

public static class GraphFragment extends Fragment {

    public GraphFragment() {
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        View rootView = inflater.inflate(R.layout.fragment_graph,
                container, false);
        TextView sectionBarView = (TextView) rootView
                .findViewById(R.id.section_label);
        sectionBarView.setText("pups3");
        return rootView;
    }
}

Each Fragment should be customizable, thats why I have three classes.

Nevertheless, the app crashes in the getItem method. Any ideas? Thank you!

Edit: The complete MainActivity.java:

import ...
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;
    public List<String> fragments = new Vector<String>();

    /**
     * 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); //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);
            fragments.add(ConnectionFragment.class.getName());
            fragments.add(DataFragment.class.getName());
            fragments.add(GraphFragment.class.getName());
            //fragmentsA = "fragments";

        }

        @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 =null;
            switch (position) {
                case 0:
                    fragment = new ConnectionFragment();
                    break;
                case 1:
                    fragment = new DataFragment();
                    break;              
                case 2:
                    fragment = new GraphFragment();
                    break;          }
            return fragment;*/
            return Fragment.instantiate(getBaseContext(), fragments.get(position));

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

        @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);
            case 2:
                return getString(R.string.title_section3).toUpperCase(l);
            }
            return null;
        }
    }


    /**
     * A dummy fragment representing a section of the app, but that simply
     * displays dummy text.
     */
    public static class ConnectionFragment extends Fragment {
        /**
         * The fragment argument representing the section number for this
         * fragment.
         */
        public static final String ARG_SECTION_NUMBER = "section_number";
        public String stringConnectionStatus = "Offline";
        public String stringWiflyIp = "0.0.0.0";

        public ConnectionFragment() {}

        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container,
                Bundle savedInstanceState) {
            View connectionView = inflater.inflate(R.layout.fragment_connection,container, false);
            TextView statusView = (TextView) connectionView.findViewById(R.id.status_label);
            statusView.setText("Connection status: " + stringConnectionStatus);
            TextView ipView = (TextView) connectionView.findViewById(R.id.ip_label);
            ipView.setText("WiFly IP: " + stringWiflyIp);
            /**TextView sectionBarView = (TextView) connectionView
                    .findViewById(R.id.section_label);
            sectionBarView.setText("pups");"*/

            return connectionView;
        }
    }
    public static class DataFragment extends Fragment {

        public DataFragment() {}

        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container,
                Bundle savedInstanceState) {
            View dataView = inflater.inflate(R.layout.fragment_data,
                    container, false);
            //TextView sectionBarView = (TextView) dataView.findViewById(R.id.section_label);
            //sectionBarView.setText("pups2");
            return dataView;
        }
    }
    public static class GraphFragment extends Fragment {

        public GraphFragment() {}

        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container,
                Bundle savedInstanceState) {
            View rootView = inflater.inflate(R.layout.fragment_graph,
                    container, false);
            //TextView sectionBarView = (TextView) rootView.findViewById(R.id.section_label);
            //sectionBarView.setText("pups3");
            return rootView;
        }
    }
}
Concupiscent answered 22/4, 2013 at 14:35 Comment(2)
Can you post the logcat error and exactly what line it errors out on?Header
see comment on the answer belowConcupiscent
M
18

Create the adapter:

class MyPagerAdapter extends FragmentPagerAdapter {
        public List<String> fragmentsA; 

        public MyPagerAdapter(FragmentManager fm) {
            super(fm);
            fragmentsA = fragments;
        }

        @Override
        public Fragment getItem(int position) {
            //return MyFragment.newInstance();
            return Fragment.instantiate(context, fragmentsA.get(position));

        }

        @Override
        public CharSequence getPageTitle(int position) {
            //return CONTENT[position % CONTENT.length].toUpperCase();
            return mEntries.get(position % CONTENT.length).toUpperCase();
        }

        @Override
        public int getCount() {
           // return CONTENT.length;
            return mEntries.size();
        }

        @Override
        public int getItemPosition(Object object) {
            return POSITION_NONE;
        }
    }

Each fragment belongs to different classes.

So you have to define a fragment list (These go to the main FragmentActivity) :

static MyPagerAdapter adapter;

and fill it with the fragments:

fragments.add(ConnectionFragment.class.getName());
fragments.add(DataFragment.class.getName());
fragments.add(Tab3.class.getName());
//..etc

Then you have to add the fragments to the adapter like this:

 pager = (ViewPager)findViewById(R.id.viewpager);
 adapter = new MyPagerAdapter(getSupportFragmentManager());
 pager.setAdapter(adapter);

The MyPagerAdaper will go through all the fragments contained by the fragments list, then it will instantiate each of them.

Microbe answered 22/4, 2013 at 14:43 Comment(18)
Thanks for the fast reply. I applied your proposals and this is what logcat gives me now:Concupiscent
04-22 18:15:32.964: E/AndroidRuntime(7540): Caused by: java.lang.NullPointerException 04-22 18:15:32.964: E/AndroidRuntime(7540): at com.example.wiflytemp.MainActivity$SectionsPagerAdapter.<init>(MainActivity.java:70) 04-22 18:15:32.964: E/AndroidRuntime(7540): at com.example.wiflytemp.MainActivity.onCreate(MainActivity.java:43) 04-22 18:15:32.964: E/AndroidRuntime(7540): at android.app.Activity.performCreate(Activity.java:5104)Concupiscent
04-22 18:15:32.964: E/AndroidRuntime(7540): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1080) 04-22 18:15:32.964: E/AndroidRuntime(7540): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2258)Concupiscent
which is the designated row?Microbe
protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mSectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager());//row 43 mViewPager = (ViewPager) findViewById(R.id.pager); //pager mViewPager.setAdapter(mSectionsPagerAdapter);Concupiscent
you should find the reason that causes the NullPointerException. The problem is in the 70th row in your MainActivity, please copy it hereMicrobe
public SectionsPagerAdapter(FragmentManager fm) { super(fm); mSectionsPagerAdapter.fragments.add(ConnectionFragment.class.getName()); mSectionsPagerAdapter.fragments.add(DataFragment.class.getName());//thats row 70 mSectionsPagerAdapter.fragments.add(GraphFragment.class.getName()); }Concupiscent
So I think the nullpointer is related to the fragments list. public static List<String> fragments = new Vector<String>(); Do you have this row?Microbe
But it would be easier if you copied your mainActivity into your question.Microbe
ow I think i found it. the fragments list is created in the SectionsPagerAdapter by this: public List<String> fragments; I think i need to create the object properly first right?Concupiscent
It should be declared in your mainActivity outside every method. Because in your adapter you will only use the copy of it.Microbe
Okay, the app starts without crashing. So far so good. But as soon as I swipe to the next screen it crashes. These are the errors and the corresponding lines: 04-22 20:11:11.925: E/AndroidRuntime(15224): at com.example.wiflytemp.MainActivity$GraphFragment.onCreateView(MainActivity.java:177) View rootView = inflater.inflate(R.layout.fragment_graph,container, false); 04-22 20:11:11.925: E/AndroidRuntime(15224): at android.support.v4.app.FragmentPagerAdapter.finishUpdate(FragmentPagerAdapter.java:141)Concupiscent
please upload your mainActivity into your question :)Microbe
What is the error? Nullpointer again? PLease only copy the name of the error. As I see there is a problem with R.layout.fragment_graphMicrobe
04-22 20:11:11.925: E/AndroidRuntime(15224): android.view.InflateException: Binary XML file line #2: Error inflating class nullConcupiscent
Please try it without the GraphFragment, so we will see if it works with 2 fragments.Microbe
Okay, it works fine without the Graph Fragment. Thank you so much for your time and help!Concupiscent
Hello Jani Bela, I did every things like you and it works very well but the getPageTitle() method. I want to set the title for tabs in there but it is not called... So plz help me out. Thank youPatrolman
L
12

In your FragmentPagerAdapter#getItem method, do not create object of the Fragments. You need to return the Fragment in the following way -

return Fragment.instantiate(context, ConnectionFragment.class.getName());

This means that the method will look like this -

public class SectionsPagerAdapter extends FragmentPagerAdapter {

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

  @Override
  public Fragment getItem(int position) {
    Fragment fragment =null;
    switch (position) {
        case 0:
            fragment = Fragment.instantiate(context, ConnectionFragment.class.getName());
            break;
        case 1:
            fragment = Fragment.instantiate(context, DataFragment.class.getName());
            break;              
        case 2:
            fragment = Fragment.instantiate(context, GraphFragment.class.getName());
            break;          }
    return fragment;    
  }

  @Override
  public int getCount() {
    // Show 3 total pages.
    return 3;
  }
}
Lazaro answered 22/4, 2013 at 20:28 Comment(4)
I dont have this variable "context". What does it do, and do I need to create this one?Concupiscent
private Context context; //global and in your onCreate -> this.context = this;Bedfellow
In your Activity, context is this.Lazaro
Let me explain . If you create the adapter in the same class then you can simply pass YourClassName.this or this. but when you create an adapter outside the class. You have to pass a reference to adapter which tell it this associates to which activity. Then you pass a Context. Otherwise just use this.Unawares
P
0

See this example:

 public static class MyPagerAdapter extends FragmentPagerAdapter {
    private static int NUM_ITEMS = 3;

    public MyPagerAdapter(FragmentManager fragmentManager) {
        super(fragmentManager);
    }

    // Returns total number of pages
    @Override
    public int getCount() {
        return NUM_ITEMS;
    }

    // Returns the fragment to display for that page
    @Override
    public Fragment getItem(int position) {
        switch (position) {
        case 0: // Fragment # 0 - This will show FirstFragment
            return FirstFragment.newInstance(0, "Page # 1");
        case 1: // Fragment # 0 - This will show FirstFragment different title
            return FirstFragment.newInstance(1, "Page # 2");
        case 2: // Fragment # 1 - This will show SecondFragment
            return SecondFragment.newInstance(2, "Page # 3");
        default:
            return null;
        }
    }

    // Returns the page title for the top indicator
    @Override
    public CharSequence getPageTitle(int position) {
        return "Page " + position;
    }        
}
Pyles answered 30/3, 2017 at 10:4 Comment(0)
E
0

ViewPager is deprecated, use ViewPager2 instead.

With the release of ViewPager2 1.0.0, the FragmentPagerAdapter and FragmentStatePagerAdapter classes for interacting with ViewPager have been deprecated.

ViewPager2 is an improved version of the ViewPager library that offers enhanced functionality and addresses common difficulties with using ViewPager.

  • Read this to implement slide between fragments using ViewPager2
  • Read this to create swipe views with tabs using ViewPager2
  • If your app already uses ViewPager, read this page to learn more about migrating to ViewPager2.
Eltonelucidate answered 12/3, 2020 at 6:16 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.