Boîte de dialogue de saisie de texte Android


298

Lorsqu'un utilisateur clique sur a Buttondans mon application (qui est imprimée sur a SurfaceView), j'aimerais qu'un texte Dialogapparaisse et je voudrais stocker le résultat dans a String. J'aimerais que le texte Dialogrecouvre l'écran actuel. Comment puis-je faire ceci?

Réponses:


586

Cela ressemble à une bonne occasion d'utiliser un AlertDialog .

Aussi basique que cela puisse paraître, Android n'a pas de boîte de dialogue intégrée pour ce faire (pour autant que je sache). Heureusement, c'est juste un peu de travail supplémentaire en plus de créer un AlertDialog standard. Il vous suffit de créer un EditText pour que l'utilisateur puisse saisir des données et de le définir comme la vue du AlertDialog. Vous pouvez personnaliser le type d'entrée autorisé à l'aide de setInputType , si vous en avez besoin.

Si vous pouvez utiliser une variable membre, vous pouvez simplement définir la variable sur la valeur de EditText, et elle persistera après la fermeture de la boîte de dialogue. Si vous ne pouvez pas utiliser une variable membre, vous devrez peut-être utiliser un écouteur pour envoyer la valeur de chaîne au bon endroit. (Je peux éditer et élaborer plus si c'est ce dont vous avez besoin).

Au sein de votre classe:

private String m_Text = "";

Dans le OnClickListener de votre bouton (ou dans une fonction appelée à partir de 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
J'ai un fil qui met constamment à jour et rend un objet écran, et j'appelle la méthode builder.show () dans la méthode de mise à jour de l'objet écran.
Luke Taylor

1
Oh. Si vous êtes sur un thread de travail, essayez de mettre builder.show (); appelez avec runOnUiThread, similaire à cet exemple: stackoverflow.com/a/3134720/1098302 Ou peut-être qu'il serait préférable de mettre tout le code ci-dessus (qui crée le AlertDialog) dans une méthode distincte, et d'appeler cette méthode à partir de runOnUiThread.
Aaron

2
Je vous remercie. C'est bon. Cependant, il y a un petit problème. Besoin de déclarer global Context, Context cont;puis de remplacer "this" dans alertdialog par cont. Builder AlertDialog.Builder = nouveau AlertDialog.Builder (suite); entrée EditText finale = nouveau EditText (suite);

8
Je pense qu'au lieu de créer une variable globale pour le contexte, vous pouvez passer le contexte comme: "MainActivity.this" (vous devez remplacer le texte "MainActivity" par le nom de la classe d'activité que vous souhaitez utiliser).
kunal18

3
Peut-être vaut-il la peine de noter que, comme la plupart des interfaces utilisateur Android, tout est asynchrone ... ce qui signifie qu'il n'attendra pas que l'utilisateur
appuie

101

J'ajouterai à la réponse de @ Aaron avec une approche qui vous donne la possibilité de mieux styliser la boîte de dialogue. Voici un exemple ajusté:

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

Voici l'exemple de disposition utilisé pour créer la boîte de dialogue 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>

Le résultat final:

Exemple de boîte de dialogue EditText


10
Superbe solution! Je viens de remplacer getView()par findViewById(android.R.id.content)et tout a fonctionné comme un charme. Merci beaucoup pour le partage :)
Atul

N'oubliez pas de lancer ce findViewById avec (ViewGroup)!
Martin Erlic

2
"L'élément AutoCompleteTextView n'est pas autorisé ici ..."
Jaroslav Záruba

1
@JPerk: android.R.id.content vous donne l'élément racine d'une vue. Veuillez vous référer à ceci: stackoverflow.com/a/12887919/1911652
Atul

1
Je me demande, mais quelle est la valeur de @dimen/content_padding_normal?
Edric

62

Que diriez-vous de cet EXEMPLE ? Cela semble simple.

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
À peu près la même chose qu'Aaron, mais enchaîne le constructeur. Question de préférence personnelle car les deux fonctionnent bien.
Scott Biggs du

12

Si vous voulez un peu d' espace à leftet rightde inputvue, vous pouvez ajouter un peu de rembourrage comme

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>

J'espère que ça aide


Quoi resources?
Sebastian Palma

5

Je l'ai trouvé plus propre et plus réutilisable à étendre AlertDialog.Builderpour créer une classe de dialogue personnalisée. Il s'agit d'une boîte de dialogue qui demande à l'utilisateur de saisir un numéro de téléphone. Un numéro de téléphone prédéfini peut également être fourni en appelant setNumber()avant d'appelershow() .

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>

Usage:

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: J'ai actuellement la même tâche à accomplir (créer une fenêtre contextuelle / boîte de dialogue contenant un EditText).
Personnellement, je trouve que la route entièrement dynamique est quelque peu limitative en termes de créativité.

DISPOSITION DE DIALOGUE ENTIÈREMENT PERSONNALISÉE:

Plutôt que de compter entièrement sur le code pour créer la boîte de dialogue, vous pouvez le personnaliser entièrement comme ceci:

1) - Créez un nouveau Layout Resourcefichier .. Cela agira comme votre boîte de dialogue, permettant une liberté de création totale!
REMARQUE: Référez-vous aux directives de conception des matériaux pour aider à garder les choses propres et précises.

2) - Donnez des identifiants à tous vos Viewéléments. Dans mon exemple de code ci-dessous, j'ai 1 EditTextet 2 Buttons.

3) - Créez un Activityavec unButton, à des fins de test .. Nous allons le faire gonfler et lancer votre boîte de dialogue!

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
}


Part de gâteau! Pleine liberté créative! Assurez-vous simplement de suivre les directives sur le matériel;)

J'espère que cela aide quelqu'un! Dites-moi ce que vous en pensez!


2
Juste curieux de savoir pourquoi (-1) downvote? La logique que j'ai fournie fonctionne exactement comme prévu et comme décrit .. J'ai senti que c'était un bon ajout à ce poste qui n'avait pas encore été mentionné, et c'est une solution alternative parfaitement saine. Cependant , si vous avez une raison légitime de voter contre les informations que j'ai fournies, il serait légèrement plus utile de fournir un contexte pour expliquer pourquoi vous l'avez fait, afin que moi-même et les autres puissions apprendre et comprendre le raisonnement. Les votes négatifs peuvent en fait être très utile et utile dans le processus d'apprentissage - mais seulement quand il y a un contexte derrière pourquoi.
Studio2bDesigns

4

C'est du travail pour moi

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

Comment appeler? (Nom de l'activité actuelle)

showForgotDialog (current_activity_name.this);

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.