0

I am trying out Fragments in android for the first time, I am using a FragmentPagerAdapter for a finite number of fragments, in this case 3. The only problem is that when I swipe, it goes to the second and third page, but shows the layout for the first fragment everytime, instead of a different one.

MainActivity.java:

package com.example.swipetabtest;

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.view.ViewPager;
import android.support.v4.view.ViewPager.OnPageChangeListener;
import android.widget.Toast;

public class MainActivity extends FragmentActivity {
    FragmentPagerAdapter adapterViewPager;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ViewPager vpPager = (ViewPager) findViewById(R.id.vpPager);
        adapterViewPager = new MyPagerAdapter(getSupportFragmentManager());
        vpPager.setAdapter(adapterViewPager);
    }

    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:
                return FirstFragment.newInstance(0, "Page # 1");
            case 1:
                return SecondFragment.newInstance(1, "Page # 2");
            case 2:
                return ThirdFragment.newInstance(2, "Page # 3");
            default:
                return null;
            }
        }

    }

}

FirstFragment.java

package com.practice.swipetabtest;

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

public class FirstFragment extends Fragment {
    // Store instance variables
    private String title;
    private int page;

    // newInstance constructor for creating fragment with arguments
    public static FirstFragment newInstance(int page, String title) {
        FirstFragment fragmentFirst = new FirstFragment();
        Bundle args = new Bundle();
        args.putInt("someInt", page);
        args.putString("someTitle", title);
        fragmentFirst.setArguments(args);
        return fragmentFirst;
    }

    // Store instance variables based on arguments passed
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        page = getArguments().getInt("someInt", 0);
        title = getArguments().getString("someTitle");
    }

    // Inflate the view for the fragment based on layout XML
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_first, container, false);
        return view;
    }
}

SecondFragment.java

package com.practice.swipetabtest;

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

public class SecondFragment extends Fragment {
    // Store instance variables
    private String title;
    private int page;

    // newInstance constructor for creating fragment with arguments
    public static FirstFragment newInstance(int page, String title) {
        FirstFragment fragmentFirst = new FirstFragment();
        Bundle args = new Bundle();
        args.putInt("someInt", page);
        args.putString("someTitle", title);
        fragmentFirst.setArguments(args);
        return fragmentFirst;
    }

    // Store instance variables based on arguments passed
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        page = getArguments().getInt("someInt", 1);
        title = getArguments().getString("someTitle");
    }

    // Inflate the view for the fragment based on layout XML
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_second, container, false);
        return view;
    }
}

ThirdFragment.java

package com.practice.swipetabtest;

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

public class ThirdFragment extends Fragment {
    // Store instance variables
    private String title;
    private int page;

    // newInstance constructor for creating fragment with arguments
    public static FirstFragment newInstance(int page, String title) {
        FirstFragment fragmentFirst = new FirstFragment();
        Bundle args = new Bundle();
        args.putInt("someInt", page);
        args.putString("someTitle", title);
        fragmentFirst.setArguments(args);
        return fragmentFirst;
    }

    // Store instance variables based on arguments passed
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        page = getArguments().getInt("someInt", 2);
        title = getArguments().getString("someTitle");
    }

    // Inflate the view for the fragment based on layout XML
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_third, container, false);
        return view;
    }
}

activity_main.xml:

<?xml version="1.0" encoding="utf-8"?>
<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.v4.view.ViewPager
        android:id="@+id/vpPager"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
    </android.support.v4.view.ViewPager>
</LinearLayout>

fragment_first.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <TextView 
        android:text="this is the first fragment"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>
</LinearLayout>

fragment_second.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <TextView
        android:text="this is the second fragment"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
</LinearLayout>

fragment_third.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <TextView
        android:text="hey look a third fragment"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
</LinearLayout>

I tried checking for obvious things like whether the right layout was being inflated per fragment and the switch statement casing to the right fragment, but they look ok too me...

But it keeps showing the layout for the first fragment.

user2405469
  • 1,953
  • 2
  • 22
  • 43

2 Answers2

3

The problem is, if you take a look into your FirstFragment, SecondFragment and ThirdFragment classes instantiateFragment methods, you are actually creating a new instance of FirstFragment in all three of them.

You are calling:

        FirstFragment fragmentFirst = new FirstFragment();

In all three of your classes, where you should be calling:

        SecondFragment fragmentSecond = new SecondFragment();

or

        ThirdFragment fragmentThird = new ThirdFragment();

depending on which class you are in.

Matej
  • 1,727
  • 2
  • 14
  • 22
  • I knew it was something obvious...copying and pasting from FirstFragment.java and not renaming to return the right types...THANK YOU this has worked ::) – user2405469 Feb 16 '14 at 12:04
  • @user2405469 You're welcome! Copy & Waste is the more appropriate description. I just never do copy/pasting code or XML anymore precisely because of some bad experiences when I lost several hours trying to fix something only for it to turn out being a simple copy/paste issue. – Matej Feb 16 '14 at 12:08
  • @Matej... you are right, going to take this advice early in my coding experiences and get out of the habit :) – user2405469 Feb 16 '14 at 12:09
  • Also, a suggestion. If your First, Second and Third fragments layouts and logic are really basically identical except for changing the text inside the TextViews, you really only need one class and one layout. Call it PageFragment and then pass the text in the arguments bundle like you are doing now, retrieve them in onCreate, and set them to the TextView in onCreateView. You'll save two class files and two layout files. Possibly more if your want to add more pages in the future. – Matej Feb 16 '14 at 12:13
  • That is a good call...what if I was using two views where view b has the same and some more buttons on top that view a has and they both manipulate a certain textview? I guess it would be same as you say above right? – user2405469 Feb 16 '14 at 12:28
  • It would be the same if the visibility of these buttons just depends on the position of your Fragment inside your ViewPager. You could either have two separate XMLs and inflate a different one in onCreateView, depending on the position of the fragment, or you can have a single one, where the buttons have their visibility set to "gone" by default, but you can set it to "visible" in the fragments where you need them. – Matej Feb 16 '14 at 12:36
  • Yeah, I was thinking of setting the deafult to gone, time to play around :) – user2405469 Feb 16 '14 at 13:44
0
@Override
        public Fragment getItem(int position) {
            switch (position) 
           {
              Fragment frag=null;
        if(position==0)
            frag=new FirstFragment();
        if(position==1)
            frag=new SecondFragment();
        if(position==2)
            frag=new ThirdFragment();

        return frag;
            }
A.R.
  • 2,631
  • 1
  • 19
  • 22
  • @DoctororDrive ^ is right...how would that work since we are returning something hence breaking out anyway...?? – user2405469 Feb 16 '14 at 12:02