Как выбрать запись в AlertDialog с одним флажком выбора Android? - PullRequest
39 голосов
/ 14 апреля 2011

У меня есть диалоговое окно предупреждения с списком с одним выбором и двумя кнопками: кнопка 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.Я пытался сохранить строку в переменной, но внутри внутреннего класса можно получить доступ только к конечным переменным.Есть ли способ избежать использования окончательной переменной для сохранения выбранной радиокнопки?

Ответы [ 5 ]

138 голосов
/ 27 июля 2011

Использование конечной переменной, очевидно, не сработает (поскольку она может быть назначена только один раз, во время объявления). Так называемые «глобальные» переменные обычно являются запахом кода (особенно когда они становятся частью класса 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();
15 голосов
/ 12 февраля 2013

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

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

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

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

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

В качестве примера, вот как вы могли бы создать диалог из 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);
9 голосов
/ 14 апреля 2011
final CharSequence[] choice = {"Choose from Gallery","Capture a photo"};

int from; //This must be declared as global !

AlertDialog.Builder alert = new AlertDialog.Builder(activity);
alert.setTitle("Upload Photo");
alert.setSingleChoiceItems(choice, -1, new DialogInterface.OnClickListener() {
    @Override
    public void onClick(DialogInterface dialog, int which) {
        if (choice[which] == "Choose from Gallery") {
            from = 1;
        } else if (choice[which] == "Capture a photo") {
            from = 2;
        }
    }
});
alert.setPositiveButton("OK", new DialogInterface.OnClickListener() {
    @Override
    public void onClick(DialogInterface dialog, int which) {
        if (from == 0) {
            Toast.makeText(activity, "Select One Choice", 
                        Toast.LENGTH_SHORT).show();
        } else if (from == 1) {
            // Your Code
        } else if (from == 2) {
            // Your Code
        }
    }
});
alert.show();
1 голос
/ 21 декабря 2018

Как уже отмечали другие, реализация 'com.google.android.material: material: 1.0.0' проще

Дополнительная информация приведена в этом руководстве по материалам.https://material.io/develop/android/docs/getting-started/

CharSequence[] choices = {"Choice1", "Choice2", "Choice3"};
boolean[] choicesInitial = {false, true, false};
AlertDialog.Builder alertDialogBuilder = new MaterialAlertDialogBuilder(getContext())
    .setTitle(title)
    .setPositiveButton("Accept", null)
    .setNeutralButton("Cancel", null)
    .setMultiChoiceItems(choices, choicesInitial, new DialogInterface.OnMultiChoiceClickListener() {
      @Override
      public void onClick(DialogInterface dialog, int which, boolean isChecked) {

      }
    });
alertDialogBuilder.show();

enter image description here

0 голосов
/ 15 ноября 2018

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

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