Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android: FragmentTransaction hide doesn't work for DialogFragment

I'm trying to add a

fragmentTransaction.hide(myDialogFragment);
fragmentTransaction.addToBackStack(null);

to a FragmentTransaction so that the dialog will re-appear when the user hits the back button, but it's not working. I originally overrode onCreateDialog in my DialogFragment, but I noticed that the documentation for the hide call on FragmentTransaction states:

This is only relevant for fragments whose views have been added to a container.

So instead, now I'm overriding onCreateView. Now it sort of hides, but not really. The dialog merely shrivels, but the window still remains dark. I have to hit the back button to get rid of it, which is not the behavior I want, obviously. What am I missing here?

like image 886
Christopher Perry Avatar asked Dec 13 '22 05:12

Christopher Perry


1 Answers

A DialogFragment maintains a dialog internally and calls show and hide methods on it according to its own lifecycle. Calling FragmentTransaction.hide() just tries to set the visibility of the fragment's view, as returned by Fragment.onCreateView(), to View.GONE. The view of the DialogFragment is coincidently the view used for its internal dialog, and so what you are doing is hiding the content on the dialog. Unfortunately, hiding the view does not 'dismiss' the dialog and so the screen will still be dimmed.

When you call DialogFragment.show(FragmentTransaction,String), a FragmentTransaction is created to add it to the FragmentManager. Ordinarily, showing the dialog is considered the 'active' transaction, and then dismissing it is just popping the back stack the appropriate number of times. If you did not add any other fragments in between, then a new FragmentTransaction is created with a remove operation. If we could access this, then we could just add a backstack entry and make this operation reversible. Unfortunately, this is not possible and so the best we can do is just to make our own dismiss method (and hope the internal state does not get too screwed up):

public class UndoDialogFragmentActivity extends FragmentActivity {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        Button button = (Button) findViewById(R.id.button);
        button.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                // show a dialog fragment in the normal way
                new MyDialogFragment().show(getSupportFragmentManager(), "dialog");
            }
        });
    }

    private static class MyDialogFragment extends DialogFragment {
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setStyle(STYLE_NO_TITLE, getTheme());
            // do not allow back button to dismiss dialog; confusing behaviour otherwise!
            setCancelable(false);
        }

        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
            Button button = new Button(getActivity());
            button.setText("Dismiss");
            button.setOnClickListener(new OnClickListener() {
                @Override
                public void onClick(View v) {
                    // pressing back after 'dismissing' the dialog will cause it to be added again
                    getFragmentManager().beginTransaction().remove(MyDialogFragment.this).addToBackStack(null).commit();
                }
            });

            return button;
        }
    }
}

Clicking on the button in the fragment will cause a DialogFragment to be opened, with its own dismiss button. After pressing dismiss, you can show the dialog again by pressing the back key, undoing the remove operation. This produces somewhat questionable behaviour when you allow the back key to both show and hide the dialog, but the details can be decided by you according to your application.

like image 141
antonyt Avatar answered May 08 '23 13:05

antonyt