Search code examples
javaandroidandroid-studioandroid-fragmentsandroid-alertdialog

Android's AlertDialog in fragment


I have an app that uses tabbed activity, with 3 tabs, each with a separate fragment and layout. Tab3 has some user-profile settings, like a name for example. Name is displayed inside a cardview, so I made that cardview clickable, and onClick it would open an alertDialog with an edit text to enter the name. to build this dialog I found 2 methods.

First:- (this is run once the cardview is clicked(On clicklistener)) and its working very well and I have no issues with it but it just doesn't feel like a best-practice

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

                alert.setTitle("Enter your Username");

                LayoutInflater inflater = getActivity().getLayoutInflater();
                View view1 = inflater.inflate(R.layout.editname_layout, null);
                alert.setView(view1);
                final EditText input = view1.findViewById(R.id.editname);
                alert.setPositiveButton("Save", new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int whichButton) {

                        textView.setText(input.getText().toString());
                    }
                });

                alert.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int whichButton) {
                        // Canceled.
                    }
                });

                alert.show();

Second:- is that I build a separate DialogFragment with an interface to send data back to fragment this one feels like a best practice but i have faced many issues with it, such as.. when data is sent back to my fragment, I can't use the method "textView.setText" on the received data as I receive it outside the onCreateView method and thus textView always returns null.

public class Dialog extends AppCompatDialogFragment {
    
    private Context context;
    public DialogListener listener;

    public Dialog(Context context) {
        this.context = context;
    }

    @NonNull
    @Override
    public android.app.Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
        AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
        
            LayoutInflater inflater = getActivity().getLayoutInflater();
            View view = inflater.inflate(R.layout.name_layout, null);
            final EditText name = (EditText) view.findViewById(R.id.editname);
            builder.setView(view)
                    .setTitle("Username")
                    .setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialogInterface, int i) {

                        }
                    })
                    .setPositiveButton("Save", new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialogInterface, int i) {
                            String text = name.getText().toString();
                            listener.data(text);
                            Toast.makeText(getActivity(), "Saved", Toast.LENGTH_SHORT).show();
                        }
                    });
        
      
         return builder.create();
    }

    @Override
    public void onAttach(@NonNull Context context) {
        super.onAttach(context);

        try {
            Fragment fragment = new Tab3();
            listener = (DialogListener) fragment;
        }
        catch (ClassCastException e) {
            throw new ClassCastException(context.toString() + " must implement d.l");
        }
    }



    public interface DialogListener {
        void data(String name);
    }
}

So what I'm thinking is that I should go with the first method as it's easier, and it's easier to extract text from it but still not sure if it would be a good practice.

thanks in advance!


Solution

  • Prefer second solution:

    1. You can have your custom UI elements.
    2. You have access to lifecycle changes (onResume,onCreate,etc.).
    3. It keeps showing even when orientation is changed (the first solution doesn't).

    And for sending data to previous fragment you can create listener to fragment.

    interface MyFragmentListener {
        fun onSendBackData(data: Any)
    }
    
    class MyFragment:Fragment {
        private var listener: MyFragmentListener? = null
        
        override fun onAttach(context: Context) {
            super.onAttach(context)
            listener = when {
                context is MyFragmentListener -> context
                parentFragment is MyFragmentListener -> parentFragment as MyFragmentListener
                else -> error("You should implement MyFragmentListener")
    
            }
        }
    
        override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
            super.onViewCreated(view, savedInstanceState)
            button.setOnClickListener {
                listener?.onSendBackData("Data")
            }
        }
    }
    
    class Activity : Activity(), MyFragmentListener {
    
       override fun onSendBackData(data:Any) {
          textView.text = data.toString()
       }
    }