Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

Android Build a Self-Destructing Message Android App Using Fragments for Tabs Modifying Fragments from the Template

InboxFragment

I have been going over the Modifying Fragments and have a problem that I cannot figure out. Located in SectionsPagerAdapter.java

Have followed the instructions and cannot find where I did something wrong.

In the SectionsPagerAdapter class I have the below method where return new gives me an error:

    @Override
    public Fragment getItem(int position) {
        // getItem is called to instantiate the fragment for the given page.
        // Return a PlaceholderFragment (defined as a static inner class
        // below).
        return new InboxFragment();
    }

// the InboxFragment class is listed below:

package com.danrock.ribbit;

import android.os.Bundle;
import android.support.v4.app.ListFragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

public class InboxFragment extends ListFragment {
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        View rootView = inflater.inflate(R.layout.fragment_inbox, container,
                false);
        return rootView;
    }
}

9 Answers

Ben Jakuben
STAFF
Ben Jakuben
Treehouse Teacher

The way Fragments are included in the project has changed since these videos were recorded, and it causes some headaches!

First things first, take a look at the Teacher's Notes on that video and see if changing your import statements fixes it. There are links there to other forum posts about this same issue, too.

If that doesn't work, please reply with the full code for your SectionsPagerAdapter class.

Below is my SectionsPagerAdapter section.

package com.danrock.ribbit;

import java.util.Locale;

import android.content.Context;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;


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

    protected Context mContext;

    public SectionsPagerAdapter(Context context, FragmentManager fm) {
        super(fm);
        mContext = context;
    }

    @Override
    public Fragment getItem(int position) {
        // getItem is called to instantiate the fragment for the given page.
        // Return a PlaceholderFragment (defined as a static inner class
        // below).
        return new InboxFragment();
    }

    @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 mContext.getString(R.string.title_section1).toUpperCase(l);
        case 1:
            return mContext.getString(R.string.title_section2).toUpperCase(l);
        }
        return null;
    }
}
Ben Jakuben
Ben Jakuben
Treehouse Teacher

It looks good! What is the exact error message you get on that return statement? Also, how are you initializing mSectionsPagerAdapter in your MainActivity file? It should look like this:

mSectionsPagerAdapter = new SectionsPagerAdapter(this, getSupportFragmentManager());

Ben,

Below is my MainActivity file:

The mSectionsPagerAdapter is exactly as you have it.

package com.danrock.ribbit;

import android.app.ActionBar;
import android.app.Activity;
import android.app.FragmentTransaction;
import android.content.Intent;
import android.os.Bundle;
import android.support.v13.app.FragmentPagerAdapter;
import android.support.v4.view.ViewPager;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;

import com.parse.ParseAnalytics;
import com.parse.ParseUser;

public class MainActivity extends Activity implements ActionBar.TabListener {

    public static final String TAG = MainActivity.class.getSimpleName();
    /**
     * The {@link android.support.v4.view.PagerAdapter} that will provide
     * fragments for each of the sections. We use a {@link 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.v13.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);

        ParseAnalytics.trackAppOpened(getIntent());

        ParseUser currentUser = ParseUser.getCurrentUser();
        if (currentUser == null) {
            navigateToLogin();
        }
        else {
            Log.i(TAG, currentUser.getUsername());
        }

        // Set up the action bar.
        final ActionBar actionBar = getActionBar();
        actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);

        // Create the adapter that will return a fragment for each of the three
        // primary sections of the activity.\
        mSectionsPagerAdapter = new SectionsPagerAdapter(this, getFragmentManager());

        // primary sections of the app.
        mSectionsPagerAdapter = new SectionsPagerAdapter(this, getSupportFragmentManager());

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

        // When swiping between different sections, select the corresponding
        // tab. We can also use ActionBar.Tab#select() to do this if we have
        // a reference to the Tab.
        mViewPager
                .setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
                    @Override
                    public void onPageSelected(int position) {
                        actionBar.setSelectedNavigationItem(position);
                    }
                });

        // For each of the sections in the app, add a tab to the action bar.
        for (int i = 0; i < mSectionsPagerAdapter.getCount(); i++) {
            // Create a tab with text corresponding to the page title defined by
            // the adapter. Also specify this Activity object, which implements
            // the TabListener interface, as the callback (listener) for when
            // this tab is selected.
            actionBar.addTab(actionBar.newTab()
                    .setText(mSectionsPagerAdapter.getPageTitle(i))
                    .setTabListener(this));
        }
    }

    private void navigateToLogin() {
        Intent intent = new Intent(this, LoginActivity.class);
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
        startActivity(intent);
    }

    @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;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int itemId = item.getItemId();
        if (itemId == R.id.action_logout) {
            ParseUser.logOut();
            navigateToLogin();
        }
        return super.onOptionsItemSelected(item);
    }

    @Override
    public void onTabSelected(ActionBar.Tab tab,
            FragmentTransaction fragmentTransaction) {
        // When the given tab is selected, switch to the corresponding page in
        // the ViewPager.
        mViewPager.setCurrentItem(tab.getPosition());
    }

    @Override
    public void onTabUnselected(ActionBar.Tab tab,
            FragmentTransaction fragmentTransaction) {
    }

    @Override
    public void onTabReselected(ActionBar.Tab tab,
            FragmentTransaction fragmentTransaction) {
    }
}
Ben Jakuben
Ben Jakuben
Treehouse Teacher

Okay, again looking good. And what's the exact error you get on the return new InboxFragment(); line?

I noticed that my imports did not copy from above.

Below is the top portion of the file.

package com.danrock.ribbit;

import android.app.ActionBar; import android.app.Activity; import android.app.FragmentTransaction; import android.content.Intent; import android.os.Bundle; import android.support.v13.app.FragmentPagerAdapter; import android.support.v4.view.ViewPager; import android.util.Log; import android.view.Menu; import android.view.MenuItem;

import com.parse.ParseAnalytics; import com.parse.ParseUser;

public class MainActivity extends Activity implements ActionBar.TabListener {

I no longer get that same error message, after changing the imports.

Now I get a message for

getFragmentManager "The constructor SectionsPagerAdapter(MainActivity, FragmentManager) is undefined.

and

getSupportFragmentManager The Method getSupportFragmentManager() is undefined for the type MainActivity.

    // Create the adapter that will return a fragment for each of the three
    // primary sections of the activity.\
    mSectionsPagerAdapter = new SectionsPagerAdapter(this, getFragmentManager());

    // primary sections of the app.
    mSectionsPagerAdapter = new SectionsPagerAdapter(this, getSupportFragmentManager());
Ben Jakuben
Ben Jakuben
Treehouse Teacher

Progress! I checked your MainActivity code. You need to change it from extending Activity to FragmentActivity. Here's what the new line should look like:

public class MainActivity extends FragmentActivity implements ActionBar.TabListener {

And the import you'll need:

import android.support.v4.app.FragmentActivity;

Thank you Ben,

That took care of one statement. The only one I have now is the one below

mSectionsPagerAdapter = new SectionsPagerAdapter(this, getFragmentManager());

The constructor SectionsPagerAdapter(MainActivity, FragmentManager) is undefined

Ben Jakuben
Ben Jakuben
Treehouse Teacher

Oh yeah, you need to go back to the version you had with getSupportFragmentManager().

So sorry about these silly Fragment issues. Things like this are why people do not like working with Fragments. I am starting to refresh all the courses using Android Studio, and it will make this part work much better.

Sorry Ben, I don't understand what you mean by you need to go back to the version you had with getSupportFragmentManager().

Also, should I go to your Android Studio course instead?

I was hoping to have something to show by Friday, but that looks out of the question now.

Ben Jakuben
Ben Jakuben
Treehouse Teacher

From your code above, change getFragmentManager() to getSupportFragmentManager() in this line:

// Create the adapter that will return a fragment for each of the three
// primary sections of the activity.\
mSectionsPagerAdapter = new SectionsPagerAdapter(this, getFragmentManager());

// primary sections of the app.
mSectionsPagerAdapter = new SectionsPagerAdapter(this, getSupportFragmentManager());

It works! Thank you Ben!

Now I can continue, and maybe one day be as smart as you!

Ben Jakuben
Ben Jakuben
Treehouse Teacher

Excellent! Glad you had the patience to stick it out. Hope the rest goes smoothly! And I only seem smart with this because I've had lots of practice!

HI there I am facing the same problem but with a twist;

I did all of the above things but my code has a little bit of difference than the once specified here. i.e. the import statements are different

import android.content.Intent;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.app.FragmentTransaction;
import android.support.v4.view.ViewPager;
import android.support.v7.app.ActionBar;
import android.support.v7.app.ActionBarActivity;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;

import com.parse.ParseUser;
import com.startaddis.walia.Helper.Helper;

the one import line that might different from the code above is the v7.app.ActionBarActivity. the problem is since we have now extended from FragmentActivity my Mainactiity is no more extending from ActionBarActivity. for that reason i get an error on this line

final ActionBar actionBar =    getSupportActionBar();

and can't even compile. it can't resolve getSupportActionBar(); and if i change it to getActionBar(); only i believe i won't get the backward compatibility and also will get an error with deprecated features like

actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);

For Reference purpose i have included my whole MainActivity.java below:

import android.content.Intent;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.app.FragmentTransaction;
import android.support.v4.view.ViewPager;
import android.support.v7.app.ActionBar;
import android.support.v7.app.ActionBarActivity;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;

import com.parse.ParseUser;
import com.startaddis.walia.Helper.Helper;


public class MainActivity extends FragmentActivity implements ActionBar.TabListener {

    /**
     * The {@link android.support.v4.view.PagerAdapter} that will provide
     * fragments for each of the sections. We use a
     * {@link 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;


    ParseUser currentUser;
    public final String TAG = MainActivity.class.getSimpleName();

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


        //get user cached on disk.
        currentUser = ParseUser.getCurrentUser();

        if(currentUser == null) {
            //redirect to login
            Intent intent = new Intent(this, LoginActivity.class);
            Helper.clearAndStartActivity(MainActivity.this, intent);
        }
        else
        {
            Log.i(TAG,currentUser.getUsername());
        }
        // Set up the action bar.
        //final ActionBar actionBar =  getSupportActionBar();
        final ActionBar actionBar =    getSupportActionBar();
        actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);


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

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

        // When swiping between different sections, select the corresponding
        // tab. We can also use ActionBar.Tab#select() to do this if we have
        // a reference to the Tab.
        mViewPager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
            @Override
            public void onPageSelected(int position) {
                actionBar.setSelectedNavigationItem(position);
            }
        });

        // For each of the sections in the app, add a tab to the action bar.
        for (int i = 0; i < mSectionsPagerAdapter.getCount(); i++) {
            // Create a tab with text corresponding to the page title defined by
            // the adapter. Also specify this Activity object, which implements
            // the TabListener interface, as the callback (listener) for when
            // this tab is selected.
            actionBar.addTab(
                    actionBar.newTab()
                            .setText(mSectionsPagerAdapter.getPageTitle(i))
                            .setTabListener(this));
        }
    }


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

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_logout) {
            ParseUser.logOut();
            Intent intent = new Intent(MainActivity.this,LoginActivity.class);
            Helper.clearAndStartActivity(MainActivity.this,intent);
        }

        return super.onOptionsItemSelected(item);
    }

    @Override
    public void onTabSelected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
        // When the given tab is selected, switch to the corresponding page in
        // the ViewPager.
        mViewPager.setCurrentItem(tab.getPosition());
    }

    @Override
    public void onTabUnselected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
    }

    @Override
    public void onTabReselected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
    }


}