Replace fragment in fragment itself in TabActivity

369 views Asked by At

I am sorry on the duplicate question but I didn't get answer for my problem. I create app with TabActivity and also trying to replace one fragment from fragment itself, I read in https://developer.android.com/training/basics/fragments/fragment-ui.html how to do it and i created interface in my fragment that i want to be replace with another, I implement the interface in my MainActivity and still when running my app it show me container itself.

here is my code:

Main Activity:

public class MainActivity extends FragmentActivity implements New2.OnReplaceFragment {
   private SectionsPagerAdapter mSectionsPagerAdapter;
   private ViewPager mViewPager;
   public static MainActivity instance = null;

   public static MainActivity getInstance(){
       return instance;
   }

   @Override
   protected void onCreate(Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);
       setContentView(R.layout.activity_main);
       mSectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager());
       mViewPager = (ViewPager) findViewById(R.id.frame_container);
       mViewPager.setAdapter(mSectionsPagerAdapter);
       TabLayout tabLayout = (TabLayout) findViewById(R.id.tabs);
       tabLayout.setupWithViewPager(mViewPager);
        tabLayout.getTabAt(0).setIcon(R.drawable.icon_info);
        tabLayout.getTabAt(1).setIcon(R.drawable.icon_heart_rate_sensor_jpg);
        tabLayout.getTabAt(2).setIcon(R.drawable.icon_graph_jpg);
        instance = this;
    }
    @Override
    public void onReplaceFragment(Class fragmentClass) {
        Fragment fragment = null;
        try {
            fragment = (Fragment) fragmentClass.newInstance();
        } catch (Exception e) {
            e.printStackTrace();
        }
        // Insert the fragment by replacing any existing fragment
        FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
        transaction.replace(R.id.frame_container,fragment);

        // Replace whatever is in the fragment_container view with this fragment,
        // and add the transaction to the back stack so the user can navigate back


        transaction.addToBackStack(null);

        // Commit the transaction
        transaction.commit();
    }

    public static class PlaceholderFragment extends Fragment {
        /**
         * The fragment argument representing the section number for this
         * fragment.
         */
        private static final String ARG_SECTION_NUMBER = "section_number";

        public PlaceholderFragment() {
        }
        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container,
                                 Bundle savedInstanceState) {
            View rootView = inflater.inflate(R.layout.fragment_main, container, false);
            TextView textView = (TextView) rootView.findViewById(R.id.section_label);
            textView.setText(getString(R.string.section_format, getArguments().getInt(ARG_SECTION_NUMBER)));
            return rootView;
        }
    }

    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 PlaceholderFragment (defined as a static inner class below).
            switch (position) {
                case 0:
                  //  New1 tab1 = new New1();
                    return New1.newInstance();
                case 1:
                    return New2.newInstance();
                case 2:
                    return New3.newInstance();
                default:
                    return null;
            }
        }
        @Override
        public int getCount() {
            // Show 3 total pages.
            return 3;
        }

        @Override
        public CharSequence getPageTitle(int position) {
            switch (position) {
                case 0:
                    return "SECTION 1";
                case 1:
                    return "SECTION 2";
                case 2:
                    return "SECTION 3";
            }
            return null;
        }
    }
}

my fragment that I want to replace

Fragment:

public class New2 extends Fragment {
    TextView name;
    Button change;
    ImageView image1;
    Animation anime;
    private OnReplaceFragment dataPasser;

    public static New2 newInstance(){
        New2 fragment = new New2();
        return fragment;
    }
    public New2(){

    }
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
         View rootView = inflater.inflate(R.layout.fragment_new2, container, false);
        name = (TextView) rootView.findViewById(R.id.nameTt);
        change = (Button) rootView.findViewById(R.id.changeBtn);
        image1 = (ImageView) rootView.findViewById(R.id.image1);
        anime = AnimationUtils.loadAnimation(getActivity().getApplicationContext(),R.anim.zoom);
        change.setOnClickListener(changeName);
        return rootView;
    }

    View.OnClickListener changeName = new View.OnClickListener() {
        @Override
        public void onClick(View view) {

            image1.startAnimation(anime);
            Handler handler = new Handler();
            handler.postDelayed(new Runnable() {
                @Override
                public void run(){
                    dataPasser.onReplaceFragment(Result.class);
                }
            },1000);
        }
    };
    public interface OnReplaceFragment {
        public void onReplaceFragment(Class fragmentClass);
    }

    @Override
    public void onAttach(Activity a) {
        super.onAttach(a);
        try {
            dataPasser = (OnReplaceFragment) a;
        } catch (ClassCastException e) {
            throw new ClassCastException(a.toString() + " must implement onDataPass");
        }
    }
}

the fragment that i want to display

public class Result extends Fragment {

TextView textView;
Button btnBack;
public static Result instance = null;

public static Result getInstance(){
    return instance;
}

public Result() {
    // Required empty public constructor
}


@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    // Inflate the layout for this fragment
    View v = inflater.inflate(R.layout.fragment_result, container, false);
    textView = (TextView) v.findViewById(R.id.text11);
    btnBack = (Button) v.findViewById(R.id.btnBack);
    textView.setText("working!!");
    Toast.makeText(getActivity().getApplicationContext(),"working",Toast.LENGTH_LONG).show();
    return v;
}

}

Main Activity XML:

    <?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/main_content"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:context="com.example.hercules.tadhosttutrial.MainActivity">

<android.support.design.widget.AppBarLayout
    android:id="@+id/appbar"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:paddingTop="@dimen/appbar_padding_top"
    android:background="@color/red"
    android:theme="@style/AppTheme.AppBarOverlay">


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

</android.support.design.widget.AppBarLayout>

<android.support.v4.view.ViewPager
    android:id="@+id/frame_container"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:layout_behavior="@string/appbar_scrolling_view_behavior" />

New2 XML:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.hercules.tadhosttutrial.New2"
android:background="@color/yellow">

<!-- TODO: Update blank fragment layout -->

<Button
    android:id="@+id/changeBtn"
    android:layout_width="80dp"
    android:layout_height="40dp"
    android:layout_gravity="center_horizontal"
    android:text="change"/>

<ImageView
    android:id="@+id/image1"
    android:background="@drawable/icon_complete"
    android:layout_width="200dp"
    android:layout_height="200dp"
    android:layout_centerHorizontal="true"
    android:layout_centerVertical="true"
    />

Result XML:

    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/colorAccent"
    tools:context="com.example.hercules.tadhosttutrial.Result">

  <!-- TODO: Update blank fragment layout -->

  <Button
      android:id="@+id/btnBack"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:text="back"/>

  <TextView
      android:id="@+id/text11"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:text="WORKING"
      android:layout_centerVertical="true"
      android:layout_centerHorizontal="true"
      android:textSize="70dp"
      />

</RelativeLayout>
1

There are 1 answers

1
Yazan On

What i mean, is making MainActivity as a main container for all fragments, either with tabs or just a regular fragment,

1- Main Activity XML: remove ViewPager, add a FrameLayout instead (use same id)

2- Create new fragment TabsFragment with this XML:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.hercules.tadhosttutrial.New2"
android:background="@color/yellow">

<android.support.v4.view.ViewPager
    android:id="@+id/frame_container"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:layout_behavior="@string/appbar_scrolling_view_behavior" />
</RelativeLayout>

3- Move initializing SectionsPagerAdapter and ViewPager from main activity to TabsFragment:

this part:

private SectionsPagerAdapter mSectionsPagerAdapter;
private ViewPager mViewPager;

and this:

mSectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager());
mViewPager = (ViewPager) findViewById(R.id.frame_container);
mViewPager.setAdapter(mSectionsPagerAdapter);
TabLayout tabLayout = (TabLayout) findViewById(R.id.tabs);
tabLayout.setupWithViewPager(mViewPager);
tabLayout.getTabAt(0).setIcon(R.drawable.icon_info);
tabLayout.getTabAt(1).setIcon(R.drawable.icon_heart_rate_sensor_jpg);
tabLayout.getTabAt(2).setIcon(R.drawable.icon_graph_jpg);

4- I think moving SectionsPagerAdapter class in a new file is better too.

now if you want default view for app to be the tabs, then in MainActivity at onCreate() show TabsFragment by calling your method:

onReplaceFragment(TabsFragment.class);

now every thing should work fine, because the idea here is to replace the fragment displayed in main activity with another one in this case TabsFragment, Result, and New2

not to replace viewpager fragments (because as i told you this is managed via the adapter) not by calling replace()

you may need to play around this, it's not a final code, just something to give you idea about it.