Cosimo Sguanci
Cosimo Sguanci

Reputation: 1291

Adding Ok/Cancel buttons to DialogFragment

I have a dialog Fragment and i would like to put the ok/cancel buttons in the bottom of the dialog. I tried but the only thing i got was the buttons over the edit text (that is in the DialogFragment). Thisi is my dialog: enter image description here

And this is my dialog code:

public class dialogNewFile extends DialogFragment {
private EditText textNewFile;

public dialogNewFile(){}

public static dialogNewFile newIstance(String title){
    dialogNewFile frag=new dialogNewFile();
    Bundle args=new Bundle();
    args.putString("title",title);
    frag.setArguments(args);
    return frag;
}


@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedIstanceState ){
    return inflater.inflate(R.layout.fragment_newfile,container);
}

@Override
public void onViewCreated(View view, @Nullable Bundle savedIstanceState){
    super.onViewCreated(view, savedIstanceState);
    textNewFile=(EditText) view.findViewById(R.id.edit_text_newfile);
    String title=getArguments().getString("title","Enter name");
    getDialog().setTitle(title);
    textNewFile.requestFocus();
    getDialog().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE);
}

@Override
public void onResume() {
    Window window = getDialog().getWindow();
    Point size = new Point();
    // Store dimensions of the screen in `size`
    Display display = window.getWindowManager().getDefaultDisplay();
    display.getSize(size);
    // Set the width of the dialog proportional to 75% of the screen width
    window.setLayout((int) (size.x * 0.75), (int) (size.x * 0.50));
    window.setGravity(Gravity.CENTER);
    // Call super onResume after sizing
    super.onResume();

}

this is the layout of the dialog fragment:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
android:id="@+id/dialogNewFile">

<EditText
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:padding="35dp"
    android:hint="@string/hint_new_file"
    android:inputType="text"
    android:id="@+id/edit_text_newfile"/>

</LinearLayout>

Upvotes: 4

Views: 7425

Answers (3)

ar34z
ar34z

Reputation: 2669

I've found a solution for this years ago, but I can't access the repository anymore, so had to invent the wheel again.

I wanted DialogFragment with lifecycle access in order to observe a LiveData object (via viewLifeCyclerOwner). Databinding is used in the layout. An AlertDialog is used because I also wanted the Ok / Cancel buttons to give it a native behaviour.

The class is cleaned up a bit.

class AddDiscountCodeDialog : DialogFragment(), DialogInterface.OnShowListener {
    private lateinit var binding: DialogAddDiscountCodeBinding
    private lateinit var handler: AddDiscountCodeHandler

    // Full screen dialogs are ugly
    override fun onResume() {
        super.onResume()

        val params = dialog?.window?.attributes
        params?.width = WindowManager.LayoutParams.MATCH_PARENT
        params?.height = WindowManager.LayoutParams.WRAP_CONTENT
        dialog?.window?.attributes = params as WindowManager.LayoutParams
    }

    // Override this method to initialize viewLifecycleOwner
    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        return binding.root
    }

    // Create a custom dialog.
    // Binding class is instantiated here because we need to set the view
    override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
        binding = DialogAddDiscountCodeBinding.inflate(layoutInflater)

        val alert = AlertDialog.Builder(requireContext())
                .setTitle("Title")
                .setPositiveButton("Ok Button", null)
                .setNegativeButton("Cancel", null)
                .setView(binding.root)
                .create()
                .also {
                    it.setOnShowListener(this)
                    it.setCanceledOnTouchOutside(false)
                }

        return alert
    }

    // Overwrite the positive button click so it won't dismiss when clicked
    override fun onShow(dialog: DialogInterface?) {
        val button: Button = (dialog as AlertDialog).getButton(AlertDialog.BUTTON_POSITIVE)
        button.setOnClickListener {
            setLoading(true)

            val code = binding.code
            handler.addDiscountCode(code.toString()).observe(viewLifecycleOwner, Observer { result ->
                setLoading(false)

                // ... removed code

                dismiss()
            })
        }
    }

    // Set loading state in the layout. Blocks the "Positive" button to avoid multiple API calls.
    private fun setLoading(loading: Boolean) {
        val button: Button? = (dialog as? AlertDialog)?.getButton(AlertDialog.BUTTON_POSITIVE)

        button?.isEnabled = !loading
        button?.alpha = if (loading) 0.5f else 1.0f
        binding.loading = loading
    }

    companion object {
        val TAG = AddDiscountCodeDialog::class.java.simpleName

        fun create(handler: AddDiscountCodeHandler): AddDiscountCodeDialog {
            return AddDiscountCodeDialog().also {
                it.handler = handler
            }
        }
    }
}

Upvotes: 0

Aung Myo Linn
Aung Myo Linn

Reputation: 2890

You shall override onCreateDialog and use AlertDialog.Builder to set the Positive and Negative buttons something like below:

@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
    String title = getArguments().getString("title");
    AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
    builder.setTitle(title);
    builder.setMessage("Are you sure?");

    // Edited: Overriding onCreateView is not necessary in your case
    LayoutInflater inflater = LayoutInflater.from(getContext());
    View newFileView = inflater.inflate(R.layout.fragment_newfile, null);
    builder.setView(newFileView);

    builder.setPositiveButton("OK",  new DialogInterface.OnClickListener() {
        @Override
        public void onClick(DialogInterface dialog, int which) {
            // on success
        }
    });
    builder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
        @Override
        public void onClick(DialogInterface dialog, int which) {
            dialog.dismiss();
        }
    });

    return builder.create();
}

Upvotes: 6

ugur
ugur

Reputation: 3654

If you wanna use custom dialog view, use alertdialog.setView method

       AlertDialog.Builder builder = new AlertDialog.Builder(this); 
       View myview = alertDialog.getLayoutInflater().inflate(R.layout.custom_dialog_layout, null);
       final AlertDialog alertDialog = builder.create();
       builder.setView(myview);
       alertDialog .show();

For the clicks events.

Button positiveButton = myview.findViewById(R.id.btnPositive);
positiveButton.setOnclickListener(new OnClickListener .....

Upvotes: 0

Related Questions