AlertDialog не подходит для длинного списка, вида и кнопок, если они используются вместе - PullRequest
0 голосов
/ 21 апреля 2020

Некоторое время go Я столкнулся с проблемой с AlertDialog:

Если он используется с адаптером списка (через setAdpater / setSingleChoiceItems / setMultiChoiceItems) и пользовательским представлением (через setView) и иногда с кнопками, а также списком слишком длинный и не соответствует высоте диалога, мой пользовательский добавленный вид и кнопки диалога не отображались ... (он отображается, но не виден, поскольку перемещен вниз по списку) вот тестовый код:

    final int TEST_COUNT = 20; //increase it if list fit your screen...
    List<String> list = new LinkedList<>();
    for (int i = 1; i <= TEST_COUNT; i++)
      list.add("item "+i);
    TextView testView = new TextView(this); //type of view doesn't matter
    testView.setText("test view");
    ArrayAdapter<String> adapter = new ArrayAdapter<>(this, android.R.layout.select_dialog_item, list);
    AlertDialog.Builder builder = new AlertDialog.Builder(this);
    AlertDialog dialog = builder
            .setTitle("Test AlertDialog")
            .setAdapter(adapter, (dlg, which) -> {})
            .setView(testView) //this line broke all!
            .setPositiveButton("Yes", (dlg, which) -> dlg.dismiss())
            .setNegativeButton("No", (dlg, which) -> dlg.dismiss())
            .show();

Я искал в Google и SO, но не нашел рабочего решения, только одно предложение - написать свой собственный диалог с пользовательским макетом ... И я решил найти правду.

1 Ответ

0 голосов
/ 21 апреля 2020

Поскольку я не нашел рабочего решения, я провел расследование и сделал свое собственное. Прежде всего, я проверил макет AlertDialog и источники по умолчанию:

  1. alert_dialog_material. xml
  2. AlertDialog. java
  3. AlertController. java

ссылки были найдены в Google, вы можете проверить источники в вашей IDE, конечно.

Как мы Можно понять из макета xml - root Представление AlertDialogLayout наследуется от LinearLayout (Compat), все дочерние элементы имеют высоту = WRAP_CONTENT. Но нам нужно, чтобы listview был помещен в пространство между заголовком и нашим пользовательским представлением. И решение, которое я нашел - установите вес представления «contentPanel» равным 1. Вот пример кода, решающего проблему, просто замените .show () на .create () в первой части. кода из вопроса:

dialog.setOnShowListener(dlg -> {
        AlertDialog adlg = (AlertDialog)dlg;
        View v = adlg.getWindow().findViewById(R.id.contentPanel);
        if (v != null)
            ((LinearLayoutCompat.LayoutParams)v.getLayoutParams()).weight = 1;
    });
dialog.show();

Конечно, это будет работать до тех пор, пока Google не изменит что-то в их стандартном макете alerttdialog ...

Может быть, кто-то может предложить лучшее решение?

Спасибо за внимание!

...