简体   繁体   中英

Returning Data from a Dialog Fragment to the Activity that Called It

Hey fellow stackoverflowers!!!

I'm wondering what the best way to pass a string taken from a Dialog Fragment based on user input on the Dialog into the main activity which called the string?

Here's my specific example but it's really long so if you don't feel like going through it don't worry about everything below.

Here's my source code, I've ommitted the imports n stuff

public class GroupNameFragment extends AppCompatDialogFragment {

    private EditText edittGroupName;

    public static String GROUP_NAME = "com.example.mashu.walkinggroup.controller - groupName";

    // When the views are inflated, get access to them
    @Override
    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
        edittGroupName = Objects.requireNonNull(getView()).findViewById(R.id.edittGroupName);
    }

    @NonNull
    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {

        // Get reference to fragment's layout
        View view = LayoutInflater.from(getActivity())
                .inflate(R.layout.group_name_layout, null);

        // OK button listener
        DialogInterface.OnClickListener listener = (dialog, which) -> {
            if (which == DialogInterface.BUTTON_POSITIVE) {
                // If OK pressed, create bundle to be accessed in OnDismissListener in MapActivity,
                // which contains the groupName user inputted
                String groupName = edittGroupName.getText().toString();
                Bundle bundle = new Bundle();
                bundle.putString(GROUP_NAME, groupName);
                setArguments(bundle);
            }
        };

        // Build alert dialog
        return new AlertDialog.Builder(getActivity())
                .setTitle("Choose your Group Name!")
                .setView(view)
                .setPositiveButton(android.R.string.ok, listener)
                .create();

    }

    // Extracts groupName from the bundle set up in the onClickListener above
    public static String getGroupName(GroupNameFragment dialog) {
        Bundle bundle = getArguments();
        return bundle.getString(GROUP_NAME);
    }
}

What I attempted to do was to this: First, I get access to the EditText that the user will type in their response. Then I set the Dialog Listener for the OK button which creates a bundle using the setArguments function which contains the groupName when the user is done, which will be accessed in the other activity later on by using the static getGroupName function. Here's the function in the main activity which creates the Dialog and sets the onDismissListener

private void createGroupNameDialog() {
    // Instantiate Dialog
    // Support Fragment Manager for backwards compatibility
    FragmentManager manager = getSupportFragmentManager();
    GroupNameFragment dialog = new GroupNameFragment();
    dialog.show(manager, "GroupNameDialog");

    // OnDismissListener callback function to be run whenever dialog dismissed.
    dialog.getDialog().setOnDismissListener(new DialogInterface.OnDismissListener() {
        @Override
        public void onDismiss(DialogInterface dialogInterface) {

            // Update groupName based on what user inputted and update marker name at origin
            groupName = GroupNameFragment.getGroupName(dialog);
            originMarker.setTitle(groupName);

        }
    });
}

I think the problem is in groupName = GroupNameFragment.getGroupName(dialog). I feel like theres a better way to get the bundle here, and it seems weird to use the function as static and then pass in specific instance of GroupNameFragment in order to get the bundle (wouldn't that instance be gone by then since it's being used in the "OnDismiss"?). Also, the app crashes the second createGroupNameDialog is called, but it doesn't crash and actually opens the dialog window if I comment out the OnDismissListener, so I'm sure the problems in there somewhere but I don't know why it crashes before the dialog box even opens since OnDismiss happens AFTER the user dismisses the Dialog Box.

Thanks!!!

I accomplished passing variables back using an interface and listeners. I'll show you how I handled it (although I used a DialogFragment, this should still work for AlertDialogs, and in this example I passed an integer, not a string, but it would work for any data type).

public class DialogFragmentOtherMedia extends DialogFragment {

    int dialogResult;

    //The interface is important!
    public interface YesNoListener {
        void onYesOtherMedia(int output);

        void onNoOtherMedia(int output);
    }

    //Checking for ClassCastException is nice here.
    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        if (!(activity instanceof YesNoListener)) {
            throw new ClassCastException(activity.toString() + " must implement     YesNoListener");
        }
    }

    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        dialogResult = 0;

        final String mediaType[] = {getString(R.string.Ringtones),getString(R.string.Music),getString(R.string.Alarms)};


        return new AlertDialog.Builder(getActivity())
                .setTitle(getString(R.string.Select_Other_Media_Type))
                .setSingleChoiceItems(mediaType, dialogResult, new DialogInterface.OnClickListener() {

                    @Override
                    public void onClick(DialogInterface dialog, int which) {

                        //Log.d("DialogFragmentOtherMedia.onCreateDialog","Item clicked: " + mediaType[which]);

                        dialogResult = which;
                    }
                })
                .setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {

                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        //Casting the activity to YesNoListener is very important here!  
                        //You'll register the listener in the activity later, by implementing the interface.
                        ((YesNoListener) getActivity()).onYesOtherMedia(dialogResult);
                    }
                })
                .setNegativeButton(android.R.string.no, new DialogInterface.OnClickListener() {

                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        //Same thing for your other callbacks.
                        ((YesNoListener) getActivity()).onNoOtherMedia(dialogResult);
                    }
                })
                .create();
    }
}

Then you just need to implement it in your activity where you called the dialog from:

public class AlarmDetailsActivity extends Activity
    DialogFragmentOtherMedia.YesNoListener {

    //All of your activity stuff here...

    @Override
    public void onYesOtherMedia(int result) {
        Log.i("Tag", "onYes Result: " + result);
    }

    @Override
    public void onNoOtherMedia(int result) {
        Log.i("Tag", "onNo Result: " + result);

    }



}

Sorry about all of the random strings and extra alert dialog. I just wanted to show some actual working code from my app. I tried to add comments next to the important stuff. Hope this helps!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM