Mam więc coś, co wydaje się być częstym problemem, a mianowicie tym, że tekst edycji w moim oknie dialogowym nie pojawia się, gdy jest aktywny. Widziałem kilka obejść, takich jak w tym wątku , tym i tym (i wielu innych), ale nigdy nie widziałem satysfakcjonującego wyjaśnienia, dlaczego tak się dzieje.
Wolałbym, aby Android używał własnego domyślnego zachowania dla EditTexts, niż budował własne, ale wydaje się, że wszyscy (w tych wątkach) zaakceptowali, że domyślnym zachowaniem dla EditTexts w oknach dialogowych jest po prostu podanie kursora bez klawiatury. Dlaczego miałoby to być?
Tak na marginesie, żadne z tych obejść nie wydaje się działać dla mnie - najbliższe, jakie udało mi się osiągnąć, to wymuszenie pojawienia się klawiatury pod oknem dialogowym (za pomocą InputMethodManager.toggleSoftKeyboard (*)). Moja konkretna konfiguracja to API15, EditText pojawia się w stopce w ListView w ramach AlertDialog. EditText android: aktywowana = „true” jest ustawiona, a onFocusChangeListener jest odbieranie zdarzeń ostrości.
Edytować:
Zgodnie z prośbą, oto konkretny fragment kodu, z którym pracuję. Nie będę zawracał sobie głowy całym układem, ale w tej konkretnej aplikacji EditText pojawia się w odpowiedzi na naciśnięcie przycisku w oknie dialogowym (podobnie jak w widoku akcji ). Jest zawarty w RelativeLayout, który domyślnie ma widoczność „zniknęła”:
<RelativeLayout
android:id="@+id/relLay"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:visibility="gone"
android:layout_marginTop="5dp"
android:layout_marginBottom="5dp">
<ImageButton
android:id="@+id/cancelBut"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:background="@color/transparent"
android:src="@drawable/cancelButton"
android:layout_margin="5dp"/>
<ImageButton
android:id="@+id/okBut"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toLeftOf="@id/cancelBut"
android:background="@color/transparent"
android:src="@drawable/okButton"
android:layout_margin="5dp" />
<EditText
android:id="@+id/editText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="text"
android:focusable="true"
android:layout_toLeftOf="@id/okBut"/>
</RelativeLayout>
Kod, który to tworzy, ustawia widoczność RelativeLayout na „Visible” (i ukrywa inne elementy UI). To powinno wystarczyć, aby podnieść klawiaturę, gdy EditText zostanie skupiony, na podstawie moich doświadczeń z EditText. Jednak z jakiegoś powodu tak nie jest. Mogę ustawić następującą wartość onFocusChangeListener:
edit_text.setOnFocusChangeListener(new OnFocusChangeListener() {
@Override
public void onFocusChange(View v, boolean hasFocus) {
// For whatever reason we need to request a soft keyboard.
InputMethodManager imm = (InputMethodManager)dlg.getWindow().getContext().getSystemService(_Context.INPUT_METHOD_SERVICE);
if(hasFocus)
imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0);
Log.v("DialogProblem", "Focus requested, " + (hasFocus?"has focus.":"doesn't have focus."));
}
}
});
Korzystając z tej konfiguracji, kiedy po raz pierwszy wprowadzam EditText, onFocusChangedListener wyzwala i generuje dziennik, który niezmiennie wygląda następująco:
Focus requested, has focus.
Focus requested, doesn't have focus.
Focus requested, has focus.
Klawiatura pojawia się, a następnie znika, prawdopodobnie dlatego, że przełączam ją dwa razy, ale nawet gdy upewnię się, że pozostaje podniesiona, znajduje się za oknem dialogowym (w szarym obszarze) i nie ma sposobu, aby się do niej dostać bez zamykania okna .
To powiedziawszy, chciałbym podkreślić, że chociaż mogę sprawić, że to obejście zadziała, przede wszystkim jestem zainteresowany znalezieniem prostego powodu, dla którego EditText nie jest wyzwalany w pierwszej kolejności i dlaczego to wydaje się być tak powszechne!
Odpowiedzi:
OK, więc po dużym przeczytaniu zorientowałem się, dlaczego jest to problem i nie potrzebuję żadnych obejść.
Wydaje się, że problem (przynajmniej w moim przypadku) polega na tym, że skoro miejsce, w którym wpisujesz tekst jest początkowo ukryte (lub zagnieżdżone lub coś w tym rodzaju), AlertDialog automatycznie ustawia flagę WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM (lub jakaś kombinacja tego i WindowManager .LayoutParams.FLAG_NOT_FOCUSABLE), aby rzeczy nie powodowały pojawienia się miękkich danych wejściowych.
Sposób, w jaki znalazłem rozwiązanie tego problemu, polega na dodaniu następującego wiersza po utworzeniu okna dialogowego:
dialog.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE|WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
Gdy to zrobisz, EditText zachowuje się jak normalny EditText, bez zbędnych zmian ani obejść.
źródło
clearFlags()
późniejshow()
, dzięki @AlexanderFragotsisMam ten sam problem we własnej aplikacji. Jeśli tworzysz dla poziomu API> = 8, możesz użyć tego fragmentu:
dialog.setOnShowListener(new OnShowListener() { @Override public void onShow(DialogInterface dialog) { InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); imm.showSoftInput(textEdit, InputMethodManager.SHOW_IMPLICIT); } });
Nie znalazłem rozwiązania dla niższych poziomów API ...
BTW: ten fragment kodu nie zawsze działa na emulatorze. Nie wiem dlaczego.
źródło
AlertDialog dialog = builder.create();
przed idialog.show();
po powyższym, jeśli używasz AlertDialog.BuilderJeśli przeczytasz dokumentację AlertDialog, znajdziesz tam:
Miałem problem, o którym wspomniałeś z EditText w ListView w oknie dialogowym. Naprawiłem to, zastępując niestandardową klasę widoku (w moim przypadku ListView) moim własnym FocusableListView, z nadpisaniem tylko jednej metody:
public class FocusableListView extends ListView { public FocusableListView(Context context) { super(context); } public FocusableListView(Context context, AttributeSet attrs) { super(context, attrs); } public FocusableListView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } @Override public boolean onCheckIsTextEditor() { // this is where the magic happens return true; } }
Następnie używam go w pliku układu jako:
<?xml version="1.0" encoding="UTF-8"?> <com.myexample.wiget.FocusableListView xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:descendantFocusability="beforeDescendants" android:layout_height="wrap_content" />
Możesz nadpisać RelativeLayout w swoim przypadku w ten sam sposób i powinno działać.
źródło
To właśnie zadziałało dla mnie. Utwórz AlertDialog.Builder, ustaw tytuł, pozytywnyButton, negatywnyButton. Po wykonaniu tej czynności:
AlertDialog dialog = builder.create(); dialog.getWindow().clearFlags( WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE |WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM); dialog.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE); dialog.show(); editText.requestFocus();
Nie musisz używać
builder.show();
.źródło
Powyższy kod jest bardzo pomocny. Ale musisz wywołać metodę "show" po metodzie "create" (nie wiem dlaczego, ale działa to tylko w moim oknie dialogowym z EditText w ListView). W metodzie onCreateDialog:
@Override protected Dialog onCreateDialog(int id) { switch (id) { case YOUR_DIALOG_ID: { //... AlertDialog a = new AlertDialog.Builder(this)./* ... set the properties here */ .create(); a.show(); //!!! this is very important to call the "show" method a.getWindow().clearFlags( WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM); return a; } //... } return null; }
źródło
Dziękuję Ci! Mam osadzony TextEdit w ostatnim wierszu ListView osadzony we fragmencie okna dialogowego alertu. Użyłem twojego rozwiązania usuwania flag jako postu, który można uruchomić i teraz działa idealnie.
@Override public Dialog onCreateDialog(Bundle savedInstanceState) { AlertDialog.Builder builder = new AlertDialog.Builder(getContext()); builder.setTitle("My Title"); m_adapter = new MyAdapter(getContext()); builder.setAdapter(m_adapter, new OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { // TODO Auto-generated method stub } }); final AlertDialog dialog = builder.create(); final ListView listView = dialog.getListView(); listView.setOnItemClickListener(new OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { } }); listView.post(new Runnable() { @Override public void run() { dialog.getWindow().clearFlags( WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM); } }); return dialog; }
źródło
Oto jeden sposób, aby to zrobić:
final Window dialogWindow = dialog.getWindow(); dialogWindow.clearFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM); dialogWindow.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);
źródło
Chciałbym dodać do odpowiedzi Paula i komentarza Aleksandra .
Sam mam okno dialogowe, które zostało utworzone w
onCreateDialog()
metodzie, które (wydaje się) wymaga zwróceniadialog.show();
, dlatego nie możesz dodać parametrów układu do okna dialogowego, w którym zostało utworzone okno dialogowe. Aby obejść ten problem, po prostu zachowajonCreateDialog()
tę samą metodę i dodajonResume()
metodę w następujący sposób:@Override public void onResume() { super.onResume(); Dialog dialog = getDialog(); dialog.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM); dialog.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE); }
To powinno załatwić sprawę, na szczęście działa na mnie. Zajmuję się tą sprawą już od jakiegoś czasu.
źródło
pełny kod pokazujący klawiaturę w oknie dialogowym:
public void onFocusChange(View v, boolean hasFocus) { Log.v("onFocusChange", hasFocus + " " + showkeyboard); if (hasFocus) { if (showkeyboard++ == 0) { alertDialog.getWindow().clearFlags( WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM); alertDialog.getWindow().setSoftInputMode( WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE); } else { showkeyboard = 1; } } }
źródło
This worked for me ---- editText.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { //dialog.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE); //dialog.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE); //dialog.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE); //dialog.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM); InputMethodManager mgr = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE); mgr.showSoftInput(v, InputMethodManager.SHOW_FORCED); editText.setFocusable(true); } });
źródło
wystarczy dodać poniżej codeLine:
// aby automatycznie wyświetlać klawiaturę, gdy editText jest w oknie dialogowym dialog.getWindow (). setSoftInputMode (WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);
źródło