2

I want to call another fragment from the current fragment on the click of the button in the current fragment.

Here is my Mainactivity :

import android.app.FragmentManager;
import android.os.Bundle;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.view.View;
import android.support.design.widget.NavigationView;
import android.support.v4.view.GravityCompat;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBarDrawerToggle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.Menu;
import android.view.MenuItem;

import com.asd.fragments.RecommendationsFragment;
import com.asd.ibitz4college.fragments.SearchCoachingFragment;
import com.asd.fragments.SearchCollegesFragment;
import com.asd.fragments.MainFragment;
import com.asd.fragments.SearchConsultanciesFragment;
import com.asd.fragments.TrendingFragment;

public class MainActivity extends AppCompatActivity
        implements NavigationView.OnNavigationItemSelectedListener {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);



        DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
        ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
                this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
        drawer.setDrawerListener(toggle);
        toggle.syncState();

        NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
        navigationView.setNavigationItemSelectedListener(this);

        FragmentManager fm = getFragmentManager();
        fm.beginTransaction().replace(R.id.content_frame,new MainFragment()).commit();





    }

    @Override
    public void onBackPressed() {
        DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
        if (drawer.isDrawerOpen(GravityCompat.START)) {
            drawer.closeDrawer(GravityCompat.START);
        } else {
            super.onBackPressed();
        }
    }

    @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 id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true;
        }

        return super.onOptionsItemSelected(item);
    }

    @SuppressWarnings("StatementWithEmptyBody")
    @Override
    public boolean onNavigationItemSelected(MenuItem item) {
        // Handle navigation view item clicks here.
        int id = item.getItemId();

        FragmentManager fm = getFragmentManager();
        fm.beginTransaction().replace(R.id.content_frame,new MainFragment()).commit();

        if (id == R.id.search_colleges) {
            // Handle the Search Colleges action
            fm.beginTransaction().replace(R.id.content_frame,new SearchCollegesFragment()).commit();

        }

         else if (id == R.id.search_consultancies) {
            fm.beginTransaction().replace(R.id.content_frame,new SearchConsultanciesFragment()).commit();

        }


        else if (id == R.id.search_coaching) {

            fm.beginTransaction().replace(R.id.content_frame,new SearchCoachingFragment()).commit();


        }

        else if (id == R.id.my_recommendations) {
         fm.beginTransaction().replace(R.id.content_frame, new RecommendationsFragment()).commit();

        }

         else if (id == R.id.trending) {

            fm.beginTransaction().replace(R.id.content_frame, new TrendingFragment()).commit();


        } else if (id == R.id.profile) {

        } else if (id == R.id.logout) {

        }

        DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
        drawer.closeDrawer(GravityCompat.START);
        return true;
    }
}

Here is one of my fragment :

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

import com.asd.k4c.R;


public class SearchCoachingFragment extends Fragment  {

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

            View rootview = inflater.inflate(R.layout.fragment_search_coaching,container,false);
            return rootview;



    }
} //Update code formatting

Suppose I want to call resultsfragment from the above fragment on the click of a button whose id is btn_search, then what should I do? I tried some already existing answers here, no luck! P.S: I'm a starter to the world of android dev.

  • 3
    Define a callback interface - http://developer.android.com/training/basics/fragments/communicating.html you should always communicate through the Activity the fragments are attached to. – Mark Feb 29 '16 at 12:10

5 Answers5

1

For doing a fragment transaction.Please do the following.

Eg.. A and B are fragments. Currently A is visible to the User. If you want to do a transaction. Just create as like below

 B b = new B(); 
((YourActivity)getActivity).setnewFragment(b,true);

public void setNewFragment(Fragment fragment,boolean addbackstack) {
        FragmentManager manager = getSupportFragmentManager();
        FragmentTransaction transaction = manager.beginTransaction();
        transaction.replace(R.id.fragment_content, fragment);
        if (addbackstack)
            transaction.addToBackStack(title);
        transaction.commit();
    }
Raja Jawahar
  • 6,742
  • 9
  • 45
  • 56
0

Use an interface to communicate between fragments. For example

public YourFirstFragment extends Fragment {

    public interface FragmentCallBack {
        void callBack();
    }

    private FragmentCallBack fragmentCallBack;

    public void setFragmentCallBack(FragmentCallBack fragmentCallBack) {
        this.fragmentCallBack = fragmentCallBack;
    }

    private void callThisWhenYouWantToCallTheOtherFragment(){
        fragmentCallBack.callBack();
    }
}

Then in You activity

private void setCallToFragment{
  yourFirstFragment.setFragmentCallBack(new FragmentCallBack(){
   void callBack(){
    yourSecondFragment.doWhatEver();
  }})

}
Rohit5k2
  • 17,948
  • 8
  • 45
  • 57
Niza Siwale
  • 2,390
  • 1
  • 18
  • 20
0

First you need to create an interface which defines methods that will be used by your fragment to invoke code from the respective activity it is attached to

public interface OnFragmentInteractionlistener {
    // the method that you call from your fragment, 
    // add whatever parameter you need in the implementation of this
    // method.
    void onClickOfMyView();
}

once you have created the interface, implement it any and all activities that use this fragment.

public class MainActivity extends AppCompatActivity
        implements OnMyFragmentInteractionListener {

    @Override
    public void onClickOfMyView() {
        // DO your on click logic here, like starting the transaction
        // to add/replace another fragment.
    }
}

Then in the onAttach of your fragment to an activity be sure to check if the attaching activity implements this interface, else throw a RunTimeException like so

@Override
public void onAttach(Context context) {
    super.onAttach(context);
    if (context instanceof OnMyFragmentInteractionListener) {
        mListener = (OnMyFragmentInteractionListener) context;
    } else {
        throw new RuntimeException(context.toString()
                + " must implement OnMyFragmentInteractionListener");
    }
}

Here mListener is a interface reference you hold in your fragment class through which you invoke the onClickOfMyView() method when actually the click happens

Your fragment class where the view's click code is there.

myView.setOnClickListener(new View.OnClickListener(){
    @Override
    public void onClick(View v) {
        mListener.onClickOfMyview();
    }
});
Bhargav
  • 8,118
  • 6
  • 40
  • 63
  • So basically, you need to create either a base class for all the fragments that will use this interface, or create a bunch of interfaces that activity will implement, then in every fragment you should use instanceOf and broadcastReceivder for some reason, and it will be better than use getActivity() that is built-in fragment method, i can't quite get why is this better, please explain to me(except for the cases when getActivity is null which you can just check anyway) – Nik Myers Feb 29 '16 at 12:46
  • This is better because the fragments are re-usable now, all you need to do in order to use this fragment in an activity is implement the interface, in the code you gave when one uses the fragment in an activity and it crashes, you do not know why exactly, see fragments need to be re-usable in other activities, by tying a fragment down to one activity you are going against purpose of a fragment – Bhargav Feb 29 '16 at 12:49
  • @NikMyers Also I don't understand why you need to use `broadcastReciever` ? – Bhargav Feb 29 '16 at 12:50
  • @Bharvag, so creating basic class for all activities is somehow more difficult that implementing same interface in all of activities? You have a code which registers broadcastReceiver to activity for some reason – Nik Myers Feb 29 '16 at 12:54
  • @NikMyers ah crap thats copy pasted from my app, let me fix that. what do you mean basic class for all activities? its an interface, interfaces exist for this purpose to de-couple dependencies, so that code can become re-usable – Bhargav Feb 29 '16 at 12:57
  • i meant that if you're gonna to use this fragment in other projects, with this approach, you need to implement interface in activity for this code to work, with my answer, you'll need to create a method, and in my way it would be a compile error which will be easy to fix, and also, if you have a BaseActivity class written by you, which other are extending, that you just need to create one method for it to work in all fragments of application, you approach will not be seen by compiler and thus this code wouldn't work if interface wouldn't be implemented – Nik Myers Feb 29 '16 at 13:04
  • Thanks for the response forum. I have NP Exception issue implementing the interface. here : http://stackoverflow.com/questions/35707076/null-pointer-exception-calling-fragments – Rakshith Vasudev Feb 29 '16 at 18:42
-1

You should create some method in your activity. Supposedly it will look like this :

public void startFragment(Fragment fragment) {
    fm.beginTransaction().replace(R.id.content_frame,new fragment).commit();
}

As you already done in youronNavigationItemSelected

Then, from your fragment, you can call

((MainActivity)getActivity()).startFragment(new SearchConsultanciesFragment()) 

for example

Nik Myers
  • 1,843
  • 19
  • 28
  • this is not a good way binding an activity to a fragment like this, but instead interfaces should be used that the activity implements, and the fragment "grabs" in onAttach, hence im voting down this answer – Bhargav Feb 29 '16 at 12:19
  • 1
    @Bhargav, then i want to see your answer here, which will work for all of the fragments in application, and would be relavent for Activity to implement – Nik Myers Feb 29 '16 at 12:31
  • just posted my answer, android studio actually generates this code when you create fragment using the GUI – Bhargav Feb 29 '16 at 12:37
-1

Create a method switchFragment in your MainActivity

FragmentTransaction ft;

    public void switchFrag() {
            try {
                    ft = getActivity().getFragmentManager().beginTransaction();
                    ft.replace(R.id.frame_container, new Your_Fragment.class);
                    ft.commit();
                } else {
                    Log.e("test", "else part fragment ");
                }

            } catch (Exception e) {
                e.printStackTrace();
            }

        }

Now from your current Fragment you can call this MainActivity's funciton throught the below code:

((MainActivity)getActivity()).switchFrag();

Let me know if this works for you! :)

Vivek Bhardwaj
  • 530
  • 5
  • 16
  • This is the wrong way, you are tying down the fragment to be usuable only in `MainActivity` by casting getActivity() to `MainActivity` instead if you were to use an interface to communicate between activity and fragment, there wouldn't be this coupling going on – Bhargav Feb 29 '16 at 12:52
  • 1
    i tried this in my code and its working very well .. and i did not face any problem with this.. there is not only a single path to a solution. the same thing can be done using multiple ideas..! – Vivek Bhardwaj Feb 29 '16 at 12:55
  • Alright I'm not going to fight this any more, to each his own I guess. – Bhargav Feb 29 '16 at 12:58
  • Ok imagine if you wanted to use this fragment in a different activity, there are many cases of this, this is exactly why fragments were introduced in api 11 in the first place, to make views and their logics re usable if required. But when you do something like `((MainActivity)getActivity()).switchFrag();` the fragment is completely dependent on the activity `MainActivity` the whole point of having a fragment is nullified. Instead of using a fragment here you could just inflate a layout and attach it to your container – Bhargav Feb 29 '16 at 13:02
  • this code is not just for a single activity my dear ! i think you are confused with it .. i just gave the answer according to the users need thats it .. – Vivek Bhardwaj Feb 29 '16 at 13:04
  • if you used this fragment with any other activity `((MainActivity)getActivity()).switchFrag();` would throw a classCastException – Bhargav Feb 29 '16 at 13:05
  • brother! i told you already .. according to the questions requirement .. this suits well .. ! – Vivek Bhardwaj Feb 29 '16 at 13:06