Android: EditText в диалоговом окне не подтягивает мягкую клавиатуру


Так что у меня есть то, что кажется общей проблемой, которая заключается в том, что EditText в моем диалоговом окне не отображается, когда он получает фокус. Я видел несколько обходных путей, таких как этой теме,этот и этот (и многое другое), но я никогда не видел удовлетворительного объяснения почему это происходит в первую очередь.

Я бы предпочел, чтобы android использовал свое собственное поведение по умолчанию для редактирования текстов, чем чтобы построить свой собственный, но похоже, что все (в этих потоках) приняли, что поведение по умолчанию для EditTexts в диалогах-это просто дать курсор и не клавиатуру. С чего бы это?

для записи, ни один из этих обходных путей, похоже, не работает для меня - самое близкое, что я смог сделать, это заставить клавиатуру появиться под диалоговое окно (с помощью InputMethodManager.toggleSoftKeyboard (*)). Моя конкретная конфигурация-API15, EditText отображается в нижнем колонтитуле ListView в AlertDialog. Установлен EditText android: focusable= "true", а onFocusChangeListener и получение фокуса событий.

Edit:

как и просили, вот конкретный фрагмент кода, что я работаю. Я не буду беспокоиться обо всем макете, но в этом конкретном приложении EditText появляется в ответ на нажатие кнопки в диалоговом окне (аналогично действие вида). Он содержится в RelativeLayout, который по умолчанию имеет видимость "пошел":

 <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>

код, который строит это, устанавливает видимость relativeLayout в "видимый" (и скрывает другие элементы пользовательского интерфейса). Это должны достаточно, чтобы вытащить клавиатуру, когда EditText фокусируется, основываясь на моем опыте работы с EditText. Однако, по какой-то причине это не так. Я могу установить следующий 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."));
                }
            }
        });

используя эту конфигурацию, когда я первый введите EditText, триггеры onFocusChangedListener и генерирует журнал, который неизменно выглядит следующим образом:

Focus requested, has focus.
Focus requested, doesn't have focus.
Focus requested, has focus.

клавиатура появляется, а затем исчезает, вероятно, потому, что я переключаю его дважды, но даже когда я уверен, что он остается, это за диалоговое окно (в серой области), и нет никакого способа добраться до него, не закрывая диалоговое окно.

тем не менее, я хотел бы подчеркнуть, что, хотя я могу быть в состоянии получить эту работу вокруг, чтобы работать, я в первую очередь заинтересованы в поиске простой причине почему EditText не срабатывает в первую очередь, и почему это кажется таким банальным!

10 70

10 ответов:

хорошо, так что после прочтения много, я понял, почему это проблема, и я делаю не нужно использовать любые обходные пути.

проблема кажется (по крайней мере, в моем случае), что поскольку место, где вы вводите текст, скрыто изначально (или вложено или что-то еще), AlertDialog автоматически устанавливает флаг WindowManager.Ни.FLAG_ALT_FOCUSABLE_IM (или некоторая комбинация этого и WindowManager.Ни.FLAG_NOT_FOCUSABLE) так что вещи не вызывают мягкий вход, чтобы показать.

способ, который я нашел, чтобы исправить это, чтобы добавить следующую строку после создания диалогового окна:

dialog.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE|WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);

Как только это будет сделано, EditText будет действовать как обычный EditText, без необходимости в kludges или обходных путях.

У меня такая же проблема в мои собственные приложения. Если вы разрабатываете для уровня API >= 8, вы можете использовать этот фрагмент:

dialog.setOnShowListener(new OnShowListener() {
    @Override
     public void onShow(DialogInterface dialog) {
         InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
         imm.showSoftInput(textEdit, InputMethodManager.SHOW_IMPLICIT);
    }
});

Я не нашел решения для более низких уровней API...

кстати, этот пример не всегда работает на эмуляторе. Я не знаю, почему.

Если Вы читаете документацию AlertDialog, вы найдете там:

The AlertDialog класс заботится о автоматической настройке * WindowManager.Ни.FLAG_ALT_FOCUSABLE_IM* для вас на основе того, возвращают ли какие-либо представления в диалоговом окне true из вид.onCheckIsTextEditor(). Как правило, вы хотите этот набор для без текстовых редакторов, так что он будет помещен поверх текущего пользовательского интерфейса метода ввода. Вы можете изменить это поведение, заставляя флаг в нужный режим после вызова onCreate.

у меня была проблема, которую вы упомянули с EditText в ListView внутри диалогового окна. Я исправил это путем перезаписи пользовательского класса представления (в моем случае ListView) с моим собственным FocusableListView, только с одним методом перезаписи:

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

тогда я использую его в файле макета как:

<?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" />

Вы можете перезаписать RelativeLayout в вашем случае таким же образом, и это должен работать.

приведенный выше код очень полезен. Но вы должны вызвать метод "show "после метода" create " (я не знаю, почему, но только это работает в моем диалоге с EditText в ListView). В методе 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;
}

спасибо! У меня есть встроенный TextEdit в последней строке ListView, встроенный в фрагмент диалогового окна предупреждения. Я использовал ваше решение очистки флагов в качестве сообщения, которое можно запустить, и теперь оно отлично работает.

    @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;
}

это то, что работал для меня. Создать AlertDialog.Builder, set title, positiveButton, negativeButton. После этого сделайте следующее:

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

вам не нужно использовать builder.show();.

вот один из способов сделать это:

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

Я хотел бы добавить к Павла и Александр.

у меня самого есть диалог, который создан в onCreateDialog() метод, который (кажется) требовать возврата dialog.show();, поэтому вы не можете добавить layoutparams в диалоговое окно, в котором создается диалоговое окно. Чтобы обойти это, просто держите ваш onCreateDialog() метод тот же, и добавить onResume() метод следующим образом:

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

Это следует сделать трюк, это работает для меня, благодарно. Я уже довольно давно занимаюсь этим делом.

полный код для отображения клавиатуры в диалоговое окно:

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