Finestra di dialogo per l'immissione di testo Android


298

Quando un utente fa clic su a Buttonnella mia app (che è stampata in a SurfaceView), vorrei che Dialogcomparisse un testo e vorrei archiviare il risultato in a String. Vorrei che il testo si Dialogsovrapponesse alla schermata corrente. Come posso fare questo?

Risposte:


586

Sembra una buona opportunità per usare un AlertDialog .

Per quanto possa sembrare semplice, Android non ha una finestra di dialogo integrata per farlo (per quanto ne so). Fortunatamente, è solo un piccolo lavoro extra per la creazione di un AlertDialog standard. Devi semplicemente creare un EditText affinché l'utente possa inserire i dati e impostarlo come vista di AlertDialog. È possibile personalizzare il tipo di input consentito utilizzando setInputType , se necessario.

Se sei in grado di utilizzare una variabile membro, puoi semplicemente impostare la variabile sul valore di EditText, e persisterà dopo che la finestra di dialogo è stata chiusa. Se non è possibile utilizzare una variabile membro, potrebbe essere necessario utilizzare un listener per inviare il valore della stringa nel posto giusto. (Posso modificare ed elaborare di più se questo è quello che ti serve).

All'interno della tua classe:

private String m_Text = "";

All'interno di OnClickListener del tuo pulsante (o in una funzione chiamata da lì):

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
Ho un thread che aggiorna e rende costantemente un oggetto schermo e chiamo il metodo builder.show () all'interno del metodo di aggiornamento dell'oggetto schermo.
Luke Taylor,

1
Oh. Se sei su un thread di lavoro, prova a mettere builder.show (); chiama con runOnUiThread, simile a questo esempio: stackoverflow.com/a/3134720/1098302 O forse sarebbe meglio mettere tutto il codice sopra (che crea AlertDialog) in un metodo separato e chiamarlo da runOnUiThread.
Aaron,

2
Grazie. Quello è buono. Howerver, c'è un piccolo problema. È necessario dichiarare global Context, Context cont;e quindi sostituire "this" in alertdialog con cont. AlertDialog.Builder builder = new AlertDialog.Builder (cont); input EditText finale = new EditText (cont);

8
Penso che invece di creare una variabile globale per il contesto, è possibile passare il contesto come: "MainActivity.this" (è necessario sostituire il testo "MainActivity" con il nome della classe di attività che si desidera utilizzare).
kunal18,

3
Vale la pena notare che, come la maggior parte dell'interfaccia utente di Android, questa è tutta asincrona ... il che significa che non aspetterà che l'utente tocchi OK a meno che tu non abbia qualcosa che
faccia da

101

Aggiungerò alla risposta di @ Aaron con un approccio che ti dà l'opportunità di dare uno stile migliore alla finestra di dialogo. Ecco un esempio adattato:

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

Ecco il layout di esempio utilizzato per creare la finestra di dialogo 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>

Il risultato finale:

Esempio di finestra di dialogo EditText


10
Soluzione superba! Ho appena sostituito getView()con findViewById(android.R.id.content)e tutto ha funzionato come fascino. Grazie mille per la condivisione :)
Atul,

Ricorda di lanciare quel findViewById con (ViewGroup)!
Martin Erlic,

2
"Element AutoCompleteTextView non è consentito qui ..."
Jaroslav Záruba

1
@JPerk: android.R.id.content ti dà l'elemento radice di una vista. Fare riferimento per favore: stackoverflow.com/a/12887919/1911652
Atul

1
Mi chiedo solo, ma qual è il valore di @dimen/content_padding_normal?
Edric,

62

Che ne dici di questo ESEMPIO ? Sembra semplice.

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

3
Praticamente uguale a quello di Aaron, ma incatena il costruttore. Questione di preferenze personali poiché entrambe funzionano bene.
Scott Biggs,

12

Se vuoi un po 'di spazio a lefte rightdi inputvista, puoi aggiungere un po' di riempimento come

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>

Spero che sia d'aiuto


Cosa resources?
Sebastian Palma

5

L'ho trovato più pulito e riutilizzabile da estendere AlertDialog.Builderper creare una classe di dialogo personalizzata. Questo è per una finestra di dialogo che chiede all'utente di inserire un numero di telefono. Un numero di telefono preimpostato può anche essere fornito chiamando setNumber()prima di chiamareshow() .

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

4

@LukeTaylor: Al momento ho lo stesso compito a portata di mano (creazione di un popup / finestra di dialogo che contiene un EditText) ..
Personalmente, trovo che il percorso completamente dinamico sia in qualche modo limitante in termini di creatività.

LAYOUT DIALOGO COMPLETAMENTE PERSONALIZZATO:

anziché fare affidamento interamente sul codice per creare la finestra di dialogo, è possibile personalizzarlo completamente in questo modo:

1) - Creare un nuovo Layout Resourcefile .. Questo fungerà da finestra di dialogo, consentendo la massima libertà creativa!
NOTA: fare riferimento alle linee guida per la progettazione dei materiali per aiutare a mantenere le cose pulite e puntuali.

2) - Fornisci ID a tutti i tuoi Viewelementi. Nel mio codice di esempio qui sotto, ho 1 EditTexte 2 Buttons.

3) - Crea un Activitycon aButton, a scopo di test .. Lo faremo gonfiare e avvieremo il tuo dialogo!

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
}


Pezzo di torta! Piena libertà creativa! Basta essere sicuri di seguire le linee guida sui materiali;)

Spero che questo aiuti qualcuno! Fatemi sapere cosa pensate voi ragazzi!


2
Solo curioso perché il (-1) downvote? La logica che ho fornito funziona esattamente come previsto e come descritto .. Ho pensato che fosse una buona aggiunta a questo post che non era ancora stato menzionato ed è una soluzione alternativa perfettamente valida. Tuttavia , se hai un motivo legittimo per il downgrade delle informazioni che ho fornito, sarebbe leggermente più utile se potessi per favore fornire un contesto per il motivo per cui l'hai fatto, quindi io e altri possiamo imparare e comprendere il ragionamento. I downgrade possono effettivamente essere molto utile e utile nel processo di apprendimento, ma solo quando c'è un contesto dietro il perché.
Studio2bDesigns

4

Per me è un lavoro

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

Come chiamare? (Nome attività corrente)

showForgotDialog (current_activity_name.this);

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.