How can I use the transaction backstack to pop fragments? - java

Suppose I have a MainActivity with FragmentContainerView.
This FragmentContainerView's size matches the MainActivity.
Then I want to show one fragment at a time in this FragmentContainerView.
Fragment1, Fragment2, and Fragment3.
Each fragment will have one button. When button is pressed, next fragment is loaded.
Fragment1 (Press button)--> Fragment2 (Press button)--> Fragment3 (Press button)--> Fragment1 --> and so on.
So far, I was able to implement, but I am not sure how to make my fragments such that, when I press the back button,
Fragment1 should exit app
Fragment2 should load Fragment1
Fragment3 should load Fragment2
Here is my MainActivity
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
FirstFragment fragment = new FirstFragment();
Bundle bundle = new Bundle();
bundle.putString("CLASS_NAME", " ");
fragment.setArguments(bundle);
getSupportFragmentManager().beginTransaction()
.add(R.id.fragment_container_view, fragment, null)
.commit();
}
}
Here is my Fragment1
#Override
public void onViewCreated(#NonNull View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
binding = FragmentFirstBinding.bind(getView());
String previous_class = getArguments().getString("CLASS_NAME");
if(!previous_class.equals(" ")){
binding.textViewFirstFragment.setText(previous_class);
}
//On button click, navigate to MainActivity
binding.buttonFirstFragment.setOnClickListener(this);
}
#Override
public void onClick(View v) {
//Log.i("BACKSTACK", "debug: current status of fragment back stack " + getFragmentManager().getBackStackEntryCount());
Fragment fragment = new SecondFragment();
putBundleArgument(fragment);
replaceFragment(fragment);
debug();
}
public void replaceFragment(Fragment fragment) {
FragmentTransaction transaction = getFragmentManager().beginTransaction();
transaction.replace(R.id.fragment_container_view, fragment);
transaction.addToBackStack(null);
transaction.commit();
}
Here is my Fragment2
#Override
public void onViewCreated(#NonNull View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
binding = FragmentSecondBinding.bind(getView());
String previous_class = getArguments().getString("CLASS_NAME");
binding.textViewSecondFragment.setText(previous_class);
//On button click, navigate to MainActivity
binding.buttonSecondFragment.setOnClickListener(this);
}
#Override
public void onClick(View v) {
//Log.i("BACKSTACK", "debug: current status of fragment back stack " + getFragmentManager().getBackStackEntryCount());
Fragment fragment = new ThirdFragment();
putBundleArgument(fragment);
replaceFragment(fragment);
debug();
}
public void replaceFragment(Fragment fragment) {
FragmentTransaction transaction = getFragmentManager().beginTransaction();
transaction.replace(R.id.fragment_container_view, fragment);
transaction.addToBackStack(null);
transaction.commit();
}
Lastly, here is my Fragment3
#Override
public void onViewCreated(#NonNull View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
binding = FragmentThirdBinding.bind(getView());
String previous_class = getArguments().getString("CLASS_NAME");
binding.textViewThirdFragment.setText(previous_class);
//On button click, navigate to MainActivity
binding.buttonThirdFragment.setOnClickListener(this);
}
#Override
public void onClick(View v) {
Fragment fragment = new FirstFragment();
putBundleArgument(fragment);
replaceFragment(fragment);
debug();
}
public void replaceFragment(Fragment fragment) {
FragmentTransaction transaction = getFragmentManager().beginTransaction();
/*
ThirdFragment fragment3 = new ThirdFragment();
transaction.remove(fragment3);
SecondFragment fragment2 = new SecondFragment();
transaction.remove(fragment2);
*/
getFragmentManager().popBackStack();
getFragmentManager().popBackStack();
getFragmentManager().popBackStack();
transaction.replace(R.id.fragment_container_view, fragment);
transaction.addToBackStack(null);
transaction.commit();
}

#Override // override this in MainActivity
public void onBackPressed(){
int count = getSupportFragmentManager().getBackStackEntryCount();
if(count == 1)//When there is only 1 fragment left in the stack ie Fragment 1.
finsh();
else
getSupportFragmentManager().popBackStack(); //Fragment 2 and 3 are popped here.
super.onBackPressed();
}

Related

FragmentTwo cannot be cast to FragmentOne when I am trying to comunicate between fragments

I have two fragments and I want to show them in my screen one by one. They are managed by MainActivity. The first fragment contains a TextView and a Button. The second fragment contains an EditText and a Button. What I am trying to do is: The first fragment shows on screen, and when the user press the button I want my activity to show the second fragment, and when the user press the button from this fragment I want to send the text from the EditText to the first fragment and display it on the TextView. I used interface for listeners.
public class MainActivity extends AppCompatActivity implements Listener, ListenerTwo{
FragmentTransaction fragmentTransaction;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
fragmentTransaction = getSupportFragmentManager().beginTransaction();
fragmentTransaction.replace(R.id.fragmentPlaceholder, new FragmentOne());
fragmentTransaction.commit();
}
#Override
public void onButtonSelected() {
fragmentTransaction = getSupportFragmentManager().beginTransaction();
fragmentTransaction.replace(R.id.fragmentPlaceholder, new FragmentTwo());
fragmentTransaction.commit();
}
#Override
public void onButtonPressed(String text) {
FragmentOne fragmentOne = (FragmentOne)getSupportFragmentManager().findFragmentById(R.id.fragmentPlaceholder);
if (fragmentOne != null)
fragmentOne.setTextt(text);
}
}
In my FragmentOne:
public void onViewCreated(#NonNull View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
Button button = view.findViewById(R.id.button);
textView = view.findViewById(R.id.textView);
Listener listener = (Listener) getActivity();
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(getContext(), "button clicked", Toast.LENGTH_SHORT).show();
if (listener != null)
listener.onButtonSelected();
}
});
}
public void setTextt (String text) {
textView.setText(text);
}
In FragmentTwo:
#Override
public void onViewCreated(#NonNull View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
Button button = view.findViewById(R.id.button2);
EditText editText = view.findViewById(R.id.editText);
ListenerTwo listener = (ListenerTwo) getActivity();
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(getContext(), "button clicked", Toast.LENGTH_SHORT).show();
if (listener != null)
listener.onButtonPressed(editText.getText().toString());
}
});
}
inside Activity in onButtonPressed method you are casting currently set FragmentTwo to FragmentOne. note that whe you are setting Fragment you are using fragmentTransaction.replace( <- REPLACE! you are loading fragments into R.id.fragmentPlaceholder, when new one is set, then previous is going to be destroyed
inside onButtonPressed you have to set again FragmentOne
fragmentTransaction = getSupportFragmentManager().beginTransaction();
fragmentTransaction.replace(R.id.fragmentPlaceholder, new FragmentOne());
fragmentTransaction.commit();
these lines are common, are placed also in onCreate so they may be packed into one method called in these two places
for transfering some data into fragment you may use passing this object in a constructor, but better way would be to use Bundle, so:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
showFragmentOne(null);
}
#Override
public void onButtonPressed(String text) {
showFragmentOne(text);
}
private void showFragmentOne(String text) {
Fragment fragment = new FragmentOne();
if (text!=null){
Bundle bundle = new Bundle();
bundle.putInt("text", text);
fragment.setArguments(bundle);
}
fragmentTransaction = getSupportFragmentManager().beginTransaction();
fragmentTransaction.replace(R.id.fragmentPlaceholder, fragment);
fragmentTransaction.commit();
}
inside onViewCreated at the end of method check Bundle and set text
Bundle bundle = this.getArguments();
if (bundle != null) {
String text = bundle.getString("text", null);
if(text!=null) setTextt(text); // or just textView.setText(text);
}

Problem with fragment that uses a method of another class, Android Studio

I have two different classes that i will show
public class Iniziale extends AppCompatActivity {
Button credits,gioca,giocamyquiz,newquestion;
TextView testo;
public boolean whatgame;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_iniziale);
gioca = findViewById(R.id.gioca);
giocamyquiz = findViewById(R.id.giocamyquiz);
newquestion= findViewById(R.id.newquestions);
whatgame=true;
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
gioca.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
whatgame=true;
Intent homeIntent = new Intent(Iniziale.this, MainActivity.class);
startActivity(homeIntent);
finish();
}
});
giocamyquiz.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
whatgame=false;
Intent homeIntent = new Intent(Iniziale.this, MainActivity.class);
startActivity(homeIntent);
finish();
}
});
}
public boolean FragmentMethod() {
return whatgame;
}
}
and a fragment
public class MainActivityFragment extends Fragment {
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
super.onCreateView(inflater, container, savedInstanceState);
View view = inflater.inflate(R.layout.fragment_main_activity, container, false);
what=true; //sceglie a quale quiz giocare
what=((Iniziale) getActivity()).FragmentMethod();
I want use method FragmentMethod() in my Fragment class because I need the value of the whatgame variable.
How the code is write it doesn't work.
In Iniziale class I have 2 buttons and based of what button i click I will modify my whatgame variable and modify some parameters in fragment class

How to get the current changed state of a fragment inside an Activity?

I've made 2 Activities. The first Activity contains a button, which intents to second Activity. In the second Activity I have two buttons and a container. Each button adds and replaces a fragment into the container. Each fragment in the container contains button, which intents back to first activity.
My question is: I press button2 in my second activity, that reveals fragment2 in the container, and I press fragment2, it takes me to the first activity. When I press the button of the first activity, it intents to second activity, and the container is empty again. I want to see in the container the already pressed fragment2 (i gave a background color to be visible). How can I do that?
First activity java:
public class MainActivity extends AppCompatActivity {
ImageButton bbbb;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
bbbb = findViewById(R.id.bbbb);
bbbb.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent intent = new Intent(MainActivity.this,Main2Activity.class);
startActivity(intent);
}});}}
Second activity java:
public class Main2Activity extends FragmentActivity {
private ImageButton snipe;
private ImageButton aim;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
snipe = (ImageButton) findViewById(R.id.snipe);
aim = (ImageButton) findViewById(R.id.aim);
final View.OnClickListener mListener = new View.OnClickListener() {
#Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.snipe:
FragmentManager FM = getSupportFragmentManager();
FragmentTransaction FT = FM.beginTransaction();
BlankFragment F1 = new BlankFragment();
FT.add(R.id.fragment_container1, F1);
FT.replace(R.id.fragment_container1, F1);
FT.commit();
break;
case R.id.aim:
FragmentManager FM1 = getSupportFragmentManager();
FragmentTransaction FT1 = FM1.beginTransaction();
BlankFragment2 F11 = new BlankFragment2();
FT1.add(R.id.fragment_container1, F11);
FT1.replace(R.id.fragment_container1, F11);
FT1.commit();
break; }}};
findViewById(R.id.snipe).setOnClickListener(mListener);
findViewById(R.id.aim).setOnClickListener(mListener); }}
One of the fragments java (both have the same code):
public class BlankFragment extends Fragment{
ImageButton b1;
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
super.onCreateView(inflater, container, savedInstanceState);
View rootView = inflater.inflate(R.layout.fragment_blank, container, false);
b1 = (ImageButton) rootView.findViewById(R.id.b1);
b1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent intent = new Intent(getActivity(), MainActivity.class);
startActivity(intent); }});
return rootView; }}

Back Stack in fragments not working

I have a home activity in that I am replacing fragments as required.
In home activity I have main fragment, then from main fragment I am replacing a Transport fragment, from Transport fragment I am replacing TransportList Fragment.
Now as I press back from TransportList fragment I see the main fragment instead of Transport fragment.
I have added the fragments to backstack still its working like this.
Home activity
public class HomeActivity extends AppCompatActivity{
private boolean mBackPressCancelled = false;
private static final long BACK_PRESS_DELAY = 10000;
private long mBackPressTimestamp;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home);
toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
FragmentManager fragmentManager = HomeActivity.this.getFragmentManager();
MainFragment fragment = new MainFragment();
fragmentManager.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
fragmentManager.beginTransaction().replace(R.id.mycontainer, fragment,"MAIN_FRAGMENT").commitAllowingStateLoss();
}
#Override
public void onBackPressed() {
// Do nothing if the back button is disabled.
if (!mBackPressCancelled) {
// Pop fragment if the back stack is not empty.
if (getFragmentManager().getBackStackEntryCount() > 0) {
mTxtTitle.setVisibility(View.GONE);
mLogo.setVisibility(View.VISIBLE);
super.onBackPressed();
}
else {
if (snackbar != null) {
snackbar.dismiss();
}
long currentTimestamp = System.currentTimeMillis();
if (currentTimestamp < mBackPressTimestamp + BACK_PRESS_DELAY) {
super.onBackPressed();
} else {
mBackPressTimestamp = currentTimestamp;
Toast.makeText(this,"press again",Toast.LENGTH_LONG).show();
}
}
}
}
}
Transport fragment :
mBtnSearch.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
FragmentManager fragmentManager = getFragmentManager();
TransportListFragment fragment1 = new TransportListFragment();
fragmentManager.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
fragmentManager.beginTransaction().replace(R.id.mycontainer, fragment1).addToBackStack("G").commit();
}
});
Whats going wrong here please help.Thank you.
Just remove the following lines when you add new Fragment to the BackStack:
fragmentManager.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);

How to pass parameter to Fragment from FragmentActivity

I have a FragmentActivity in my android application.
I use a viewPager to insert tabs in the activity. So I have this code. It works.
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.view_clienti);
Bundle extras = getIntent().getExtras();
if (extras != null) {
String datas= extras.getString("Cliente");
if (datas!= null) {
System.out.println("pippo");
}
}
TabAdapter = new DemoCollectionPagerAdapter(getSupportFragmentManager());
Tab = (ViewPager)findViewById(R.id.pager);
Tab.setOnPageChangeListener(
new ViewPager.SimpleOnPageChangeListener() {
#Override
public void onPageSelected(int position) {
actionBar = getActionBar();
actionBar.setSelectedNavigationItem(position); }
});
Tab.setAdapter(TabAdapter);
actionBar = getActionBar();
//Enable Tabs on Action Bar
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
ActionBar.TabListener tabListener = new ActionBar.TabListener(){
#Override
public void onTabReselected(android.app.ActionBar.Tab tab,
FragmentTransaction ft) {
// TODO Auto-generated method stub
}
#Override
public void onTabSelected(ActionBar.Tab tab, FragmentTransaction ft) {
Tab.setCurrentItem(tab.getPosition());
}
#Override
public void onTabUnselected(android.app.ActionBar.Tab tab,
FragmentTransaction ft) {
// TODO Auto-generated method stub
}};
//Add New Tab
actionBar.addTab(actionBar.newTab().setText("Scheda Cliente").setTabListener(tabListener));
actionBar.addTab(actionBar.newTab().setText("Conto Cliente").setTabListener(tabListener));
apriConnessioneDB();
}
This is the class FragmentStatePagerAdapter
public class DemoCollectionPagerAdapter extends FragmentStatePagerAdapter {
public DemoCollectionPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int i) {
switch (i) {
case 0:
//Fragement for Android Tab
return new infoCliente();
case 1:
//Fragment for Ios Tab
return new infoCliente();
case 2:
//Fragment for Windows Tab
return new infoCliente();
}
return null;
}
#Override
public int getCount() {
return 2;
}
#Override
public CharSequence getPageTitle(int position) {
return "OBJECT " + (position + 1);
}
}
This is the class Fragment:
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.view_infocliente, container, false);
if(savedInstanceState!=null){
//String tmp = savedInstanceState.getString("myKey");
//TextView mTabHost = (TextView) findViewById(android.R.id.labelRagioneSociale);
System.out.println("PIPPPPPPPPPPPPPPPPPPPPPP");
}
TextView btn=(TextView) view.findViewById(R.id.labelRagioneSociale5);
btn.setText("pippo");
return view;
}
Now I want to know How I can pass a parameter to infoCliente class.
In the onCreate method of first class I have this:
String datas= extras.getString("Cliente");
I want pass this parameter to fragment class.
Bundle bundle = new Bundle();
bundle.putInt("battery", bat);
MyFragment fragment=new MyFragment();
fragment.setArguments(bundle);
FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.add(R.id.fragment_container,fragment);
ft.commit();
Then in onCreate() method of the fragment:
Bundle bundle=getArguments(); int mLabel = bundle.getInt("battery",0);
Define an interface in your Fragment, for example
public interface FragmentCallback {
onSomethingHappend(String param);
}
Implement the interface in your Activity.
Then, when you want to call the callback, do something like this:
FragmentCallback callback = (FragmentCallback) getActivity();
callback.onSomethingHappened(string);

Categories

Resources