How to check fragment is visible in Activity OnBackpressed
I want to check when user click back button in Searchfragment I want to set OnBackpressed is running ,but if user click back button in OtherFragment I want to set OnBackpressed is not running.
and I try this in Activity is not work
btn_back.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
SearchFragment searchFragment = new SearchFragment();
if (searchFragment.isVisible()){
onBackPressed();
}
}
});
thanks for your help!
First of all, when you declare something like this:
SearchFragment searchFragment = new SearchFragment();
And then call
searchFragment.isVisible()
This will obviously return false since you didnt even add it to the container. What you need to do is to retrieve the fragment instance that you already added and check it's state.
I have once tried to use the method isVisible() but it is not entirely accurate, at least not for my case. What I came up with is to check the top fragment in the container as follow:
Fragment fragment = getActivity().getSupportFragmentManager().findFragmentById(R.id.fragment_container);
if(fragment instance of SearchFragment) //means your visible fragment is the SearchFragment
onBackPressed();
Related
I'm having an issue that maybe is happening to other community members and I wanted to ask if somebody knows the solution. I have an app with these Two activities (MainActivity, UserProfileActivity).
The MainActivity contains a NavigationDrawer that navigates through fragments. So here it's the problem. While navigating in the second fragment and pressing a button in that fragment. It opens the UserProfileActivity (child of MainActivity) with the app bar generated by being a child. When you press that back button of this new Activity it should get back to MainActivity (parent) in the fragment that we were when we called this new Activity. But not, it's getting back to the MainActivity but with the home fragment loaded. Not the one we called previously.
Does anybody know how to solve that problem? Here I leave the code of the intent I do from the fragment:
Intent intent = new Intent(context, UserProfileActivity.class);
Bundle bundle = new Bundle();
bundle.putString("userId", message.getUserId());
intent.putExtras(bundle);
context.startActivity(intent);
Reason behind this behavior:
If you set the value of android:parentActivityName in your manifest.xml, by default pressing navigation button will create a new instance of the parent activity every time rather than popping it out from the activity backstack, so you're seeing the home fragment.
Workaround
At first, remove android:parentActivityName from manifest.xml. In onCreate method of your ChildActivity, put getSupportActionBar().setDisplayHomeAsUpEnabled(true) if you haven't already. Then override onSupportNavigateUp() of your ChildActivity, and put finish().
ChildActivity.java:
public class ChildActivity extends AppCompatActivity {
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
...
getSupportActionBar().setDisplayHomeAsUpEnabled(true)
...
}
#Override
public boolean onSupportNavigateUp() {
finish();
return super().onSupportNavigateUp();
}
}
I have an activity where the user enters some data and submits it via a submit button, that same activity also has some more buttons which lead to fragments.
When I click on the fragments, the submit button of the activity overlaps the UI of the fragment, so in the calling code of fragments I set the visibility of that submit button as invisible but when back pressed from fragment then also that submit button is invisible.
I want the submit button to be visible when activity is being displayed and invisible when the fragments are being displayed.
Add your fragment on button click,
loginSubmit.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
loginSubmit.setVisibility(View.GONE);
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.addToBackStack("LayoutFragment");
ft.add(R.id.framelayoutfaqs, new LayoutFragment());
ft.commit();
}
});
#Override
public void onBackPressed() {
if (getSupportFragmentManager().getBackStackEntryCount() > 0) {
getSupportFragmentManager().popBackStackImmediate();
loginSubmit.setVisibility(View.VISIBLE);
} else
super.onBackPressed();
}
NOTE : make sure you import same Fragment class which you used to create YourFragment. Also choose getSupportFragmentManager() or getFragmentManager() accordingly.
You can handle it in 0nBackPressed() method of Activity class .
Make the button invisible in either of onCreate, onActivityCreated or onAttach methods of your fragment and make it visible in onDetach method of your fragment.
I have an activity (MainActivity) which has a navigation drawer and can show 2 fragments (Fragments A and B), one at a time. (This activity is the default activity with navigation drawer created by android studio)
When I choose fragment B on the drawer the action bar menu is updated to show a button specific for fragment B (Button P).
Button P open an independent activity (IndependentActivity) with an explicit intent, on this activity I perform a database operation and after it I finish this activity to go back to MainActivity.
The problem is: When IndependentActivity is finished, MainActivity is shown but it shows fragment A instead of fragment B which was the one that called the intent to go to IndependentActivity.
How do I fix this by showing the fragment that initiated the action to go to another activity? Is there any way to save the fragment that was appearing?
Basically what you have to do is:
Save the state of the MainActivity when you enter IndependentActivity
Reload the state of MainActivity when you exit IndependentActivity
A simple implementation of this could be:
#Override
public void onSaveInstanceState(Bundle savedInstanceState) {
// Save which fragment that is in the view when entering another activity
savedInstanceState.putString("fragment", "fragmentB");
super.onSaveInstanceState(savedInstanceState);
}
Fragment B can be replaced with a string that tells the application which is the current fragment.
Once you come back to the activity you want to:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if( savedInstanceState != null ) {
// Get which fragment that was active when you left the activity
savedInstanceState.getString("fragment");
// Programatically select the fragment here
}
}
You can read more about saving instance state here:
http://developer.android.com/training/basics/activity-lifecycle/recreating.html
I will leave it to you to programmatically select the fragment. I hope it helps!
I found out that I was having the same problem as this: https://stackoverflow.com/a/29464116/2325672
The back arrow to return did not work and reset the activity's fragments and the emulator back triangle worked perfectly.
Adding this code to IndependentActivity worked for me:
#Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId()== android.R.id.home) {
Intent intent = NavUtils.getParentActivityIntent(this);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
NavUtils.navigateUpTo(this, intent);
return true;
}
return super.onOptionsItemSelected(item);
}
I have a MainActivity in my application, from where all the fragments are called using Navigation Drawer. And default fragment of the activity is 'A'. So everytime i open the application, 'A' fragment is called. when I hit 'back' from another fragment B, I want to get to default fragment 'A', as what happens in gmail - from any fragment if we hit back, it returns to default fragment "Primary mails".
I tried calling the 'A' fragment by adding the following code to the onPause() of fragment 'B'.
#Override
public void onPause() {
super.onPause();
fragment = new A();
FragmentTransaction fragTransaction = getFragmentManager().beginTransaction();
fragTransaction.replace(R.id.a,fragment ).commit();
}
But when I hit back, fragment 'A' is called for a moment, but then the application closes unexpectedly.
Logcat :
01-14 12:44:42.264: E/WindowManager(4655): android.view.WindowLeaked: Activity com.litchi.iguardian.MainActivity has leaked window com.android.internal.policy.impl.PhoneWindow$DecorView{41da6348 V.E..... R.....ID 0,0-513,243} that was originally added here
Whats the correct way of doing this ?
to back to previous fragment see below code :
fragmentManager.popBackStack(...);
put this in onBack event
to call popBackStack method you first need to call addToBackStack method while calling fragment
Use this code
android.support.v4.app.Fragment detail = new CurrentClass();
detail.setArguments(bundle);
android.support.v4.app.FragmentManager fragmentManager = getFragmentManager();
fragmentManager.beginTransaction()
.add(R.id.content_frame, detail).addToBackStack("back")
.commit();
You should customize the behavior when you press the back button, because by default it will destroy launched activity and you see your fragment while callbacks goes from onPause() until onStop() and activity is not visible for you anymore. Just override this method, it must solve the problem:
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
// your code
return true;
}
return super.onKeyDown(keyCode, event);
}
But yeah, it is for global control, for switching fragments you may also call addToBackStack(); when you want return previous fragment by pressing back button.
instead of writing that code in onPause() you can write that code in onBackPressed() of your main activity .
I have a HomeFragment that has a button, which when clicked calls the following:
Fragment frag = new CustFragment();
FragmentManager fragmentManager = getFragmentManager();
fragmentManager.beginTransaction().replace(R.id.home_container, frag).commit();
Then in my FragmentActivity which is the fragments mentioned above, I have:
#Override
public void onBackPressed() {
getFragmentManager().popBackStack();
super.onBackPressed();
}
That's what I've tried, but if I'm on the frag fragment and I press the back button, it doesn't go back to the last fragment (the HomeFragment). Instead, it attempts to go back to the last Activity, but since there is none (i.e. the previous activity had finish() invoked on it), it just goes to the Android Home Screen.
What am I doing wrong?
PS: If I'm being unclear, just comment below and i'll try to clarify.
Change
#Override
public void onBackPressed()
{
getFragmentManager().popBackStack();
super.onBackPressed();
}
to
#Override
public void onBackPressed()
{
if(getSupportFragmentManager().getBackStackEntryCount() > 0)
getSupportFragmentManager().popBackStack();
else
super.onBackPressed();
}
and
fragmentManager.beginTransaction().replace(R.id.home_container, frag).commit();
to
fragmentManager.beginTransaction().replace(R.id.home_container, frag).addToBackStack(null).commit();
Add your fragment to back stack using addToBackStack(null) like..
fragmentManager.beginTransaction().replace(R.id.home_container, frag).addToBackStack(null).commit();
beginTransaction creates a new FragmentTransaction. It has a method addToBackstack. If you call it before you commit your transaction you can remove your overridden onBackPressed completely. Reference
You can use:
fragmentTransaction.addToBackStack(null);
and no need to take care of onBackPressed().
BTW in your onBackPressed() super.onBackPressed() means you are actually changing nothing.
It should have been something like:
if(currentFragmentIsCustFragment){
getSupportFragmentManager().popBackStack();
}else{
super.onBackPressed();
}