How Can I move from one fragment to new fragment? - android

I am trying to move to another fragment by clicking on a button. the current fragment named as FirstFragment and the target fragment named as AttendanceFragment. When I run the app it just crashed.
This is the code of the current fragment
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
/**
* A simple {#link Fragment} subclass.
*/
public class FirstFragment extends Fragment {
public FirstFragment() {
// 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_first, container, false);
Button btn1 = (Button) v.findViewById(R.id.btn1);
btn1.setOnClickListener(
new View.OnClickListener() {
#Override
public void onClick(View v) {
AttendanceFragment fragment = new AttendanceFragment();
FragmentManager fragmentManager = getActivity().getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.register_attendance, fragment);
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
}
}
);
return v;
}
}

Make an interface.
public interface FragmentChangeListener{
public void replaceFragment(Fragment fragment);
}
Implements your parent activity with this interface.
public class MainActivity extends Activity implements FragmentChangeListener {
#Override
public void replaceFragment(Fragment fragment) {
FragmentManager fragmentManager = getSupportFragmentManager();;
FragmentTransaction fragmentTransaction =
fragmentManager.beginTransaction();
fragmentTransaction.replace(mContainerId, fragment);
fragmentTransaction.addToBackStack(fragment.toString());
fragmentTransaction.commit();
}
}
Call this method from Fragments like this.
//In your fragment - call this method from onClickListener
public void showOtherFragment(){
Fragment fragment=new NewFragmentName();
FragmentChangeListener listener = (FragmentChangeListener)getActivity();
listener.replaceFragment(fragment);
}

Please read Communicating with other Fragments
There you can find elegant version of solution posted by #Sanjog Shrestha. You should register you callback in onAttach(Activity activity) and unregister it in onDetach(). You better be sure that Activity implements interface defined by yourself.

Related

Replacing a fragment from inside a fragment

I read online, that to call another fragment, to take up the FrameLayout, you need to create an interface that talks to the activity and when the button clicked the function inside the interface that is defined in the activity replaces the Fragment with another fragment, but instead of creating the interface, i tried doing it directly from inside the fragment and it worked. So any reasons why i should not be doing this ?
import android.content.Context;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentTransaction;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
public class FragmentOne extends Fragment {
public FragmentOne() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_fragment_one, container, false);
Button btnONe = view.findViewById(R.id.btnOne);
btnONe.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
onButtonPressed();
}
});
return view;
}
public void onButtonPressed() {
FragmentTransaction fragmentTransaction = getActivity().getSupportFragmentManager().beginTransaction();
fragmentTransaction.replace(R.id.fragmentContainer, new FragmentTwo("Femin Dharamshi did it!"));
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
}
}
Fragments are part of the Activity and fragment should be hosted through their parent activities as stated by google in Android developers docs.
You can refer this link:-
https://developer.android.com/training/basics/fragments/communicating
You should call getFragmentManager().beginTransaction().replace(int id, Fragment fr).commit(); in onViewCreated() method, not onCreateView() method.
Just move your code in onCreateView() into onViewCreated() method.

How can I connect fragment in Activity?

I want to go to Fragment when Click button event. but I have issues about it.
Here's my code.
#OnClick(R.id.Main_Bottom_Bar_Summary)
public void onBottomBarClicked()
{
loadFragment(new AddItemFragment());
}
private void loadFragment(android.support.v4.app.Fragment fragment) {
FragmentManager fm = getFragmentManager();
FragmentTransaction fragmentTransaction = fm.beginTransaction();
fragmentTransaction.replace(R.id.frameLayout, fragment);
fragmentTransaction.commit(); // save the changes
}
and top of the acitivity. import files.
import android.app.Fragment;
import android.app.FragmentManager;
import android.app.FragmentTransaction;
And My Fragment:
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.and.dmt.R;
public class AddItemFragment extends Fragment
{
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_additemdialog,container, false);}
}
And I can see this issue.
What's this issue? How can I solve it?
If I change loadFragment parameter "Fragment" to "android.support.v4.app.Fragment"
then This issue appear.
loadFragment() takes android.app.Fragment as argument whereas your fragment extends android.support.v4.app.Fragment.
Change the argument for loadFragment() to take v4 Fragment and use getSupportFragmentManager().
if you use support fragment, try this code :
private void loadFragment(android.support.v4.app.Fragment fragment) {
android.support.v4.app.FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
fragmentTransaction.replace(R.id.frameLayout, fragment);
fragmentTransaction.commit(); // save the changes
}
Add below code to calling Activity.
addFragment(R.id.fragment_container, NewFragment.newInstance());
and add below method in the fragment class which will return new Instance of that very fragment.
public static NewFragment newInstance() {
return new NewFragment();
}

How to remove a fragment from within itself

In my application, I have an instance of a fragment, ActivityFragment, which is added dynamically when a button, addActivity, is pressed. There is a delete_button in each ActivityFragment, and I have set an onClickListener for this button within the ActivityFragment class. When the delete_button is pressed, I want to remove the fragment from inside the onClick method. How would I go about doing this when I create the ActivityFragment object and add it to the activity in a method outside of the fragment class? And what field should I use for .remove()?
Note that delete_button should only remove the instance of the fragment it is in.
Here is my MainActivity.java with the ActivityFragment class. The addActivity button is at the bottom:
import android.app.Fragment;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.FragmentActivity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.TextView;
public class MainActivity extends FragmentActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public static class ActivityFragment extends Fragment {
// #Nullable is used because the method may return a null value
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, Bundle savedInstanceState) {
final View fragment1 = inflater.inflate(R.layout.activity_fragment, container, false);
Button edit_button = (Button) fragment1.findViewById(R.id.edit_button);
Button delete_button = (Button) fragment1.findViewById(R.id.delete_button);
edit_button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
TextView activityText = (TextView) getView().findViewById(R.id.activity_text);
activityText.setText("success");
}
});
delete_button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
getFragmentManager().beginTransaction()
.remove().commit();
}
});
return fragment1;
}
}
public void addActivity(View view) {
ActivityFragment myFragment = new ActivityFragment();
getFragmentManager().beginTransaction()
.add(R.id.fragment_container, myFragment).commit();
}
}
You can remove the fragment instance like this
delete_button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
getFragmentManager().beginTransaction()
.remove(ActivityFragment.this).commit();
}
});
A fragment can be removed by doing this:
FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
MyFragment myFragment = new MyFragment();
fragmentTransaction.remove(myFragment).commit();
Here myFragment is your "FRAGMENT" that you want to remove from the current context or current activity.

Communication between fragments via interfaces

The fragments are a part of the bottom navigation bar, so far so good on the navigation part. But when i try to pass data from fragment1 to fragment2 the app is crashing. Also I am using the example given by google at this following link
When I use the following code android studio gives me deprecated warning!
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
So I am using CONTEXT instead of ACTIVITY below is my code that crashes :
MainActivity
import android.support.annotation.NonNull;
import android.support.design.widget.BottomNavigationView;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.MenuItem;
import android.view.View;
import android.widget.TextView;
import com.br.tron.bottombar.RadioFragment;
import com.br.tron.bottombar.StreamFragment;
import com.br.tron.bottombar.InfoFragment;
public class MainActivity extends AppCompatActivity implements RadioFragment.OnNameSetListener {
BottomNavigationView bottomNavigationView;
private Fragment fragment;
private FragmentManager fragmentManager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
fragmentManager = getSupportFragmentManager();
fragment = new RadioFragment();
final FragmentTransaction transaction = fragmentManager.beginTransaction();
transaction.add(R.id.main_container, fragment).commit();
bottomNavigationView = (BottomNavigationView) findViewById(R.id.bottomNavigationBar);
bottomNavigationView.setOnNavigationItemSelectedListener(new BottomNavigationView.OnNavigationItemSelectedListener(){
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem item) {
switch (item.getItemId()) {
case R.id.nav_button_one:
fragment = new RadioFragment();
break;
case R.id.nav_button_two:
fragment = new StreamFragment();
break;
case R.id.nav_button_three:
fragment = new InfoFragment();
break;
}
final FragmentTransaction transaction = fragmentManager.beginTransaction();
transaction.replace(R.id.main_container, fragment).commit();
return true;
}
});
}
public void performStreamClick(){
View view = bottomNavigationView.findViewById(R.id.nav_button_two);
view.performClick();
}
#Override
public void setUrl(String url) {
StreamFragment frag=(StreamFragment) getSupportFragmentManager().findFragmentByTag("frag");
frag.getUrl(url);
}
}
RadioFragment(Fragment1 where the data exist)
import android.app.Activity;
import android.content.Context;
import android.support.v4.app.Fragment;
import android.os.Bundle;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
public class RadioFragment extends Fragment implements Button.OnClickListener {
Button buttonman;
View rootView;
String url;
Activity a;
OnNameSetListener onNameSetListener;
#Override
public void onAttach(Context context) {
super.onAttach(context);
if (context instanceof Activity) {
a = (Activity) context;
try{
onNameSetListener=(OnNameSetListener) context;
}
catch (Exception e){}
}
}
public RadioFragment(){
};
#Override
public View onCreateView(LayoutInflater inflater,ViewGroup container, Bundle savedInstanceState) {
rootView = inflater.inflate(R.layout.fragment_player, container, false);
buttonman = (Button)rootView.findViewById(R.id.buttonman);
buttonman.setOnClickListener(this);
return rootView;
}
#Override
public void onClick(View v) {
/*Fragment fragment = new StreamFragment();
FragmentManager fragmentManager = getActivity().getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.main_container, fragment);
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();*/
url="www.idontknow.com";
onNameSetListener.setUrl(url);
((MainActivity)a).performStreamClick();
}
public interface OnNameSetListener
{
public void setUrl(String url);
}
}
StreamFragment(fragment2 where I want to send the data -from fragment1)
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 StreamFragment extends Fragment {
TextView textViewStream;
public StreamFragment(){};
#Override
public View onCreateView(final LayoutInflater inflater,final ViewGroup container,final Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_stream, container, false);
}
public void getUrl(String url)
{
textViewStream.setText(url);
}
}
LOGCAT
01-06 20:10:23.023 3744-3744/com.br.tron.bottombar E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.br.tron.bottombar, PID: 3744
java.lang.NullPointerException: Attempt to invoke virtual method 'void com.br.tron.bottombar.StreamFragment.getUrl(java.lang.String)' on a null object reference
at com.br.tron.bottombar.MainActivity.setUrl(MainActivity.java:64)
at com.br.tron.bottombar.RadioFragment.onClick(RadioFragment.java:61)
at android.view.View.performClick(View.java:5201)
at android.view.View$PerformClick.run(View.java:21209)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5525)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:730)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:620)
01-06 20:10:24.663 3744-3744/? I/Process: Sending signal. PID: 3744 SIG: 9
You never register the frag tag you later search for.
In your MainActivity modify:
final FragmentTransaction transaction = fragmentManager.beginTransaction();
transaction.add(R.id.main_container, fragment, "frag").commit();
...
final FragmentTransaction transaction = fragmentManager.beginTransaction();
transaction.replace(R.id.main_container, fragment, "frag").commit();
...
In addition to that within your StreamFragment class you never set the TextViewStream variable after you inflate your layout.
#Override
public View onCreateView(final LayoutInflater inflater,final ViewGroup container,final Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_stream, container, false);
textViewStream = (TextView) view.findViewById(R.id.ID_GOES_HERE);
return view;
}
Edit: Further Errors
You're getting a ClassCastException because you're not checking to see whether the fragment you get in MainActivity.setUrl is a StreamFragment. And it makes sense that it's failing because you register the frag tag for all three types of custom Fragments. Here's a further solution:
fragment = new RadioFragment();
final FragmentTransaction transaction = fragmentManager.beginTransaction();
transaction.add(R.id.main_container, fragment, "radio_fragment").commit();
...
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem item) {
switch (item.getItemId()) {
String tag = "";
case R.id.nav_button_one:
fragment = new RadioFragment();
tag = "radio_fragment";
break;
case R.id.nav_button_two:
fragment = new StreamFragment();
tag = "stream_fragment";
break;
case R.id.nav_button_three:
fragment = new InfoFragment();
tag = "info_fragment";
break;
}
final FragmentTransaction transaction = fragmentManager.beginTransaction();
transaction.replace(R.id.main_container, fragment, tag).commit();
return true;
}
Make the appropriate change in the Tag string in setUrl:
StreamFragment frag=(StreamFragment) getSupportFragmentManager().findFragmentByTag("stream_fragment");
if (frag != null) frag.getUrl(url);
Both of the current answers key in on your crash problem. I expect that will take care of your primary question. #asadmshah seems to have taken care of your next problem. Make sure to up vote his answer & accept it.
Regarding the warning from using Google's example code, here is what AS will currently give you if you tell it to create a new fragment.
#Override
public void onAttach(Context context) {
super.onAttach(context);
if (context instanceof OnFragmentInteractionListener) {
mListener = (OnFragmentInteractionListener) context;
} else {
throw new RuntimeException(context.toString()
+ " must implement OnFragmentInteractionListener");
}
}
The point of this is to make sure that the Activity you're attaching to implements the interface you've defined in your fragment.
And on the subject of the interface, all fragment to activity comms should be done through it. It would be better to find a way to call performStreamClick() through the interface as well. (I just realized I made this same mistake on an app I started several months ago but am just finishing up now :).
Lastly, just an FYI, you can get the attached activity of a fragment with getActivity().
EDIT:
1st, it might help to see your current code. I'm going to assume you have what Asad has put in his answer, more or less. Also, what is the expected behavior? I believe that you make a selection in RadioFragment then replace it with StreamFragment. That is, both fragments take the whole nav bar, they don't exist at the same time. If this is wrong, let me know.
If you're still calling setUrl() and performStreamClick() in the same order as before, you're getting null because you've never created a fragment by that name. You can't find a fragment you haven't already created.
Without actually setting this up to test it myself, I believe what you need to do would be to save the url in a global variable in setUrl(), then in your click listener, pass that to the StreamFragment when you create it.
See the "Deliver a Message to a Fragment" section of the link you've sited for doing that
Bundle args = new Bundle();
args.putInt(ArticleFragment.ARG_POSITION, position);
newFragment.setArguments(args);
(obviously, handling your url string instead of the int in the example)
Also, it's not a bad idea to handle null when searching for a fragment that should exist already
StreamFragment frag=(StreamFragment) getSupportFragmentManager().findFragmentByTag("stream_frag");
if(frag == null) {
final FragmentTransaction transaction = fragmentManager.beginTransaction();
StreamFragment fragment = new StreamFragment();
transaction.replace(R.id.main_container, fragment, "stream_frag").commit();
}
You should initialize your textViewStream in the StreamFragment fragment.

add() function giving error in Fragment

I have the following code in the Main Activity and I have a FragmentLayout class Which is responsible for calling the fragment.
Code
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
public class MainActivity extends FragmentActivity
{
Button btn;
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btn=(Button)findViewById(R.id.button1);
btn.setOnClickListener(new OnClickListener()
{
#Override
public void onClick(View v)
{
FragmentLayout f1=new FragmentLayout();
getSupportFragmentManager().beginTransaction().add(R.id.main_id, f1).commit();
}
});
}
}
I get this error-
The method add(int, Fragment) in the type FragmentTransaction is not applicable for the arguments (int, FragmentLayout) MainActivity.java.
What is the problem here?
You can use transaction manager only for Fragments.
I provide you simple example:
Create some Fragment and layour for it:
public class FragmentOne extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater,
ViewGroup container, Bundle savedInstanceState) {
//Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_one, container, false);
}
}
And in your public void onClick(View v)
just call:
FragmentOne f1=new FragmentOne();
getSupportFragmentManager().beginTransaction().add(R.id.main_id, f1).commit();
Here
getSupportFragmentManager().beginTransaction().add(R.id.main_id, f1).commit();
f1 must extend Fragment in order to be added as part of a FragmentTransaction.

Categories

Resources