Replace multiple fragments at the same time - android

I have an Activity with a navigation drawer. I have used fragments for this and when I'm moving to different menus in the drawer I add them to the backstack with addToBackStack() method. Basically, Activity starts with Fragment A then if I go to Fragment B or Fragment C I can press back and go back to Fragment A.
But now I have a notification which should open the Activity with Fragment B open and when I press back it should take me back to Fragment A. Is there a way to handle this like in startActivities.
Here is the code for the Activity:
#Override
protected void onCreate(Bundle savedInstanceState) {
...
getSupportFragmentManager().beginTransaction().replace(R.id.layoutContent, new FragmentA()).commit();
}
#Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.buttonA:
getSupportFragmentManager().popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
break;
case R.id.buttonB:
transactFragment(new FragmentB());
break;
...
}
}
private void transactFragment(Fragment fragment) {
getSupportFragmentManager().beginTransaction().replace(R.id.layoutContent, fragment).addToBackStack(fragment.getClass().getName()).commit();
}

Why not just define the fragments with tags and call them as you need to?
Here's a sample of how I work with my fragments:
Start your fragments in the Activity's onCreate() method, like so:
/** Load screen1 */
Instructions screen1 = new Instructions();
screen1.setArguments(getIntent().getExtras());
getFragmentManager().beginTransaction().
add(com.example.tool.R.id.
instructions_container, screen1, "screen1").
addToBackStack(null).
commit();
Then you can grab them and show/hide them as much as you like:
/** screen 1 */
public void showInstructions()
{
// show screen 1
getFragmentManager().findFragmentByTag("screen1").
getView().setVisibility(View.VISIBLE);
}
In my project, we use a global enum to check which fragment is currently up, so we don't have to rely on the stack, which has more than once proven itself to be unreliable.
onBack calls a switch, which checks this enum and acts accordingly. For your use-case, you can just track when this notification has been called, so it will go from Fragment B, to Fragment A.

Related

How to navigate from fragment in one activity to fragment in another activity?

I want to add back navigation to toolbar. I need to get from a fragment in an activity to a specific fragment in another activity.
It looks a little like this, where every orange line means navigating to a new activity or fragment:
How do I move from fragment B to fragment A from OtherActivity?
Consider these steps:
From Activity 1 holding Fragment A , you want to directly load Fragment B in Activity 2.
Now, I am thinking first, then you press a button in Fragment A, you can directly go to Activity B.
Then it means, you can simply load Fragment B as soon as you arrive in Activity 2.
Since you are dealing with back navigation (I believe you mean the upNavigation?), you can override the following:
But watch clearly, because if you need to load an exact fragment in Activity 2, you need to know somehow:
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
Intent intent = new Intent(this, Activity2.class);
intent.putExtra("frag", "fragmentB");
startActivity(intent);
return true;
default:
return super.onOptionsItemSelected(item);
}
}
As you can see, when you click the back arrow on the toolbar, we pass a value through our intent to identity which fragment we want to load.
Next, in your Activity2, simply get the intent extra and do a switch or an if statement:
#Override
public void onResume(){
super.onResume();
Intent intent = getIntent();
String frag = intent.getExtras().getString("frag");
switch(frag){
case "fragmentB":
//here you can set Fragment B to your activity as usual;
fragmentManager.beginTransaction().replace(R.id.container_body, new FragmentB()).commit();
break;
}
}
From here, you should have your Fragment B showing in Activity 2.
Now you can handle the same thing while inside Activity 2 to decide where to go when a user clicks the back home arrow!
I hope this helps you get an idea.
Note: I thought about the interface approach and realized it is not necessary since this can be done easily with this approach!
To navigate from one Activity to another Activity's Fragment, with Kotlin version 1.4.0 and, for example, calling a click listener on a button it works so:
binding.yourButton.setOnClickListener {
supportFragmentManager.beginTransaction().replace(R.id.yourLayout, NameOfYourFragment()).commit()
}
Use this code to change your fragment
fragmentManager.beginTransaction().replace(R.id.container_body, new FragmentC()).commit();
and to show navigation on custom toolbar add
Toolbar toolbar = (Toolbar) rootView.findViewById(R.id.toolbar);
((AppCompatActivity)getActivity()).setSupportActionBar(toolbar);
((AppCompatActivity)getActivity()).getSupportActionBar().setDisplayHomeAsUpEnabled(true)
((AppCompatActivity)getActivity()).getSupportActionBar().setHomeButtonEnabled(true);

Using the back button from a fragment in Android

I'm aiming for the following behavior.
When I am on my main activity,
If I navigate into fragment 1,
and from there, navigate into fragment 2,
then when I hit the phone's back button,
because I am on fragment 2 I am returned to the home screen, and not fragment 1.
If I had a separate button on the page, this behavior would be very easy, as I could just do:
Button.setOnClickListener(new OnClickListener()
{
#Override
public void onClick(View v)
{
FragmentManager fm = getFragmentManager();
fm.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
}
});
I'm running into difficulties because I need to use the phone's own back button. I've read that the OnButtonPressed() event is only usable by an activity, not a fragment, and moving this kind of logic into the activity is proving difficult!
How can I achieve the behavior I'm after?
Just track the backstackcount and you can do whatever you want on the basis of count :
#Override
public void onBackPressed() {
manageBackStack();
}
private void manageBackStack() {
switch (getSupportFragmentManager().getBackStackEntryCount()) {
case 1:
//Do when count is 1
break;
case 2:
//Do when count is 2
break;
default:
finish();
}
}
Hope it will help :)
When you are adding the fragment you need to add the transaction to back stack. That means you want this transaction to be reversed when back button is pressed.
Please use the below code :
getSupportFragmentManager().beginTransaction()
.add(detailFragment, "detail")
// Add this transaction to the back stack
.addToBackStack()
.commit();
You can find more details in :
https://developer.android.com/training/implementing-navigation/temporal.html

Fragment not attached to Activity when back pressed

I have an implementation of fragment as explained here. I have expanded the BaseFragment class to handle navigation icon onClickListener. The code for that looks like this,
private void onBackButtonPressed(int tag)
{
switch (tag)
{
case Global.DISPLAY_STORE:
{
setTitle("Loyalty Cards",Color.BLACK);
setToolBar(getResources().getColor(R.color.white), Global.ADD_CARD,R.drawable.add_round_btn);
break;
}
case Global.ADD_CARD:
{
setTitle("Wallet", Color.WHITE);
setToolBar(getResources().getColor(R.color.colorPrimary), Global.DISPLAY_STORE,R.drawable.icon_shopping);
getFragmentManager().popBackStack();
break;
}
case Global.CARD_DETAILS:
{
setTitle("Loyalty Cards",Color.BLACK);
setToolBar(getResources().getColor(R.color.white), Global.ADD_CARD,R.drawable.add_round_btn);
getFragmentManager().popBackStack();
break;
}
}
}
I am using this block of code to change the ToolBar icons and colors when back button is pressed.This code resides in BaseFragment.
Here is how I implement the code to handle back press,
I have my fragment extending the BaseFragment
public class CardDetailsFragment extends BaseFragment
Now inside the BaseFragment onCreate I have this code,
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mainActivity = (MainActivity) getActivity();
ImageButton righBarButton = (ImageButton) mainActivity.getToolbar().findViewById(R.id.btn_ToolBarRightBtn);
righBarButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
onRighBarButtonClicked(Integer.parseInt(v.getTag().toString()));
}
});
mainActivity.getToolbar().setNavigationOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
onBackButtonPressed(BACK_BUTTON_TAG);
}
});
getFragmentManager().addOnBackStackChangedListener(this);
shouldDisplayHomeUp();
}
By this every fragments back button press and the right bar button item click in toolbar are handled.
Consider the scenario I have three fragments A , B and C.
From Fragment A I open Fragment B and Then Fragment C. Now From fragment C I click the back button to reach fragment B. The back button event is handled by above code and it works fine.
Now from Fragment B, I click the back button to reach Fragment A. But when I click back button I am getting exception
java.lang.IllegalStateException: Fragment CardDetailsFragment{d8b35b5} not attached to Activity
at android.support.v4.app.Fragment.getResources(Fragment.java:636)
here the CardDetailsFragment is the FragmentC, but I am clicking the
back button from Fragment B
The first time the user presses the back button, Fragment C is no longer necessary and thus it is detached from the activity. The problem lies in the fact that even though Fragment C is detached, it is still registered as a listener for back stack change events.
The second time the user presses the back button, your onBackStackPressed() method is called in Fragment C. When getResources() is executed, there is no activity attachment so getResources() fails.
Something like this in your fragment should fix it:
#Override
public void onDestroy() {
getFragmentManager().removeOnBackStackChangedListener(this);
super.onDestroy();
}

How to refresh a previous fragment on back press without disturbing the back stack

I am using one activity for tabactivity with viewpager and attached fragmentA.when i want to move fragmentB ,replaced fragmentB with present fragmentA.I need to find solution for onbackpress in FragmentB refresh fragmentA wihtout changing Backstack because i used nearly ten fragments in one tab.
Is there any method in fragment life cycle
When Fragment B over Fragment A, fragment A is onPause(). After backpress, fragment A is onResume(). So you can create a boolean to observe this change.
In Fragment A
private boolean isBackFromB;
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
isBackFromB=false;
}
#Override
public void onPause() {
super.onPause();
isBackFromB = true;
}
#Override
public void onResume() {
super.onResume();
updateUI();
if (isBackFromB) //Do something
}
View pager does not always hold it's fragments in memory, so you have to handle 2 scenarios:
1 - fragment is recreated - just read data from wherever you hold them and show in ordinary way.
2 - fragment is modified from outside while still has been held by ViewPager, and as I understand this is what concerns you.
What you can do is to create this listener and then notify fragment that it was shown again and possibly should reload it's data.
More complex answer for communicating between different application's components is using some event bus like Otto.
override onBackPressed() method in Activity, add all fragment in backstack.
#Override
public void onBackPressed() {
FragmentManager manager =getFragmentManager();
int count = manager.getBackStackEntryCount();
if (count == 0) {
super.onBackPressed();
} else {
manager.popBackStack();
}
}

Create custom BackKey to navigate through framents

I got the next FragmentActivity. This FragmentActivity inflates a layout with a LinearLayout(a menu where some buttons are defined to call other fragments) and a FrameLayout (a black space where the other fragments are loaded depending the button I select).
public class MenuViewActivity extends FragmentActivity {
....
I load the selected Fragment using onClickListener:
protected void onCreate(Bundle savedInstanceState) {
....
final OnClickListener fragment_1 = new OnClickListener() {
#Override
public void onClick(View v) {
fragment_1 Fragment = new fragment_1();
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.fragment_container, Fragment);
transaction.addToBackStack(null);
transaction.commit();
}
};
I do this for about 5 buttons. This menu also contains a custom back key. The functionality of this back button should be like:
[fragment_1][fragmen_2][fragment_3][fragment_4][fragment_5]
The app starts always showing fragment_1. I con go from fragment_1 to any of the other fragments. So I could go for example from [fragment_1] to [fragment_4]. When pressing the back key I should go back to [fragment_1].
To detail a little bit more the functionality, I could do: [fragment_1]->[fragment_2]->[fragment_3] and when pressing back, should go back to [fragment_1].
I've got a onClickListener for the back key, but I don't know how to implement this functionality.
you're looking for this
getSupportFragmentManager().popBackStack();
also if you're unaware that's the default functionality for the actual android back button, so unless you've overrode it that will do the same thing.
You just need to pop all fragments from your backstack, unless you reach the one you want. It is probably simplest to use FragmentManager's popBackStack():
public abstract void popBackStack (int id, int flags)
Pop all back stack states up to the one with the given identifier

Categories

Resources