Ввод текстового диалога Android

298

Когда пользователь нажимает a Buttonв моем приложении (которое напечатано в a SurfaceView), я хотел бы, чтобы появился текст, Dialogи я хотел бы сохранить результат в String. Я бы хотел, чтобы текст Dialogперекрывал текущий экран. Как я могу это сделать?

Люк Тейлор
источник

Ответы:

586

Похоже, хорошая возможность использовать AlertDialog .

Как ни странно, в Android нет встроенного диалога для этого (насколько я знаю). К счастью, это просто небольшая дополнительная работа над созданием стандартного AlertDialog. Вам просто нужно создать EditText, чтобы пользователь мог вводить данные, и установить его как представление AlertDialog. При необходимости вы можете настроить разрешенный тип ввода, используя setInputType .

Если вы можете использовать переменную-член, вы можете просто установить для переменной значение EditText, и оно сохранится после закрытия диалогового окна. Если вы не можете использовать переменную-член, вам может понадобиться прослушиватель для отправки строкового значения в нужное место. (Я могу редактировать и уточнять больше, если это то, что вам нужно).

В вашем классе:

private String m_Text = "";

В OnClickListener вашей кнопки (или в функции, вызываемой оттуда):

AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("Title");

// Set up the input
final EditText input = new EditText(this);
// Specify the type of input expected; this, for example, sets the input as a password, and will mask the text
input.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD);
builder.setView(input);

// Set up the buttons
builder.setPositiveButton("OK", new DialogInterface.OnClickListener() { 
    @Override
    public void onClick(DialogInterface dialog, int which) {
        m_Text = input.getText().toString();
    }
});
builder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
    @Override
    public void onClick(DialogInterface dialog, int which) {
        dialog.cancel();
    }
});

builder.show();
Аарон
источник
1
У меня есть поток, который постоянно обновляет и отображает экранный объект, и я вызываю метод builder.show () в методе обновления экранного объекта.
Люк Тейлор
1
Ой. Если вы работаете с потоком, попробуйте положить builder.show (); вызовите с runOnUiThread, как в этом примере: stackoverflow.com/a/3134720/1098302 Или, может быть, было бы лучше поместить весь код выше (который создает AlertDialog) в отдельный метод, и вызвать этот метод изнутри runOnUiThread.
Аарон
2
Спасибо. Это хорошо. Но есть небольшая проблема. Надо объявить global Context, Context cont;и заменить, заменить "это" в алертиалдиалог на cont. AlertDialog.Builder builder = новый AlertDialog.Builder (продолжение); окончательный ввод EditText = новый EditText (продолжение);
8
Я думаю, что вместо создания глобальной переменной для контекста, вы можете передать контекст следующим образом: «MainActivity.this» (вам нужно заменить текст «MainActivity» именем класса активности, которое вы хотите использовать).
kunal18
3
Стоит отметить, что, как и в большинстве Android-интерфейсов, все это асинхронно ... это означает, что пользователь не будет ждать
нажатия кнопки
101

Я добавлю к ответу @ Аарона подход, который даст вам возможность лучше оформить диалоговое окно. Вот скорректированный пример:

AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
builder.setTitle("Title");
// I'm using fragment here so I'm using getView() to provide ViewGroup
// but you can provide here any other instance of ViewGroup from your Fragment / Activity
View viewInflated = LayoutInflater.from(getContext()).inflate(R.layout.text_inpu_password, (ViewGroup) getView(), false);
// Set up the input
final EditText input = (EditText) viewInflated.findViewById(R.id.input);
// Specify the type of input expected; this, for example, sets the input as a password, and will mask the text
builder.setView(viewInflated);

// Set up the buttons
builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
    @Override
    public void onClick(DialogInterface dialog, int which) {
        dialog.dismiss();
        m_Text = input.getText().toString();
    }   
}); 
builder.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
    @Override
    public void onClick(DialogInterface dialog, int which) {
        dialog.cancel();
    }   
}); 

builder.show();

Вот пример макета, использованного для создания диалога EditText:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:padding="@dimen/content_padding_normal">

    <android.support.design.widget.TextInputLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <AutoCompleteTextView
            android:id="@+id/input"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:hint="@string/hint_password"
            android:imeOptions="actionDone"
            android:inputType="textPassword" />

    </android.support.design.widget.TextInputLayout>
</FrameLayout>

Конечный результат:

Пример диалога EditText

Michal
источник
10
Отличное решение! Я просто заменить getView()с , findViewById(android.R.id.content)и это все работало как шарм. Большое спасибо за то, что поделились :)
Atul
Не забудьте привести этот findViewById к (ViewGroup)!
Мартин Эрлик
2
«Элемент AutoCompleteTextView здесь не разрешен ...»
Ярослав
1
@JPerk: android.R.id.content дает вам корневой элемент представления.
Атул,
1
Просто интересно, а в чем ценность @dimen/content_padding_normal?
Эдрик
62

Как насчет этого ПРИМЕРА ? Это кажется простым.

final EditText txtUrl = new EditText(this);

// Set the default text to a link of the Queen
txtUrl.setHint("http://www.librarising.com/astrology/celebs/images2/QR/queenelizabethii.jpg");

new AlertDialog.Builder(this)
  .setTitle("Moustachify Link")
  .setMessage("Paste in the link of an image to moustachify!")
  .setView(txtUrl)
  .setPositiveButton("Moustachify", new DialogInterface.OnClickListener() {
    public void onClick(DialogInterface dialog, int whichButton) {
      String url = txtUrl.getText().toString();
      moustachify(null, url);
    }
  })
  .setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
    public void onClick(DialogInterface dialog, int whichButton) {
    }
  })
  .show(); 
bhekman
источник
3
Почти так же, как у Аарона, но цепляет строителя. Дело личных предпочтений, так как оба работают нормально.
Скотт Биггс
12

Если вы хотите , чтобы некоторые места в leftи rightиз точки inputзрения, вы можете добавить некоторое дополнение , как

private fun showAlertWithTextInputLayout(context: Context) {
    val textInputLayout = TextInputLayout(context)
    textInputLayout.setPadding(
        resources.getDimensionPixelOffset(R.dimen.dp_19), // if you look at android alert_dialog.xml, you will see the message textview have margin 14dp and padding 5dp. This is the reason why I use 19 here
        0,
        resources.getDimensionPixelOffset(R.dimen.dp_19),
        0
    )
    val input = EditText(context)
    textInputLayout.hint = "Email"
    textInputLayout.addView(input)

    val alert = AlertDialog.Builder(context)
        .setTitle("Reset Password")
        .setView(textInputLayout)
        .setMessage("Please enter your email address")
        .setPositiveButton("Submit") { dialog, _ ->
            // do some thing with input.text
            dialog.cancel()
        }
        .setNegativeButton("Cancel") { dialog, _ ->
            dialog.cancel()
        }.create()

    alert.show()
}

dimens.xml

<dimen name="dp_19">19dp</dimen>

Надеюсь, это поможет

Фан Ван Линь
источник
Что resources?
Себастьян Пальма
5

Я нашел его более понятным и более пригодным для повторного использования AlertDialog.Builderдля создания собственного диалогового класса. Это для диалога, который просит пользователя ввести номер телефона. Предварительно установленный номер телефона также можно получить, позвонив setNumber()до звонка show().

InputSenderDialog.java

public class InputSenderDialog extends AlertDialog.Builder {

    public interface InputSenderDialogListener{
        public abstract void onOK(String number);
        public abstract void onCancel(String number);
    }

    private EditText mNumberEdit;

    public InputSenderDialog(Activity activity, final InputSenderDialogListener listener) {
        super( new ContextThemeWrapper(activity, R.style.AppTheme) );

        @SuppressLint("InflateParams") // It's OK to use NULL in an AlertDialog it seems...
        View dialogLayout = LayoutInflater.from(activity).inflate(R.layout.dialog_input_sender_number, null);
        setView(dialogLayout);

        mNumberEdit = dialogLayout.findViewById(R.id.numberEdit);

        setPositiveButton("OK", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int id) {
                if( listener != null )
                    listener.onOK(String.valueOf(mNumberEdit.getText()));

            }
        });

        setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int id) {
                if( listener != null )
                    listener.onCancel(String.valueOf(mNumberEdit.getText()));
            }
        });
    }

    public InputSenderDialog setNumber(String number){
        mNumberEdit.setText( number );
        return this;
    }

    @Override
    public AlertDialog show() {
        AlertDialog dialog = super.show();
        Window window = dialog.getWindow();
        if( window != null )
            window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);
        return dialog;
    }
}

dialog_input_sender_number.xml

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:padding="10dp">

    <TextView
        android:id="@+id/title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        android:paddingBottom="20dp"
        android:text="Input phone number"
        android:textAppearance="@style/TextAppearance.AppCompat.Large" />

    <TextView
        android:id="@+id/numberLabel"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintTop_toBottomOf="@+id/title"
        app:layout_constraintLeft_toLeftOf="parent"
        android:text="Phone number" />

    <EditText
        android:id="@+id/numberEdit"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:layout_constraintTop_toBottomOf="@+id/numberLabel"
        app:layout_constraintLeft_toLeftOf="parent"
        android:inputType="phone" >
        <requestFocus />
    </EditText>

</android.support.constraint.ConstraintLayout>

Использование:

new InputSenderDialog(getActivity(), new InputSenderDialog.InputSenderDialogListener() {
    @Override
    public void onOK(final String number) {
        Log.d(TAG, "The user tapped OK, number is "+number);
    }

    @Override
    public void onCancel(String number) {
        Log.d(TAG, "The user tapped Cancel, number is "+number);
    }
}).setNumber(someNumberVariable).show();
Магнус W
источник
4

@LukeTaylor: У меня сейчас такая же задача (создание всплывающего окна / диалогового окна, содержащего EditText).
Лично я считаю, что полностью динамический маршрут несколько ограничивает креативность.

ПОЛНОСТЬЮ ПОЛЬЗОВАТЕЛЬСКОЕ РАСПОЛОЖЕНИЕ ДИАЛОГА:

Вместо того, чтобы полностью полагаться на Код для создания Диалога, вы можете полностью настроить его следующим образом:

1) - Создайте новый Layout Resourceфайл. Он будет действовать как ваш Диалог, предоставляя полную свободу творчества!
ПРИМЕЧАНИЕ. См. Рекомендации по проектированию материалов, чтобы обеспечить чистоту и актуальность.

2) - Дайте идентификаторы всем вашим Viewэлементам. В приведенном ниже примере кода у меня есть 1 EditTextи 2 Buttons.

3) Создайте Activityс собойButton, для целей тестирования .. Мы сделаем так, чтобы он раздулся и запустил ваш диалог!

public void buttonClick_DialogTest(View view) {

    AlertDialog.Builder mBuilder = new AlertDialog.Builder(MainActivity.this);

    //  Inflate the Layout Resource file you created in Step 1
    View mView = getLayoutInflater().inflate(R.layout.timer_dialog_layout, null);

    //  Get View elements from Layout file. Be sure to include inflated view name (mView)
    final EditText mTimerMinutes = (EditText) mView.findViewById(R.id.etTimerValue);
    Button mTimerOk = (Button) mView.findViewById(R.id.btnTimerOk);
    Button mTimerCancel = (Button) mView.findViewById(R.id.btnTimerCancel);

    //  Create the AlertDialog using everything we needed from above
    mBuilder.setView(mView);
    final AlertDialog timerDialog = mBuilder.create();

    //  Set Listener for the OK Button
    mTimerOk.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick (View view) {
            if (!mTimerMinutes.getText().toString().isEmpty()) {
                Toast.makeText(MainActivity.this, "You entered a Value!,", Toast.LENGTH_LONG).show();
            } else {
                Toast.makeText(MainActivity.this, "Please enter a Value!", Toast.LENGTH_LONG).show();
            }
        }
    });

    //  Set Listener for the CANCEL Button
    mTimerCancel.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick (View view) {
            timerDialog.dismiss();
        }
    });

    //  Finally, SHOW your Dialog!
    timerDialog.show();


    //  END OF buttonClick_DialogTest
}


Кусок пирога! Полная творческая свобода! Просто неукоснительно следуйте Руководству по материалам;)

Надеюсь, это кому-нибудь поможет! Дайте мне знать, что вы, ребята, думаете!

Studio2bDesigns
источник
2
Просто любопытно, почему (-1) понизить? Предоставленная мною логика работает точно так, как задумано и как описано ... Я чувствовал, что это хорошее дополнение к этому посту, которое еще не было упомянуто, и является совершенно разумным альтернативным решением. Однако , если у вас есть законная причина для опровержения предоставленной мною информации, было бы немного полезнее, если бы вы предоставили некоторый контекст для того, почему вы это сделали, чтобы я и другие могли узнать и понять аргументацию. полезно и полезно в процессе обучения - но только тогда, когда за этим стоит контекст.
Studio2bDesigns
4

Это работа для меня

private void showForgotDialog(Context c) {
        final EditText taskEditText = new EditText(c);
        AlertDialog dialog = new AlertDialog.Builder(c)
                .setTitle("Forgot Password")
                .setMessage("Enter your mobile number?")
                .setView(taskEditText)
                .setPositiveButton("Reset", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        String task = String.valueOf(taskEditText.getText());
                    }
                })
                .setNegativeButton("Cancel", null)
                .create();
        dialog.show();
    }

Как позвонить? (Название текущей деятельности)

showForgotDialog (current_activity_name.this);

Абдулла Парияни
источник