remove stack in fragment - android

each time when I open a fragment, it will be added to the stack.
So, the back button returns to me according to the stack.
I think I have to delete the stack each time I open a fragment.
if so how can I do that?
here is my code
public class MainActivity extends AppCompatActivity {
private FragmentManager fragmentManager;
FragmentTransaction transaction;
LinearLayout firstColumn,secondColumn,thirdColumn;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
fragmentManager = getSupportFragmentManager();
firstColumn = (LinearLayout) findViewById(R.id.first_column);
secondColumn = (LinearLayout) findViewById(R.id.second_column);
firstColumn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.main_container_frame_layout, new FirstFragment());
transaction.commit();
}
});
secondColumn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.main_container_frame_layout, new SecondFragment());
transaction.commit();
}
});
}
}
Thank you in advance.

getSupportFragmentManager().popBackStack() will return back according to the stack. below code will help you.
#Override
public void onBackPressed() {
if(getSupportFragmentManager().getBackStackEntryCount() > 0) {
getSupportFragmentManager().popBackStack();
}else
super.onBackPressed();
}

Related

Why my new fragment can't subscribe otto

I have made a post in my activity, and it works well in the first fragment BlankFragment, however, when I tried to replace BlankFragment with BlackFragment2, and do the same subscribe, it can't subscribe anymore, here is the code.
MainActivity:
FragmentManager fragmentManager = getSupportFragmentManager();
fragmentManager.beginTransaction().add(R.id.fr1, new BlankFragment()).commit();
button = (Button)findViewById(R.id.btn);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
BusStation.getBus().post(new Message("hellworld"));
}
});
btn2 = (Button)findViewById(R.id.btn2);
btn2.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
FragmentManager fragmentManager1 = getSupportFragmentManager();
fragmentManager1.beginTransaction().replace(R.id.fr1, new BlankFragment2()).commit();
BusStation.getBus().post(new Message("zhengzhi zhou"));
}
});
}
BlankFragment and BlankFragment2 are using the same code:
#Override
public void onResume() {
super.onResume();BusStation.getBus().register(this);
}
#Override
public void onPause() {
super.onPause();
BusStation.getBus().unregister(this);
}
#Subscribe
public void receiveMsg(Message msg){
textView.setText(msg.getMsg());
}
Can anyone help me with this?
Use commitNow() instead Of commit()
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
// Replace the contents of the container with the new fragment
ft.replace(R.id.fragment_place, fragment);
// or ft.add(R.id.your_placeholder, new FooFragment());
// Complete the changes added above
ft.commitNow();

Android Move to previous fragment without reload

I have a HomeFragment and LoginFragment in the same Activity. At first it shows the HomeFragment and then go to LoginFragment. But when I back to HomeFragment it reloads the HomeFragment.
How to make the HomeFragment not reload when I press back from LoginFragment.
Thanks in advance. Here is my code :
MainActivity.java
private void setEvent() {
img_action_back.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
closeKeyboard(getApplication(), img_action_back.getWindowToken());
onBackPressed();
}
});
}
#Override
public void onBackPressed() {
if (fragment instanceof LoginFragment)
{
LoginFragment loginFragment = (LoginFragment)fragment;
if(loginFragment.fromDrawer)
Navigator.showHomeFragment(mContext);
else
finish();
}
}
}
Navigator.java
public static void showHomeFragment(Context context) {
final FragmentTransaction transaction =
getFragmentManager(context).beginTransaction();
transaction.replace(CONTAINER_ID, new HomeFragment());
transaction.commit();
}
public static void showLoginFragment(Context context,Boolean fromDrawer,String infoRegister) {
final FragmentTransaction transaction =
getFragmentManager(context).beginTransaction();
transaction.replace(CONTAINER_ID,
LoginFragment.newInstance(fromDrawer,infoRegister),"login");
transaction.commit();
}
Your issue is that you're recreating a new HomeFragment instance when you press back. You should instead pop the FragmentManager backstack.
#Override
public void onBackPressed() {
if (fragment instanceof LoginFragment) {
LoginFragment loginFragment = (LoginFragment)fragment;
if(loginFragment.fromDrawer) {
getFragmentManager(mContext).popBackStack();
} else {
finish();
}
}
}
You also need to make sure you add the LoginFragment to the backstack.
public static void showLoginFragment(Context context,Boolean fromDrawer,String infoRegister)
{
final FragmentTransaction transaction =
getFragmentManager(context).beginTransaction();
transaction.replace(CONTAINER_ID,
LoginFragment.newInstance(fromDrawer,infoRegister),"login");
transaction.addToBackStack(null);
transaction.commit();
}
#SunnySydeUp has a nice answer. I've found some improvement scope in your code.
You need to add the Fragment in the back stack so that the super.onBackPressed call won't recreate the Fragment again like the other answer says.
But as you're really worried about recreating Fragment you might initialize them once and use the instance again during transaction.
So in the onCreate function of your Activity initialize both of them first like this.
private HomeFragment mHomeFragment;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_layout);
mHomeFragment = new HomeFragment();
}
Now your onBackPressed may look like
#Override
public void onBackPressed() {
if (fragment instanceof LoginFragment) {
if(loginFragment.fromDrawer) {
super.onBackPressed();
} else {
finish();
}
}
}
And the Navigator.java
public static void showHomeFragment(Context context) {
final FragmentTransaction transaction =
getFragmentManager(context).beginTransaction();
transaction.replace(CONTAINER_ID, mHomeFragment);
transaction.commit();
}
public static void showLoginFragment(Context context,Boolean fromDrawer,String infoRegister) {
final FragmentTransaction transaction =
getFragmentManager(context).beginTransaction();
transaction.replace(CONTAINER_ID,
LoginFragment.newInstance(fromDrawer,infoRegister),"login");
transaction.addToBackStack(null).commit();
}

fragment created twice on orientation change

I know this question has been asked, but I haven't succeeded with the answers.
I have a fragment with a recycler view in it. I have a button which can show and hide this fragment. This all works fine until the orietation of the screen is changed. Then the fragment is recreated, and the one on top is shown and hidden, but there is one behind which stays there.
I understand I need to use
if (savedInstanceState == null)
somewhere, but cannot manage to succeed where. Thanks very much,
Here is my code.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_maps);
recyclerViewFragment = new RecyclerViewFragment();
FragmentTransaction trans = getSupportFragmentManager().beginTransaction();
trans.add(R.id.recycle_view_container, recyclerViewFragment, RECYCLER_FRAGMENT);
trans.commit();
trans.show(recyclerViewFragment);
Button showHideButton = (Button)findViewById(R.id.button_show_hide);
showHideButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
showHideFragment(recyclerViewFragment);
}
});
showHideButton.playSoundEffect(SoundEffectConstants.CLICK);
}
public void showHideFragment(final Fragment fragment){
FragmentTransaction trans = getSupportFragmentManager().beginTransaction();
trans.setCustomAnimations(android.R.anim.slide_in_left , android.R.anim.slide_out_right);
if (fragment.isHidden()) {
trans.show(fragment);
Log.d("hidden","Show");
} else {
trans.hide(fragment);
Log.d("Shown","Hide");
}
trans.commit();
}
Thanks very much guys!!!!!!!
I suggest make some changes to your code
I suppose that RECYCLER_FRAGMENT is a constant that contains a tag used to mark your fragment
RecyclerViewFragment recyclerViewFragment;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_maps);
if(savedInstanceState == null) {
recyclerViewFragment = new RecyclerViewFragment();
FragmentTransaction trans = getSupportFragmentManager().beginTransaction();
trans.add(R.id.recycle_view_container, recyclerViewFragment, RECYCLER_FRAGMENT);
trans.commit();
}else{
recyclerViewFragment = getSupportFragmentManager().findFragmentByTag(RECYCLER_FRAGMENT);
if(savedInstanceState.getString("vi").equals("hid")){
getSupportFragmentManager().beginTransaction().hide(recyclerViewFragment).commit();
}
}
Button showHideButton = (Button)findViewById(R.id.button_show_hide);
showHideButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
FragmentManager manager = getSupportFragmentManager();
if (fragment.isVisible()) {
manager.beginTransaction().hide(recyclerViewFragment).commit();
} else {
manager.beginTransaction().show(recyclerViewFragment).commit();
}
}
});
}
#Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
if(recyclerViewFragment.isVisible() == true){
outState.putString("vi","vis");
}else{
outState.putString("vi", "hid");
}
}
Instead of this:
trans.add(R.id.recycle_view_container, recyclerViewFragment, RECYCLER_FRAGMENT);
try this:
trans.replace(R.id.recycle_view_container, recyclerViewFragment, RECYCLER_FRAGMENT);
The name is misleading. Replace actually works as add also, if the first time. What is happening is that when your activity rotate, onCreate() is called again so you are adding the same fragment on top of the existing one

Android: activity does not work after backing from a fragment

i have an activity like WelcomeActivity and a fragment like GuideFragment.
i have a button in WelcomeActivity which cause a navigation to GuideFragment. Also i have a button in GuideFragment which navigates back to the WelcomeActivity.
For first time it goes to GuideFragment by clicking on the button and cames back to WelcomeActivity by pressing btn_back. Hwever after coming back to activity, the button does not work any more.
whats wrong with my code?
activity clas:
public class WelcomeActivity extends FragmentActivity
{
FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
GuideFragment guideFragment = new GuideFragment();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_welcome);
guideFragment = new GuideFragment();
}
public void onGuideClick(View view)
{
fragmentTransaction.replace(android.R.id.content, guideFragment);
fragmentTransaction.addToBackStack(null);
fragmentManager.popBackStack();
fragmentTransaction.commit();
}
}
and fragment class:
public class GuideFragment extends Fragment
{
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
// create ContextThemeWrapper from the original Activity Context with the custom theme
Context contextThemeWrapper = new ContextThemeWrapper(getActivity(), R.style.guideFrag);
// clone the inflater using the ContextThemeWrapper
LayoutInflater localInflater = inflater.cloneInContext(contextThemeWrapper);
// inflate the layout using the cloned inflater, not default inflater
View view = inflater.inflate(R.layout.fragment_guide, container, false);
Button button = (Button) view.findViewById(R.id.btn_back);
button.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
getActivity().getFragmentManager ().popBackStack();
}
});
return view;
}
}
Thanks
Remove fragmentManager.popBackStack(); from onGuideClick(View view). Also the transaction should not be a member field.
public void onGuideClick(View view) {
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(android.R.id.content, guideFragment);
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
}
You also initiate the GuideFragment twice, once is enough.
I changed WelcomeActivity like this:
public class WelcomeActivity extends FragmentActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_welcome);
}
public void onGuideClick(View view)
{
FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
GuideFragment guideFragment = new GuideFragment();
fragmentTransaction.replace(android.R.id.content, guideFragment);
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
}
}

How to implement saveFragmentInstanceState?

Could you anyone advice me how to implement saveFragmentInstanceState() or some other methods to retrieving fragment instance when back button is pressed. I use own stack for fragment, viz code bellow:
public class stackA extends ActivityInTab {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.i("StackA", "onCreate");
if(savedInstanceState == null){
navigateTo(new fragmentA());
}
}
}
Next there is implementation of ActivityInTab class. I think for this class must be implemented methods for saving and retrieving fragment state but still I can't find the way how to do this.
abstract class ActivityInTab extends FragmentActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_in_tab);
Log.i("ActivityInTab", "onCreate");
}
protected void navigateTo(Fragment newFragment) {
FragmentManager manager = getSupportFragmentManager();
FragmentTransaction ft = manager.beginTransaction();
ft.replace(R.id.content, newFragment);
ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
ft.addToBackStack(null);
ft.commit();
}
#Override
public void onBackPressed() {
Log.i("ActivityInTab", "onBackPressed");
FragmentManager manager = getSupportFragmentManager();
if (manager.getBackStackEntryCount() > 1) {
super.onBackPressed();
} else {
// Otherwise, ask user if he wants to leave :)
//showExitDialog();
super.onBackPressed();
}
}
}
And finally, this is imlementation of Fragments:
public class fragmentA extends Fragment {
private LinearLayout ll;
private FragmentActivity fa;
private String textViewText;
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
Log.i("Fragment A", "onCreateView");
fa = super.getActivity();
ll = (LinearLayout) inflater.inflate(R.layout.fragmenta, container,
false);
Button next = (Button) ll.findViewById(R.id.button1);
Button randomBtn = (Button) ll.findViewById(R.id.random_button);
final TextView randomText = (TextView) ll
.findViewById(R.id.random_textview);
next.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
((ActivityInTab) getActivity()).navigateTo(new
fragmentB());
}
});
randomBtn.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
// TODO Auto-generated method stub
randomText.setText(String.valueOf(Math.random()));
textViewText = randomText.getText().toString();
}
});
if (savedInstanceState != null) {
randomText.setText(savedInstanceState.getString("TextView"));
}
return ll;
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
// setRetainInstance(true);
}
#Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putString("TextView", textViewText);
}
}
I'm able to save instance state only for orientation changes using onSaveInstanceState(Bundle outState), but no for back button.
I would be very grateful for any advice, thanks.
In the onBackPressed Method you have access to the FragmentManager which can retrieve any fragment for you using the FragmentManager methods "findFragmentById" or "findFragmentByTag".
You can get direct access to any fragment whos state you want to save using either of those two methods depending on how you added the fragments.

Categories

Resources