NumberPicker не работает внутри DialogFragment

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

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

Кто-нибудь может дать совет, как это исправить? До сих пор я заметил, что есть много вещей, которые я пытаюсь сделать с виджетами в определенных действиях или фрагментах, которые не поддерживаются в этом конкретном классе.

Ниже приведены фрагменты соответствующего кода и изображений:

У меня есть класс ClockActivity с двумя кнопками:

...
public class ClockActivity extends ActionBarActivity {

...

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_clock);

    // Define gui objects
    ...
    mWorkForTime           = (Button)findViewById(R.id.work_for_time);
    mBreakForTime          = (Button)findViewById(R.id.break_for_time);

    // Add listeners for the work for/break for buttons
    mWorkForTime.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            // Bring up the picker fragment
            DialogFragment newFragment = TimePickerFragment.newInstance(R.string.work_title);
            newFragment.show(getSupportFragmentManager(), "WorkTimePicker");
        }
    });
    mBreakForTime.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            // Bring up the picker fragment
            DialogFragment newFragment = TimePickerFragment.newInstance(R.string.break_title);
            newFragment.show(getSupportFragmentManager(), "BreakTimePicker");
        }
    });
    ...

Класс TimePickerFragment расширяет DialogFragment:

public class TimePickerFragment extends DialogFragment {
    // Setup the time pickers
    private NumberPicker mHourPicker;
    private NumberPicker mMinutePicker;

    public static TimePickerFragment newInstance(int title) {
        TimePickerFragment fragment = new TimePickerFragment();
        Bundle args = new Bundle();
        args.putInt("title", title);
        fragment.setArguments(args);
        return fragment;
    }

    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        super.onCreateDialog(savedInstanceState);

        int title = getArguments().getInt("title");

        LayoutInflater inflater = getActivity().getLayoutInflater();

        View view = (View)inflater.inflate(R.layout.activity_time_picker, null);

        // Initialize the pickers
        mHourPicker = (NumberPicker)view.findViewById(R.id.hours_picker);
        mMinutePicker = (NumberPicker)view.findViewById(R.id.minutes_picker);
        mHourPicker.setMinValue(0);
        mMinutePicker.setMinValue(0);
        mHourPicker.setMaxValue(24);
        mMinutePicker.setMaxValue(59);


        Dialog alertDialog = new AlertDialog.Builder(getActivity())
                .setTitle(title)
                .setView(inflater.inflate(R.layout.activity_time_picker, null))
                .setNegativeButton(R.string.negate,
                        new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog, int which) {
                                ((ClockActivity) getActivity()).doNegativeTimeDialogClick();
                            }
                        })
                .setPositiveButton(R.string.confirm,
                        new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog, int which) {
                                ((ClockActivity) getActivity()).doPositiveTimeDialogClick();
                            }
                        })
                .create();
        return alertDialog;
    }
}

Ниже приведен XML для представления DialogFragment, которое находится в

<?xml version="1.0" encoding="utf-8"?>
    <LinearLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <LinearLayout
            android:layout_width="fill_parent"
            android:layout_height="wrap_content">

            <TextView
                android:layout_width="0dp"
                android:layout_weight="1"
                android:layout_height="wrap_content"
                android:gravity="center"
                android:text="@string/hours"
                android:textSize="24sp"
                android:textStyle="bold"/>

            <TextView
                android:layout_width="0dp"
                android:layout_weight="1"
                android:layout_height="wrap_content"
                android:gravity="center"
                android:text="@string/minutes"
                android:textSize="24sp"
                android:textStyle="bold"/>

        </LinearLayout>

        <LinearLayout
            android:layout_width="fill_parent"
            android:layout_height="wrap_content">

            <NumberPicker
                android:id="@+id/hours_picker"
                android:layout_width="0dp"
                android:layout_weight="1"
                android:layout_height="wrap_content"/>

            <NumberPicker
                android:id="@+id/minutes_picker"
                android:layout_width="0dp"
                android:layout_weight="1"
                android:layout_height="wrap_content"/>

        </LinearLayout>
    </LinearLayout>

Вот изображение текущей операции:

http://i.imgur.com/4UiSLcn.png

Вот что я хочу иметь:

http://www.i-programmer.info/images/stories/Core/Android/Pickers/ten.gif

Вот некоторый вывод, который я вижу на консоли, когда пытаюсь редактировать NumberPicker с помощью программной клавиатуры:

01-02 16:10:46.559  18438-18438/com.example.android.worktimer W/IInputConnectionWrapper﹕ beginBatchEdit on inactive InputConnection
01-02 16:10:46.569  18438-18438/com.example.android.worktimer W/IInputConnectionWrapper﹕ endBatchEdit on inactive InputConnection

person Burke9077    schedule 02.01.2015    source источник


Ответы (2)


Вы должны предоставить сборщику массив того, что вы пытаетесь выбрать.

    String[] myStringArray = new String[]{"a","b","c"};
    mMinutePicker.setMinValue(0);
    mMinutePicker.setMaxValue(myStringArray.length - 1);
    mMinutePicker.setDisplayedValues(myStringArray);

И изменить

    Dialog alertDialog = new AlertDialog.Builder(getActivity()) .setTitle(title) .setView(inflater.inflate(R.layout.activity_time_picker, null)) 

to

    Dialog alertDialog = new AlertDialog.Builder(getActivity()).setTitle(title).setView(view)

Вы снова раздуваете представление.

person Farooq Arshed    schedule 02.01.2015
comment
Что делать, если мне нужен список номеров? Я попробовал это: mHourPicker.setMinValue(0); mMinutePicker.setMinValue(0); Похоже, что метод setDisplayedValues() будет принимать только массив строк. - person Burke9077; 03.01.2015
comment
установите число в массиве строк, а затем извлеките число из массива, например myStringArray[mMinutePicker.getValue()] - person Farooq Arshed; 03.01.2015
comment
Или вы можете добавить прослушиватель для выбора номера и получить позицию выбранного элемента и найти эту позицию в массиве. - person Farooq Arshed; 03.01.2015
comment
Я настраиваю массив, но элементы все еще не отображаются. Я попытался добавить прослушиватель событий клавиатуры, но они тоже не появились. - person Burke9077; 03.01.2015
comment
попробуйте добавить это mMinutePicker.setWrapSelectorWheel(true); - person Farooq Arshed; 03.01.2015
comment
Хм, все равно не повезло. Спасибо хоть. Я отредактировал вопрос с некоторым выводом, который я вижу на консоли, когда нажимаю NumberChooser. - person Burke9077; 03.01.2015
comment
Диалог alertDialog = new AlertDialog.Builder(getActivity()) .setTitle(title) .setView(inflater.inflate(R.layout.activity_time_picker, null)) должен быть Dialog alertDialog = new AlertDialog.Builder(getActivity()) .setTitle( title) .setView(view) вы ничего не меняете в представлении, если снова его раздуваете. - person Farooq Arshed; 03.01.2015
comment
Отлично. позвольте мне добавить это к ответу. - person Farooq Arshed; 03.01.2015

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

Есть ряд проблем, с которыми вы столкнетесь, например, findViewById не работает в onCreateDialog. Я думаю, это потому, что представление еще не создано. Я попытался обойти эту проблему, инициализировав NumberPicker в onCreateView. По крайней мере, в этом методе я мог заставить работать onFindViewById, но он все еще не работал, устанавливая минимальные и максимальные значения для NumberPicker. Короче говоря, я просто не мог заставить NumberPicker работать в DialogFragment. Все, что я пытался сделать, просто сделать код более скрытым и слишком сложным для понимания. Мой принцип кодирования заключается в том, чтобы перестать заставлять код работать, когда он становится трудным для понимания.

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

public Dialog show() {
    AppCompatActivity activity = CoreAndroid.getActivity();
    Context context = CoreAndroid.getContext();
    AlertDialog.Builder builder = new AlertDialog.Builder(activity);
    // Get the layout inflater
    LayoutInflater inflater = LayoutInflater.from(CoreAndroid.getContext());
    ViewGroup viewGroup = activity.findViewById(android.R.id.content);
    View dialogView = inflater.inflate(R.layout.log_filter_dialog, viewGroup, false);
    builder.setView(dialogView);
    builder.setPositiveButton(R.string.apply, new DialogInterface.OnClickListener() {
        @Override
        public void onClick(DialogInterface dialog, int id) {
            // sign in the user ...
        }
    })
            .setNegativeButton(R.string.exit, new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface dialog, int id) {
                    dialog.cancel();
                }
            });

    dialog = builder.create();
    initDialog(dialogView)  // this method is where the NumberPicker and other
                            // controls in the dialog get initialized
    dialog.show();
    return dialog;
}

Это просто метод в классе, который создает диалог и показывает его. После вызова метода builder.create вы можете найти представления в макете диалогового окна, которые вы хотите инициализировать, с помощью dialogView.findViewId. Это намного проще и понятнее, чем пытаться использовать DialogFragment. Я увлекся попыткой использовать DialogFragment, потому что другие люди предоставили его в качестве шаблона кода. Может быть причина использовать DialogFragment, но для того, что мне нужно было сделать, это было слишком громоздко, и я не смог заставить его делать некоторые простые вещи, такие как инициализация элемента управления.

person Tom Rutchik    schedule 17.03.2021