Diálogo de entrada de texto Android

298

Cuando un usuario hace clic Buttonen a en mi aplicación (que está impreso en a SurfaceView), me gustaría Dialogque aparezca un texto y me gustaría almacenar el resultado en a String. Me gustaría que el texto se Dialogsuperponga a la pantalla actual. ¿Cómo puedo hacer esto?

Luke Taylor
fuente

Respuestas:

586

Suena como una buena oportunidad para usar un AlertDialog .

Tan básico como parece, Android no tiene un cuadro de diálogo incorporado para hacer esto (que yo sepa). Afortunadamente, es solo un pequeño trabajo adicional además de crear un AlertDialog estándar. Simplemente necesita crear un EditText para que el usuario ingrese datos y configurarlo como la vista del AlertDialog. Puede personalizar el tipo de entrada permitida usando setInputType , si lo necesita.

Si puede usar una variable miembro, simplemente puede establecer la variable en el valor de EditText, y persistirá después de que se haya cerrado el diálogo. Si no puede usar una variable miembro, es posible que necesite usar un escucha para enviar el valor de la cadena al lugar correcto. (Puedo editar y elaborar más si esto es lo que necesitas).

Dentro de tu clase:

private String m_Text = "";

Dentro de OnClickListener de su botón (o en una función llamada desde allí):

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();
Aaron
fuente
1
Tengo un hilo que constantemente actualiza y renderiza un objeto de pantalla, y llamo al método builder.show () dentro del método de actualización del objeto de pantalla.
Luke Taylor
1
Oh. Si está en un subproceso de trabajo, intente poner builder.show (); llame con runOnUiThread, similar a este ejemplo: stackoverflow.com/a/3134720/1098302 O tal vez sería mejor poner todo el código anterior (que crea el AlertDialog) en un método separado, y llamar a ese método desde runOnUiThread.
Aaron
2
Gracias. Eso es bueno. Howerver, hay un pequeño problema. Necesita declarar global Context, Context cont;y luego reemplazar "esto" en el cuadro de diálogo de alerta por cont. AlertDialog.Builder builder = nuevo AlertDialog.Builder (cont); entrada final de EditText = nuevo EditText (cont);
8
Creo que en lugar de crear una variable global para el contexto, puede pasar el contexto como: "MainActivity.this" (debe reemplazar el texto "MainActivity" con el nombre de la clase de actividad que desea usar).
kunal18
3
Vale la pena señalar que, como la mayoría de la interfaz de usuario de Android, todo esto es asíncrono ... lo que significa que no esperará a que el usuario toque OK a menos que tenga algo que haga que la puerta al siguiente paso ...
ewall
101

Agregaré a la respuesta de @ Aaron con un enfoque que le brinda la oportunidad de diseñar el cuadro de diálogo de una mejor manera. Aquí hay un ejemplo ajustado:

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();

Aquí está el diseño de ejemplo utilizado para crear el cuadro de diálogo 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>

El resultado final:

Ejemplo de diálogo Editar texto

Michal
fuente
10
Excelente solución! Acabo de cambiar getView()con findViewById(android.R.id.content)y todo funcionó como encanto. Muchas gracias por compartir :)
Atul
¡Recuerda lanzar ese findViewById con (ViewGroup)!
Martin Erlic
2
"Element AutoCompleteTextView no está permitido aquí ..."
Jaroslav Záruba
1
@JPerk: android.R.id.content le brinda el elemento raíz de una vista. Consulte esto por favor: stackoverflow.com/a/12887919/1911652
Atul
1
Solo me pregunto, pero ¿cuál es el valor de @dimen/content_padding_normal?
Edric
62

¿Qué tal este EJEMPLO ? Parece sencillo.

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
fuente
3
Más o menos lo mismo que Aaron, pero encadena al constructor. Asunto de preferencia personal ya que ambos funcionan bien.
Scott Biggs
12

Si quieres un poco de espacio en lefty rightde la inputvista, se puede añadir un poco de relleno como

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>

Espero que ayude

Phan Van Linh
fuente
¿Qué es resources?
Sebastian Palma el
5

Lo encontré más limpio y más reutilizable para extender AlertDialog.Builderpara crear una clase de diálogo personalizada. Esto es para un diálogo que le pide al usuario que ingrese un número de teléfono. También se puede proporcionar un número de teléfono preestablecido llamando setNumber()antes de llamar 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>

Uso:

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();
Magnus W
fuente
4

@LukeTaylor: Actualmente tengo la misma tarea a mano (crear una ventana emergente / diálogo que contiene un EditText).
Personalmente, encuentro que la ruta completamente dinámica es algo limitante en términos de creatividad.

DISEÑO DE DIÁLOGO TOTALMENTE PERSONALIZADO: en

lugar de confiar completamente en el Código para crear el Diálogo, puede personalizarlo por completo de la siguiente manera:

1) - Cree un nuevo Layout Resourcearchivo ... ¡Esto actuará como su Diálogo, permitiendo una libertad creativa total!
NOTA: Consulte las pautas de diseño de materiales para ayudar a mantener las cosas limpias y en punto.

2) - Proporcione ID a todos sus Viewelementos. En mi código de ejemplo a continuación, tengo 1 EditTexty 2 Buttons.

3) - Crear un Activitycon unButton, con fines de prueba ... Lo haremos inflar y lanzar su diálogo!

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
}


Pedazo de pastel! ¡Libertad creativa completa! Solo asegúrese de seguir las pautas de material;)

¡Espero que esto ayude a alguien! Déjame saber lo que ustedes piensan!

Studio2bDesigns
fuente
2
Por curiosidad, ¿por qué el voto negativo (-1)? La lógica que proporcioné funciona exactamente como se esperaba y como se describe. Sentí que era una buena adición a esta publicación que aún no se había mencionado, y es una solución alternativa perfectamente sólida. Sin embargo , si tiene un motivo legítimo para rechazar la información que proporcioné, sería un poco más útil si pudiera proporcionar un contexto de por qué lo hizo, para que yo y otros puedan aprender y comprender el razonamiento. Los votos negativos pueden ser muy útil y útil en el proceso de aprendizaje, pero solo cuando hay un contexto detrás de por qué.
Studio2bDesigns
4

Es trabajo para mi

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();
    }

¿Como llamar? (Nombre de la actividad actual)

showForgotDialog (current_activity_name.this);

Abdullah Pariyani
fuente