Synthetix
Synthetix

Reputation: 2135

Can't change EditText margins programmatically inside AlertDialog

I have an AlertDialog in my app that contains an EditText field. This dialog needs to be generated programmatically and should match the way the EditTextPreference dialog looks that is displayed automatically by Android when a user edits text by touching an EditTextPreference. This all works, but the size of the EditText inserted programmatically is too wide and doesn't match the one displayed by the EditTextPreference when touched. The following two images show the problem.

EditText looks like this when added to the AlertDialog using setView():

EditText looks like this when added to the AlertDialog using setView()

But should look like this:

Should look like this

Here is the XML code in the XML responsible for the EditTextPreference:

<EditTextPreference
            android:title="Enter Name"
            android:key="name"
            android:defaultValue=""
            android:summary=""
            android:inputType="textCapSentences|textMultiLine"
            android:singleLine="false"
            android:gravity="top|left"
            android:lines="2"
            android:minLines="1"
            android:maxLines="2"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:scrollbars="vertical"
            />

And the Java code responsible for my dialog:

AlertDialog.Builder alertDialog = new AlertDialog.Builder(mainActivity);
alertDialog.setTitle("Enter Date");

final EditText input = new EditText(mainActivity);
LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,LinearLayout.LayoutParams.WRAP_CONTENT);
input.setLayoutParams(lp);
input.setGravity(android.view.Gravity.TOP|android.view.Gravity.LEFT);
input.setInputType(InputType.TYPE_TEXT_FLAG_CAP_SENTENCES|InputType.TYPE_TEXT_FLAG_MULTI_LINE);
input.setLines(1);
input.setMaxLines(1);
input.setText(lastDateValue);
alertDialog.setView(input);

Upvotes: 10

Views: 6983

Answers (5)

Torkel Velure
Torkel Velure

Reputation: 1326

Building on @LeonardoSibela answer, I made this simple function in kotlin to show a dialog with an edittext and a callback.

    private fun showEditDialog(title: String, preFill: String, onSubmit: (text: String) -> Unit) {
        val editText = EditText(requireContext()).apply {
            setText(preFill)
        }
        val viewContainer = LinearLayout(requireContext()).apply {
            orientation = LinearLayout.VERTICAL
            val lp = LinearLayout.LayoutParams(
                LinearLayout.LayoutParams.MATCH_PARENT,
                LinearLayout.LayoutParams.MATCH_PARENT
            ).apply {
                setMargins(16.dp, 0, 16.dp, 0)
            }
            addView(editText, lp)
        }
        MaterialAlertDialogBuilder(requireContext())
            .setView(viewContainer)
            .setTitle(title)
            .setPositiveButton("Ok") { _, _ -> onSubmit(editText.text.toString()) }
            .setNegativeButton("Cancel") { _, _ -> }
            .show()
    }

And you could use it like this:

showEditDialog("Change name", "") { name ->
   viewModel.updateName(name)
}

Upvotes: 0

notes-jj
notes-jj

Reputation: 1557

Create an Android XML with the needed and formatted Elements. Inflate the XML/view and add view to dialog button.

This way the UI design and the code is cleaner separated. The Android XML Editor with preview makes it easier to get the wanted optical results.

The Example uses Databinding and so the XML/View is addressed via Databinding DialogEditTextBinding.inflate([...]) and the result is accessed via databinding dialogBinding.editText.getText().toString().

Java Code in Fragment/Activity

final DialogEditTextBinding dialogBinding = DialogEditTextBinding.inflate(getLayoutInflater());

AlertDialog.Builder alertDialog = new AlertDialog.Builder(mainActivity);
alertDialog.setTitle("Enter Date");

alertDialog.setView(dialogBinding);

alertDialog.setPositiveButton("OK",
    (dialog, whichButton) -> {
        String editText = dialogBinding.editText.getText().toString();
        doSomething(editText);
    });

Android XML for Dialog extra Elements

dialog_edit_text.xml:

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        >

        <EditText
            android:id="@+id/edit_text"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginStart="22dp"
            android:layout_marginEnd="22dp"
            android:textSize="12sp"
            />

    </LinearLayout>
</layout>

PS

PS: The example is combined out of my code and your code, so it may contain errors.

Upvotes: 0

Ansshkki
Ansshkki

Reputation: 848

You can do this without extra container layout, only add this to your alertDialog :

alertDialog.setOnShowListener(dialog -> {
    ViewGroup.MarginLayoutParams p = (ViewGroup.MarginLayoutParams) editText.getLayoutParams();
    p.setMargins(50, 20, 50, 20); // You can change the margins for your need
    editText.requestLayout();
});

Upvotes: 0

Leonardo Sibela
Leonardo Sibela

Reputation: 2189

You have to add a container before doing that, e.g LinearLayout

AlertDialog.Builder alertDialog = new AlertDialog.Builder(mainActivity);
alertDialog.setTitle("Enter Date");

LinearLayout container = new LinearLayout(this);
container.setOrientation(LinearLayout.VERTICAL);
LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,LinearLayout.LayoutParams.WRAP_CONTENT);
lp.setMargins(left, top, right, bottom);
final EditText input = new EditText(mainActivity);
input.setLayoutParams(lp);
input.setGravity(android.view.Gravity.TOP|android.view.Gravity.LEFT);
input.setInputType(InputType.TYPE_TEXT_FLAG_CAP_SENTENCES|InputType.TYPE_TEXT_FLAG_MULTI_LINE);
input.setLines(1);
input.setMaxLines(1);
input.setText(lastDateValue);
container.addView(input, lp);

alertDialog.setView(container);

I hope it helps :)

Upvotes: 28

piyush poriya
piyush poriya

Reputation: 316

AlertDialog.Builder alertDialog = new AlertDialog.Builder(mainActivity);
alertDialog.setTitle("Enter Date");

final EditText input = new EditText(mainActivity);
LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,LinearLayout.LayoutParams.WRAP_CONTENT);
lp.setMargins(left, top, right, bottom);
input.setLayoutParams(lp);
input.setGravity(android.view.Gravity.TOP|android.view.Gravity.LEFT);
input.setInputType(InputType.TYPE_TEXT_FLAG_CAP_SENTENCES|InputType.TYPE_TEXT_FLAG_MULTI_LINE);
input.setLines(1);
input.setMaxLines(1);
input.setText(lastDateValue);
alertDialog.setView(input);

Please change your code as above and provide desire all margins

Upvotes: 0

Related Questions