Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Saving and restoring EditText cursor position in a DialogFragment using savedInstanceState

Tags:

android

Most of what I read says that you should call onSaveInstanceState() on your DialogFragment to save its state and then call onActivityCreated() and restore the state there. While this works, I found a problem:

If I have an EditText in my custom layout of my DialogFragment AlertDialog and lets say I type in my password in it. The password is masked and cursor is blinking after the last password character I have entered. If I save value entered in EditText in onSaveInstanceState() and restore state using onActivityCreated(), it is restored but the cursor is moved to the beginning of what I just typed in before rotation instead of staying at the end.

However, if I restore what I saved using onCreateDialog() by checking my savedInstanceState for null first, then my cursor stays at the end after the last character typed in which is what it should be.

I wonder which way is correct although I see both working fine and retaining the password on rotation change. It is the only that one little think that the cursor moves to the beginning instead of staying at the end in the case of onActivityCreated().

like image 658
pixel Avatar asked Jul 02 '15 20:07

pixel


1 Answers

The EditText widget automatically saves and restores its own state. You don't need to save and restore the entered string. Let the widget handle its own state and the cursor position will not change after restart.

Here's an example:

public class PasswordDialog extends DialogFragment {
    private static final String TAG = "PasswordDialog";
    private static final String TITLE_KEY = "title";
    private String mTitle;

    public static PasswordDialog newInstance(String title) {
        PasswordDialog f = new PasswordDialog();
        Bundle args = new Bundle();
        args.putString(TITLE_KEY, title);
        f.setArguments(args);
        return f;
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (savedInstanceState==null) {
            //not restart
            Bundle args = getArguments();
            if (args==null) {
                throw new IllegalArgumentException("Bundle args required");
            }
            mTitle = args.getString(TITLE_KEY);
        } else {
            //restart
            mTitle = savedInstanceState.getString(TITLE_KEY);
        }
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putString(TITLE_KEY, mTitle);
    }

    @Override
    @NonNull
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        Log.i(TAG, "onCreateDialog()");

        AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());

        LayoutInflater inflater = getActivity().getLayoutInflater();
        View customView = inflater.inflate(R.layout.fragment_dialog_note_edit, null);

        final EditText passwordView = (EditText) customView.findViewById(R.id.dialog_note_edit_text);

        builder
                .setTitle(mTitle)
                .setView(customView)
                .setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int whichButton) {
                        //nothing
                    }
                })
                .setPositiveButton("Save", new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int whichButton) {
                        String password = passwordView.getText().toString();
                        Log.i(TAG, "password= " + password);
                    }
                });

        return builder.create();
    }
}
like image 166
Bob Snyder Avatar answered Sep 29 '22 14:09

Bob Snyder