Wprowadź tekstowe okno dialogowe Androida

298

Gdy użytkownik kliknie ikonę Buttonw mojej aplikacji (która jest wydrukowana jako a SurfaceView), chciałbym, Dialogaby pojawił się tekst i chciałbym zapisać wynik w String. Chciałbym, aby tekst Dialognakładał się na bieżący ekran. W jaki sposób mogę to zrobić?

Luke Taylor
źródło

Odpowiedzi:

585

Brzmi jak dobra okazja do użycia AlertDialog .

Tak proste, jak się wydaje, Android nie ma wbudowanego okna dialogowego, aby to zrobić (o ile mi wiadomo). Na szczęście jest to tylko trochę dodatkowej pracy nad stworzeniem standardowego AlertDialog. Musisz tylko utworzyć tekst EditText, aby użytkownik mógł wprowadzać dane, i ustawić go jako widok AlertDialog. W razie potrzeby można dostosować dozwolony typ danych wejściowych za pomocą setInputType .

Jeśli możesz użyć zmiennej członkowskiej, możesz po prostu ustawić zmienną na wartość EditText i będzie ona utrzymywać się po zamknięciu okna dialogowego. Jeśli nie możesz użyć zmiennej członka, być może będziesz musiał użyć detektora, aby wysłać wartość ciągu we właściwe miejsce. (Mogę edytować i opracowywać więcej, jeśli tego właśnie potrzebujesz).

W twojej klasie:

private String m_Text = "";

W OnClickListener twojego przycisku (lub w funkcji wywoływanej stamtąd):

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
źródło
1
Mam wątek, który stale aktualizuje i renderuje obiekt ekranowy, i wywołuję metodę builder.show () w ramach metody aktualizacji obiektu ekranowego.
Luke Taylor
1
O. Jeśli korzystasz z wątku roboczego, spróbuj umieścić builder.show (); Wywołaj za pomocą runOnUiThread, podobnie jak w tym przykładzie: stackoverflow.com/a/3134720/1098302 A może lepiej byłoby umieścić cały kod powyżej (który tworzy AlertDialog) w osobnej metodzie i wywołać tę metodę z poziomu runOnUiThread.
Aaron
2
Dziękuję Ci. Dobre. Jednak jest mały problem. Musisz zadeklarować, global Context, Context cont;a następnie zastąpić „to” w alertdialog przez cont. AlertDialog.Builder builder = new AlertDialog.Builder (cd); final EditText input = new EditText (cd);
8
Myślę, że zamiast tworzyć zmienną globalną dla kontekstu, możesz przekazać kontekst, taki jak: „MainActivity.this” (musisz zastąpić tekst „MainActivity” nazwą klasy aktywności, której chcesz użyć).
kunal18
3
Być może warto zauważyć, że podobnie jak większość interfejsu użytkownika Androida, wszystko to jest asynchroniczne ... co oznacza, że ​​nie będzie czekać, aż użytkownik
kliknie
101

Dodam do odpowiedzi @ Aarona podejście, które daje możliwość lepszego stylizowania okna dialogowego. Oto dostosowany przykład:

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

Oto przykładowy układ użyty do utworzenia okna dialogowego 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>

Wynik końcowy:

Przykład okna dialogowego EditText

Michał
źródło
10
Doskonałe rozwiązanie! Ja po prostu zastąpione getView()ze findViewById(android.R.id.content)i to wszystko działało jak uroku. Wielkie dzięki za udostępnienie :)
Atul
Pamiętaj, aby rzucić to findViewById za pomocą (ViewGroup)!
Martin Erlic
2
„Element AutoCompleteTextView nie jest tutaj dozwolony ...”
Jaroslav Záruba 14.04.17
1
@JPerk: android.R.id.content daje element główny widoku. Proszę odnieść się do tego: stackoverflow.com/a/12887919/1911652
Atul
1
Zastanawiam się, ale jaka jest wartość @dimen/content_padding_normal?
Edric
62

Co powiesz na ten PRZYKŁAD ? Wydaje się to proste.

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
źródło
3
Prawie tak samo jak Aarona, ale łączy budowniczego. Sprawa osobistych preferencji, ponieważ oba działają dobrze.
Scott Biggs,
12

Jeśli chcesz trochę miejsca na lefti rightod inputwidoku można dodać trochę jak wyściółka

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>

Mam nadzieję, że to pomoże

Phan Van Linh
źródło
Co jest resources?
Sebastian Palma
5

Zauważyłem, że rozszerzenie jest bardziej przejrzyste i wielokrotnego użytku, AlertDialog.Builderaby utworzyć niestandardową klasę okna dialogowego. To jest okno dialogowe z prośbą o podanie numeru telefonu. Zaprogramowany numer telefonu można również podać, dzwoniąc setNumber()przed nawiązaniem połączenia 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>

Stosowanie:

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.
źródło
4

@LukeTaylor: Obecnie mam pod ręką to samo zadanie (tworzenie wyskakującego okienka / okna dialogowego zawierającego tekst edycji).
Osobiście uważam, że w pełni dynamiczna droga jest nieco ograniczająca pod względem kreatywności.

W PEŁNI NIESTANDARDOWY LAYOUT DIALOGU:

Zamiast polegać wyłącznie na Code do tworzenia Dialogu, możesz go w pełni dostosować w następujący sposób:

1) - Utwórz nowy Layout Resourceplik. Będzie to działać jako Twój Dialog, pozwalając na pełną swobodę twórczą!
UWAGA: Zapoznaj się z wytycznymi dotyczącymi projektowania materiałów, aby pomóc utrzymać porządek w czystości.

2) - Podaj identyfikatory wszystkim swoim Viewelementom. W poniższym przykładowym kodzie mam 1 EditTexti 2 Buttons.

3) - Utwórz za ActivitypomocąButton, do celów testowych. Będziemy go napompować i uruchomić Twój Dialog!

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
}


Bułka z masłem! Pełna swoboda twórcza! Pamiętaj tylko o przestrzeganiu Materiałowych Wytycznych;)

Mam nadzieję, że to komuś pomoże! Daj mi znać, co myślicie!

Studio2bDesigns
źródło
2
Ciekawe, dlaczego głosowanie (-1)? Przedstawiona przeze mnie logika działa dokładnie zgodnie z przeznaczeniem i zgodnie z opisem. Czułem, że był to dobry dodatek do tego postu, o którym jeszcze nie wspomniano, i jest idealnie solidnym rozwiązaniem alternatywnym.Jednakże , jeśli mają uzasadnione powody downvoting te informacje okażą byłoby nieco bardziej pomocne, gdyby mógł Pan podać jakiś kontekst, dlaczego to zrobiłeś, więc ja i inni mogą nauczyć się i zrozumieć rozumowanie .. Downvotes rzeczywistości może być bardzo przydatne i pomocne w procesie uczenia się - ale tylko wtedy, gdy za kontekstem kryje się przyczyna.
Studio2bDesigns
4

To dla mnie praca

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

Jak zadzwonić? (Nazwa bieżącej działalności)

showForgotDialog (current_activity_name.this);

Abdullah Pariyani
źródło