I have a DrawerMenuActivity suppose "AA" and it has 3 fragments "A", "B" and "C" as it's menu. Fragment "A" is my default screen. Now i have navigated to the fragment "B" which has listview items and each item click will open another new activity "AB". In AB there will be a button and that button click will open another activity "AC". so Basically the flow is as follows,
From AA(DrawerMenuActivity) -> "A" fragemnt -> "B" or "C" fragments -> AB(Activity) -> AC(Activity)
Now what i want to do is to return to fragment "B" from the Activity "AC".
I have replaced the fragments of Activity "AA" like this,
in OnCreate(),
if (savedInstanceState == null) {
A fragment = new A();
replaceFragment(fragment, false, Constants.HOME_FRG_TAG);
Handler handler = new Handler(Looper.getMainLooper());
Runnable runnable = new Runnable() {
#Override
public void run() {
if (getIntent().getStringExtra("FROM AC") != null) {
updateDisplay(1);
}
}
};
handler.postDelayed(runnable, 10);
}
and for replacing fragments,
public void updateDisplay(int position) {
Fragment fragment = null;
String tag = null;
switch (position) {
case 0:
clearStack();
mDrawerLayout.closeDrawer(mDrawerList);
break;
case 1:
fragment = new B();
tag = "B";
break;
case 2:
fragment = new C();
tag = "C";
break;
default:
break;
}
if (fragment != null) {
replaceFragment(fragment, true, tag);
setTitle(navMenuTitles[position]);
mDrawerLayout.closeDrawer(mDrawerList);
} else {
Log.e("Activity", "Error in creating fragment");
}
}
replaceFragment() function,
public void replaceFragment(Fragment newFragment, boolean backStackTag, String fragmentTag) {
try {
Fragment selectedFrag = getSupportFragmentManager().findFragmentByTag(fragmentTag);
if (selectedFrag != null && selectedFrag.isVisible()) {
return;
}
FragmentManager fm = AA.this.getSupportFragmentManager();
FragmentTransaction transaction = fm.beginTransaction();
if (backStackTag) transaction.addToBackStack(null);
transaction.commit();
} catch (Exception e) {
Log.e("exception ", " on adding fragment");
// TODO: handle exception
}
}
and clearStack(),
public void clearStack() {
FragmentManager fm = AA.this.getSupportFragmentManager();
if (fm.getBackStackEntryCount() > 0) {
fm.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
}
}
in AC Activity i have tried to come back to fragment "B" like this,
Intent in = new Intent(AC.this, AA.class);
in.putExtra("FROM AC", "from ac");
startActivity(in);
now this does what i intend to do but the problem is when it is loading fragment "A" opens for a brief time and then it comes back to the fragment "B".
How Do i navigate to fragment "B" from Activity "AC" properly?? please any help would be appreciated...!!
First when you go from AB to AC start it as with startActvityForResult, and make sure you don't pass the clear backstack flags. Do it just like this:
public static final int REQ_CODE = 1;
Intent in = new Intent(this, AB.class);
startActivityForResult(in, REQ_CODE);
So the backstack is not cleared. When replacing the fragments in AA do it like this:
public void replaceFragment(Fragment newFragment, boolean backStackTag, String fragmentTag) {
try {
Fragment selectedFrag = getSupportFragmentManager().findFragmentByTag(fragmentTag);
if (selectedFrag != null && selectedFrag.isVisible()) {
return;
}
FragmentManager fm = AA.this.getSupportFragmentManager();
FragmentTransaction transaction = fm.beginTransaction();
transaction.replace(R.id.container, fragmentB).commit();
} catch (Exception e) {
Log.e("exception ", " on adding fragment");
// TODO: handle exception
}
}
And when you want to get back from activity AC, set the result to RESULT_OK if you want to navigate back to AA or RESULT_CANCELED if not.
setResult(Activity.RESULT_OK);
finish();
In AB, override the onActivityResult method so it sends you back to AA:
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQ_CODE) {
if (resultCode == RESULT_OK) {
finish();
}
}
}
so if RESULT_OK is passed, it will go back to AA where the activity was still in onStop() and the state was saved. Also make sure to init your views in onCreate and not in onStart.
Use startActivityForResult to pass params from AC to AA.It's a little complicated.EventBus may be helpful to you.
Related
hello great community I have an app in which I am using bottom navigation with 4 fragments. to move to the last fragment the user must be logged in so when a new user open the app and tap on item 4 a login activity open.
the problem is when I backpress from login activity it moves me to the home fragment 1 which is ok but the state of the bottom navigation item doesn't changes the fragment 4 remain highlighted. so how to manage it that when I return back from the login activity the home fragment item should be highlighted.
[
this is my BottomNAvigation main activity
public class Bottom_Nav extends AppCompatActivity implements BottomNavigationView.OnNavigationItemSelectedListener {
SparseArray<Fragment> myFragments;
String user_type;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_bottom__nav);
SharedPreferences sharedPreferences = getSharedPreferences("DataStore", Context.MODE_PRIVATE);
user_type = sharedPreferences.getString("user_type", "");
BottomNavigationView bottomNavigationView = (BottomNavigationView) findViewById(R.id.navigation);
Nav_Helper.disableShiftMode(bottomNavigationView);
//make array to avoid re creating of fragments
myFragments = new SparseArray<Fragment>();
//loading the default fragment
loadFragment(new HomeFragment());
//getting bottom navigation view and attaching the listener
bottomNavigationView.setOnNavigationItemSelectedListener(this);
}
private void loadFragment(Fragment fragment) {
//switching fragment
FragmentTransaction fragmentTransaction =
getSupportFragmentManager().beginTransaction();
fragmentTransaction.replace(R.id.content, fragment);
fragmentTransaction.commit();
}
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem item) {
Fragment fragment = null;
int id = item.getItemId();
if (id == R.id.navigation_home) {
fragment = new HomeFragment();
myFragments.put(1, fragment);
loadFragment(fragment);
} else if (id == R.id.navigation_use) {
getFragmentManager().popBackStack();
switch (user_type) {
case "detailer":
fragment = new Detailer_Zone();
myFragments.put(4, fragment);
loadFragment(fragment);
break;
case "customer":
fragment = new Customer_Zone();
myFragments.put(4, fragment);
loadFragment(fragment);
break;
case "empty":
Intent intent = new Intent(this, Login_Activity.class);
startActivity(intent);
break;
}
}
else if (id == R.id.navigation_search) {
// get cached instance of the fragment
fragment = myFragments.get(2);
// if fragment doesn't exist in myFragments, create one and add to it
if (fragment == null) {
fragment = new SearchFragment();
myFragments.put(2, fragment);
}
loadFragment(fragment);
} else if (id == R.id.navigation_map) {
// get cached instance of the fragment
fragment = myFragments.get(3);
// if fragment doesn't exist in myFragments, create one and add to it
if (fragment == null) {
fragment = new MapsActivity();
myFragments.put(3, fragment);
}
loadFragment(fragment);
}
return true;
}
Case for Login:
case "empty":
Intent intent = new Intent(this, Login_Activity.class);
startActivityForResult(intent , 101);
break;
Login activity:
When user click on back button execute below code.
setResult(RESULT_CANCELED);
finish();
Handle case in Bottom_Nav activity :
// This method is called when the second activity finishes
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
// check that it is the SecondActivity with an OK result
if (requestCode == 101) {
if (resultCode == RESULT_CANCELED) {
onNavigationItemSelected(menuItem)
}
}
}
Try this work around. Replace your case "empty": with this:
case "empty":
bottomNavigationView.setSelectedItemId(R.id.navigation_home);
Intent intent = new Intent(this, Login_Activity.class);
startActivity(intent);
break;
Tell me if this works.
I have bottom navigation and set each item load a fragment. When my application load Home fragment default selected. My application fragment Backstack work when navigate for example click Posts > Search > Favor and after press back it's work and back to Search > Post > Home But my problem in select again Previous fragment for example when navigate Post > Search > Post now when press back first press not working and not back any fragment and second press back to Home. I want work this format when navigate Post > Search > Post on press back navigate Search > Home.
I have pushFragments method and Override onBackPressed. My codes this is:
pushFragments method:
public void pushFragments(String tag, Fragment fragment){
FragmentManager manager = getSupportFragmentManager();
FragmentTransaction fTransaction = manager.beginTransaction();
if (manager.findFragmentByTag(tag)==null){
fTransaction.add(R.id.frame_fragmentMain_container,fragment,tag);
fTransaction.addToBackStack(tag);
}
Fragment homeFragment = manager.findFragmentByTag(TAG_FRAGMENT_HOME);
Fragment postsFragment = manager.findFragmentByTag(TAG_FRAGMENT_POSTS);
Fragment usersFragment = manager.findFragmentByTag(TAG_FRAGMENT_USERS);
Fragment searchFragment = manager.findFragmentByTag(TAG_FRAGMENT_SEARCH);
Fragment favorFragment = manager.findFragmentByTag(TAG_FRAGMENT_FAVOR);
// Hide all Fragment
if(homeFragment!=null){
fTransaction.hide(homeFragment);
}
if(postsFragment!=null){
fTransaction.hide(postsFragment);
}
if(usersFragment!=null){
fTransaction.hide(usersFragment);
}
if(searchFragment!=null){
fTransaction.hide(searchFragment);
}
if(favorFragment!=null){
fTransaction.hide(favorFragment);
}
switch (tag){
case TAG_FRAGMENT_HOME:
if(homeFragment!=null){
fTransaction.show(homeFragment);
setToolbarTitle("Home Page");
disableNavigationToolbarIcon();
}
break;
case TAG_FRAGMENT_POSTS:
if(postsFragment!=null){
fTransaction.show(postsFragment);
setToolbarTitle("Posts List");
enabledNavigationToolbarIcon();
}
break;
case TAG_FRAGMENT_USERS:
if(usersFragment!=null){
fTransaction.show(usersFragment);
setToolbarTitle("Authors List");
enabledNavigationToolbarIcon();
}
break;
case TAG_FRAGMENT_SEARCH:
if(searchFragment!=null){
fTransaction.show(searchFragment);
setToolbarTitle("Search Page");
enabledNavigationToolbarIcon();
}
break;
case TAG_FRAGMENT_FAVOR:
if(favorFragment!=null){
fTransaction.show(favorFragment);
setToolbarTitle("Favor Posts");
enabledNavigationToolbarIcon();
}
break;
}
fTransaction.commitAllowingStateLoss();
}
and Override onBackPressed:
#Override
public void onBackPressed() {
FragmentManager manager = getSupportFragmentManager();
if(manager.getBackStackEntryCount()>1){
for (Fragment fragment : manager.getFragments()){
if(fragment.isVisible()){
FragmentManager childManager = fragment.getChildFragmentManager();
if(childManager.getBackStackEntryCount()>0){
if(fragment instanceof UsersFragment){
setToolbarTitle("Authors List");
}
childManager.popBackStack();
return;
}
}
}
manager.popBackStack();
}else{
new AlertDialog.Builder(this)
.setTitle("Really Exit?")
.setMessage("Are you sure you want to exit?")
.setNegativeButton(android.R.string.no, null)
.setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface arg0, int arg1) {
finish();
moveTaskToBack(true);
}
}).create().show();
}
}
Try this out..It will definitely work..
public void pushFragments(Fragment fragment) {
try {
String backStateName = fragment.getClass().getName();
FragmentManager fragmentManager = getSupportFragmentManager();
boolean fragmentPop = fragmentManager.popBackStackImmediate(backStateName, 0);
if (!fragmentPop) {
try {
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.frame_layout, fragment);
fragmentTransaction.addToBackStack(backStateName);
fragmentTransaction.commit();
} catch (Exception e) {
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
and in OnBackPress ---
#Override
public void onBackPressed() {
if (getSupportFragmentManager().getBackStackEntryCount() == 1) {
finish();
return;
}
super.onBackPressed();
}
I have a lot of Fragments. e.g: A1,A2,A3, B1,B2,C1,C2,C3. All Fragments were in a container,FActivity.
I hoped when current Fragment was A1 or B1 or c1 I press the back key,the project finished.
I follwed this order to hide previous one and show next one, and all of them were addToBackStack.But when I call FActivity.onBackPressed(), I found the popBack not restoring previous fragment and feel confused.some fragment were missed.Especially B1 and C1 were not in the backstack. They were missed.
here is my hide&show code:
private void showFragment(FragmentTransaction ft1, Fragment fm1, Fragment fm2, String tag) {
if (fm1 != null) {
if (!fm1.isAdded()) {
ft1.add(R.id.information_detail, fm1).hide(fm1);
} else {
ft1.hide(fm1);
}
ft1.addToBackStack(tag);
}
if (!fm2.isAdded()) {
ft1.add(R.id.infomation_detail, fm2, tag);
} else {
ft1.show(fm2);
}
ft1.commit();
}
fragment control
Fragment currentFragment ;
public void startFragmentOnParameter(Fragment oldFragment, String tag, String... param) {
FragmentTransaction ft1 = getFragmentManager().beginTransaction();
switch (tag) {
case "A1":
A1= new A1();
showFragment(ft1,oldFragment, A1, true, "A1");
currentFragment = mPatientCaseInHistory;
break;
case "A2":
A2= new A2();
showFragment(ft1, oldFragment, A2, false, "A2");
currentFragment = mPatientWithArrear2;
break;
case "A3":
A3= new A3();
showFragment(ft1, oldFragment, A3, false, "A3");
currentFragment = mPatientsCases3;
break;
......
}
and onBackPressed
public void onBackPressed() {
String name = currentFragment.getClass().getSimpleName();
if(name.equals("A1")||name.equals("B2")||name.equals("C1")){
finish();
}else{
super.onBackPressed();
currentFragment = (Fragment) getFragmentManager().findFragmentById(R.id.infomation_detail);
}
}
What's wrong in my code?
Try to use
getFragmentManager().popBackStack();
instead
super.onBackPressed();
I have an Activity in which I switch the content by replacing a Fragment.
In the onCreate of this Activity, I set the first Fragment with this code:
fm.beginTransaction().add(R.id.container, new FooFragment(), "f_0").commit();
After that, I want to switch this Fragment by another one depending on an Integer (I use a drawer), here is the code:
int position = //I get my index here
Fragment f = fm.findFragmentByTag("f_" + position); //(1)
if (f == null) {
switch (position) {
case 0:
f = new FooFragment();
break;
case 1:
f = new BarFragment();
break;
//Etc...
}
}
//Then I replace the actual Fragment by the new one
fm.beginTransaction()
.replace(R.id.container, f, "f_" + position)
.commit();
My problem is that the code on (1) always return null so every time I change the Fragment, it creates a new instance. I want to have at any time only one instance of each Fragment type.
Thanks.
Set first fragment:
getSupportFragmentManager().beginTransaction().addToBackStack("f_0").replace(R.id.container, new FooFragment(), "CURRENT_FRAGMENT_TAG").commit();
Use this function to replace fragments:
public void replaceFragment(Fragment fragment, String tag) {
Fragment currentFragment = getSupportFragmentManager().findFragmentByTag("CURRENT_FRAGMENT_TAG");
//to avoid adding the same fragment, you can use 'instanceof' instead of comparator
if (currentFragment.getClass() == fragment.getClass()) {
return;
}
getSupportFragmentManager().popBackStack(tag, FragmentManager.POP_BACK_STACK_INCLUSIVE);
getSupportFragmentManager()
.beginTransaction()
.addToBackStack(tag).replace(R.id.container, fragment, "CURRENT_FRAGMENT_TAG")
.commit();
}
Example execution:
replaceFragment(new FooFragment(), "f_" + position);
Override onBackPressed.
#Override
public void onBackPressed() {
if (getSupportFragmentManager().getBackStackEntryCount() == 1) {
finish();
} else {
super.onBackPressed();
}
}
I'm using NavigationDrawer with some fragments, the problem is when I'm in a fragment and hit the back button, it makes the app close, then I have to open it again, put my username and password all over again to use the app, how can I prevent that from happen?
public class NavigationMain extends ActionBarActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//...
}
public void setFragmentList(int posicao) {
Fragment fragment = null;
switch (posicao) {
case 0:
fragment = new MainFragment();
break;
case 1:
fragment = new MensagensFragment();
break;
case 2:
fragment = new EscolasFragment();
break;
case 3:
fragment = new AutorizadasFragment();
break;
case 4:
fragment = new CadastroFragment();
break;
default:
break;
}
if (fragment != null) {
FragmentManager fragmentManager = getFragmentManager();
fragmentManager.beginTransaction().replace(R.id.content_frame, fragment).commit();
// update selected item and title, then close the drawer
navigationAdapter.resetarCheck();
navigationAdapter.setChecked(posicao, true);
layoutDrawer.closeDrawer(linearDrawer);
} else {
// error in creating fragment
Log.e("MainActivity", "Error in creating fragment");
}
}
}
#Override
public void onBackPressed() {
int count = getFragmentManager().getBackStackEntryCount();
if (count == 0) {
super.onBackPressed();
//additional code
} else {
getFragmentManager().popBackStack();
}
}
I think you missed to add the fragment transaction in your back stack. Try the following:
fragmentManager.beginTransaction().replace(R.id.content_frame, fragment).addToBackStack(null).commit();