Как выбрать запись в AlertDialog с помощью флажка с одним выбором Android?

У меня есть диалоговое окно предупреждения со списком с одним выбором и двумя кнопками: кнопка OK и кнопка cancel. В приведенном ниже коде показано, как я его реализовал.

private final Dialog createListFile(final String[] fileList) {
  AlertDialog.Builder builder = new AlertDialog.Builder(this);
  builder.setTitle("Compare with:");

  builder.setSingleChoiceItems(fileList, -1, new DialogInterface.OnClickListener() {
    public void onClick(DialogInterface dialog, int whichButton) {
      Log.d(TAG,"The wrong button was tapped: " + fileList[whichButton]);
    }
  });

  builder.setPositiveButton("OK", new DialogInterface.OnClickListener() {
    public void onClick(DialogInterface dialog, int whichButton) {}
  });

  builder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
    public void onClick(DialogInterface dialog, int whichButton) {}
  });

  return builder.create();
}

Моя цель - получить имя выбранного переключателя при нажатии кнопки OK. Я попытался сохранить строку в переменной, но внутри внутреннего класса можно получить доступ только к конечным переменным. Есть ли способ избежать использования конечной переменной для хранения выбранного переключателя?


person LuckyStarr    schedule 14.04.2011    source источник


Ответы (5)


Использование конечной переменной, очевидно, не сработает (поскольку ее можно присвоить только один раз, во время объявления). Так называемые "глобальные" переменные обычно являются запахом кода (особенно когда они становятся частью класса Activity, где обычно создаются AlertDialogs). Более чистое решение — привести объект DialogInterface к AlertDialog, а затем вызвать getListView().getCheckedItemPosition(). Нравится:

new AlertDialog.Builder(this)
        .setSingleChoiceItems(items, 0, null)
        .setPositiveButton(R.string.ok_button_label, new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int whichButton) {
                dialog.dismiss();
                int selectedPosition = ((AlertDialog)dialog).getListView().getCheckedItemPosition();
                // Do something useful withe the position of the selected radio button
            }
        })
        .show();
person E-Riz    schedule 27.07.2011
comment
Что, если бы я хотел запомнить, что было выбрано, и при следующем открытии диалогового окна выбор уже был выбран? - person Si8; 12.10.2013
comment
@SiKni8, вы можете сохранить selectedPosition (возможно, как переменную экземпляра Activity), а затем вызвать getListView().setItemChecked() при следующем открытии диалогового окна. - person E-Riz; 13.10.2013
comment
Я получил selectedPosition, но не знаю, где вызывать .setItemChecked(). Вот мой вопрос: stackoverflow.com/questions/19327170/ - person Si8; 13.10.2013
comment
совет: вы можете использовать android.R.string.ok для своего R.string.ok_button_label - person k2col; 26.11.2016

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

В этом примере я использую реализацию DialogFragment и получаю значение с помощью метода обратного вызова.

Метод обратного вызова для получения значений из диалога можно реализовать, создав общедоступный интерфейс.

public interface OnDialogSelectorListener {
    public void onSelectedOption(int selectedIndex);
}

Также DialogFragment реализует DialogInterface.OnClickListener, что означает, что вы можете зарегистрировать класс, который вы реализовали, как OnClickListener для создаваемого DialogFragment.

Например

public Dialog onCreateDialog(Bundle savedInstanceState) {
    final AlertDialog.Builder builder = new AlertDialog.Builder(this.getActivity());

    builder.setTitle(R.string.select);
    builder.setSingleChoiceItems(mResourceArray, mSelectedIndex, this);
    builder.setPositiveButton(R.string.ok, this);
    builder.setNegativeButton(R.string.cancel, this);
    return builder.create();
}

Линия

builder.setSingleChoiceItems(mResourceArray, mSelectedIndex, this);

Создает диалоговое окно выбора с параметрами из массива ресурсов, хранящегося в mResourceArray. Это также предварительно выбирает индекс параметра из того, что хранится в mSelectedIndex, и, наконец, устанавливает сам this в качестве OnClickListener. (Посмотрите полный код в конце, если этот абзац немного сбивает с толку)

Теперь метод OnClick позволяет получить значение, полученное из диалогового окна.

@Override
public void onClick(DialogInterface dialog, int which) {

    switch (which) {
        case Dialog.BUTTON_NEGATIVE: // Cancel button selected, do nothing
            dialog.cancel();
            break;

        case Dialog.BUTTON_POSITIVE: // OK button selected, send the data back
            dialog.dismiss();
            // message selected value to registered callbacks with the
                    // selected value.
            mDialogSelectorCallback.onSelectedOption(mSelectedIndex);
            break;

        default: // choice item selected
                    // store the new selected value in the static variable
            mSelectedIndex = which;
            break;
    }
}

Здесь происходит следующее: когда элемент выбран, он сохраняется в переменной. Если пользователь нажимает кнопку Отмена, обновление не возвращается и ничего не изменяется. Если пользователь нажимает кнопку OK, он возвращает значение Activity, создавшему его, с помощью созданного обратного вызова.

В качестве примера, вот как вы могли бы создать диалог из файла FragmentActivity.

final SelectorDialog sd = SelectorDialog.newInstance(R.array.selector_array, preSelectedValue);
sd.show(getSupportFragmentManager(), TAG);

Здесь массив ресурсов _R.array.selector_array_ — это массив строк, отображаемых в диалоговом окне, а preSelectedValue — это индекс, который следует выбрать при открытии.

Наконец, ваш FragmentActivity реализует OnDialogSelectorListener и получит сообщение обратного вызова.

public class MyActivity extends FragmentActivity implements OnDialogSelectorListener {
// ....

    public void onSelectedOption(int selectedIndex) {
        // do something with the newly selected index
    }
}

Я надеюсь, что это полезно для кого-то, так как мне потребовалось МНОГО попыток понять это. Полная реализация этого типа DialogFragment с обратным вызовом находится здесь.

public class SelectorDialog extends DialogFragment implements OnClickListener {
    static final String TAG = "SelectorDialog";

    static int mResourceArray;
    static int mSelectedIndex;
    static OnDialogSelectorListener mDialogSelectorCallback;

    public interface OnDialogSelectorListener {
        public void onSelectedOption(int dialogId);
    }

    public static DialogSelectorDialog newInstance(int res, int selected) {
        final DialogSelectorDialog dialog  = new DialogSelectorDialog();
        mResourceArray = res;
        mSelectedIndex = selected;

        return dialog;
    }

    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);

        try {
            mDialogSelectorCallback = (OnDialogSelectorListener)activity;
        } catch (final ClassCastException e) {
            throw new ClassCastException(activity.toString() + " must implement OnDialogSelectorListener");
        }
    }

    public Dialog onCreateDialog(Bundle savedInstanceState) {
        final AlertDialog.Builder builder = new AlertDialog.Builder(this.getActivity());

        builder.setTitle(R.string.select);
        builder.setSingleChoiceItems(mResourceArray, mSelectedIndex, this);
        builder.setPositiveButton(R.string.ok, this);
        builder.setNegativeButton(R.string.cancel, this);
        return builder.create();
    }

    @Override
    public void onClick(DialogInterface dialog, int which) {

        switch (which) {
            case Dialog.BUTTON_NEGATIVE:
                dialog.cancel();
                break;

            case Dialog.BUTTON_POSITIVE:
                dialog.dismiss();
                // message selected value to registered calbacks
                mDialogSelectorCallback.onSelectedOption(mSelectedIndex);
                break;

            default: // choice selected click
                mSelectedIndex = which;
                break;
        }

    }
}

Вопрос из комментария Как вызвать это из Fragment вместо Activity.

Сначала внесите несколько изменений в файл DialogFragment.

Удалите событие onAttach, так как это не самый простой способ в этом сценарии.

Добавьте новый метод, чтобы добавить ссылку на обратный вызов

public void setDialogSelectorListener (OnDialogSelectorListener listener) {
    this.mListener = listener;
}

Внедрите прослушиватель в свой Fragment

public class MyFragment extends Fragment implements SelectorDialog.OnDialogSelectorListener {
// ....

    public void onSelectedOption(int selectedIndex) {
        // do something with the newly selected index
    }
}

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

final SelectorDialog sd = SelectorDialog.newInstance(R.array.selector_array, preSelectedValue);
// this is a reference to MyFragment
sd.setDialogSelectorListener(this);
// mActivity is just a reference to the activity attached to MyFragment
sd.show(this.mActivity.getSupportFragmentManager(), TAG);
person Kirk    schedule 12.02.2013
comment
Спасибо за ваши объяснения. Как бы вы реализовали обратный вызов, чтобы при срабатывании прослушивателя сообщалось Fragment вместо Activity? - person JJD; 15.10.2013
comment
Я добавил объяснение того, как я использую это в Fragment - person Kirk; 15.10.2013


Попробуй это.

final String[] fonts = {"Small", "Medium", "Large", "Huge"};

AlertDialog.Builder builder = new AlertDialog.Builder(TopicDetails.this);
builder.setTitle("Select a text size");
builder.setItems(fonts, new DialogInterface.OnClickListener() {
  @Override
  public void onClick(DialogInterface dialog, int which) {
    if ("Small".equals(fonts[which])) {
      Toast.makeText(MainActivity.this,"you nailed it", Toast.LENGTH_SHORT).show();
    }
    else if ("Medium".equals(fonts[which])) {
      Toast.makeText(MainActivity.this,"you cracked it", Toast.LENGTH_SHORT).show();
    }
    else if ("Large".equals(fonts[which])){
      Toast.makeText(MainActivity.this,"you hacked it", Toast.LENGTH_SHORT).show();
    }
    else if ("Huge".equals(fonts[which])){
     Toast.makeText(MainActivity.this,"you digged it", Toast.LENGTH_SHORT).show();
    }
  // the user clicked on colors[which]
  }
});
builder.show();
person Nikhil jassal    schedule 15.11.2018

person    schedule
comment
from не является окончательным, вы не можете использовать его во внутреннем классе. - person LuckyStarr; 14.04.2011