Ошибка при получении тега из DatePickerFragment

#java #android #android-fragments #datepicker #tags

#java #Android #android-фрагменты #datepicker #Теги

Вопрос:

Я создаю приложение с двумя датами выбора даты, чтобы установить даты начала и окончания. Поскольку DatePicker вызывается из DialogFragments, я установил два тега, чтобы различать результаты в основном действии:

 
 @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.sel_start_date:
                DialogFragment startDatePicker = new DatePickerFragment();
                startDatePicker.show(getSupportFragmentManager(), START_DATE_PICKER_TAG);
                break;
           case R.id.sel_end_date:
                DialogFragment endDatePicker = new DatePickerFragment();
                endDatePicker.show(getSupportFragmentManager(), END_DATE_PICKER_TAG);
                break;

  

Класс DatePickerFragment:

 public class DatePickerFragment extends DialogFragment {
    @NonNull
    @Override
    public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
        Calendar calendar = Calendar.getInstance();
        int year = calendar.get(Calendar.YEAR);
        int month = calendar.get(Calendar.MONTH);
        int day = calendar.get(Calendar.DAY_OF_MONTH);
        return new DatePickerDialog(getActivity(), (DatePickerDialog.OnDateSetListener) getActivity(), year, month, day );
    }
  

и вот как я получаю результат в основном действии

   @Override
    public void onDateSet(DatePicker view, int year, int month, int dayOfMonth) {
        if (view.getTag().equals(START_DATE_PICKER_TAG)) {
            calendarStartDate.set(Calendar.YEAR, year);
            calendarStartDate.set(Calendar.MONTH, month);
            calendarStartDate.set(Calendar.DAY_OF_MONTH, dayOfMonth);
            start_date_btn.setText(dayOfMonth   "/"   (month   1)   "/"   year);
        } else {
            calendarEndDate.set(Calendar.YEAR, year);
            calendarEndDate.set(Calendar.MONTH, month);
            calendarEndDate.set(Calendar.DAY_OF_MONTH, dayOfMonth);
            end_date_btn.setText(dayOfMonth   "/"   (month   1)   "/"   year);
        }
    }
  

Тем не менее, я получаю исключение NullPointerException, выполняя view.getTag(). Как я могу решить это или как еще я могу дифференцировать результаты?

Уточнение: DatePickerDialog — это собственный класс, не тот, который я создал, поэтому я не могу редактировать их методы `

TimePickerFragment:

 public class TimePickerFragment extends DialogFragment {
    private static final String ARGS_TAG = "ARGS_TAG";

    @NonNull
    @Override
    public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
        Calendar calendar = Calendar.getInstance();
        int hour = calendar.get(Calendar.HOUR_OF_DAY);
        int minute = calendar.get(Calendar.MINUTE);

        final String tag = getArguments().getString(ARGS_TAG);
        return new TimePickerDialog(getActivity(), (TimePickerDialog.OnTimeSetListener) getActivity(), hour, minute, android.text.format.DateFormat.is24HourFormat(getActivity())) {
                @Override
                protected void onCreate(Bundle savedInstanceState) {
                    super.onCreate(savedInstanceState);
                }
            };
    }

    public static TimePickerFragment newInstance(String tag){
        Bundle args = new Bundle();
        args.putString(ARGS_TAG, tag);
        TimePickerFragment fragment = new TimePickerFragment();
        fragment.setArguments(args);
        return fragment;
    }
  

Ответ №1:

Решение: определите два интерфейса для пересылки данных из фрагментов в activity.

Шаг 1. Определите OnDateSetListener интерфейс для связи между MainActivity и DatePickerFragment .

 public interface OnDateSetListener {
    void onDateSet(String tag, DatePicker view, int year, int month, int dayOfMonth);
}
  

Шаг 2. Определите OnTimeSetListener интерфейс для связи между MainActivity и TimePickerFragment .

 public interface OnTimeSetListener {
    void onTimeSet(String tag, TimePicker view, int hourOfDay, int minute);
}
  

Шаг 3. Let MainActivity реализует оба интерфейса.

 public class MainActivity extends AppCompatActivity implements OnDateSetListener, OnTimeSetListener {

    // Your code her
    ...

    @Override
    public void onDateSet(String tag, DatePicker view, int year, int month, int dayOfMonth) {
        // Process code with tag here
    }

    @Override
    public void onTimeSet(String tag, TimePicker view, int hourOfDay, int minute) {
        // Process code with tag here.
    }
}
  

Шаг 4. Измените код в DatePickerFragment

 public class DatePickerFragment extends DialogFragment implements DatePickerDialog.OnDateSetListener {
    private static final String ARGUMENT_TAG = "ARGUMENT_TAG";

    public static DatePickerFragment newInstance(String tag) {
        Bundle args = new Bundle();
        args.putString(ARGUMENT_TAG, tag);
        DatePickerFragment fragment = new DatePickerFragment();
        fragment.setArguments(args);
        return fragment;
    }

    @NonNull
    @Override
    public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
        Calendar calendar = Calendar.getInstance();
        int year = calendar.get(Calendar.YEAR);
        int month = calendar.get(Calendar.MONTH);
        int day = calendar.get(Calendar.DAY_OF_MONTH);
        return new DatePickerDialog(requireActivity(), this, year, month, day);
    }

    @Override
    public void onDateSet(DatePicker view, int year, int month, int dayOfMonth) {
        final String tag = getArguments().getString(ARGUMENT_TAG);
        OnDateSetListener listener = (OnDateSetListener) requireActivity();
        listener.onDateSet(tag, view, year, month, dayOfMonth);
    }
}
  

Шаг 5. Измените код в TimePickerFragment .

 public class TimePickerFragment extends DialogFragment implements TimePickerDialog.OnTimeSetListener {
    private static final String ARGS_TAG = "ARGS_TAG";

    public static TimePickerFragment newInstance(String tag) {
        Bundle args = new Bundle();
        args.putString(ARGS_TAG, tag);
        TimePickerFragment fragment = new TimePickerFragment();
        fragment.setArguments(args);
        return fragment;
    }

    @Override
    public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
        Calendar calendar = Calendar.getInstance();
        int hour = calendar.get(Calendar.HOUR_OF_DAY);
        int minute = calendar.get(Calendar.MINUTE);
        return new TimePickerDialog(requireActivity(), this, hour, minute, DateFormat.is24HourFormat(getActivity()));
    }


    @Override
    public void onTimeSet(TimePicker view, int hourOfDay, int minute) {
        final String tag = getArguments().getString(ARGS_TAG);
        OnTimeSetListener listener = (OnTimeSetListener) requireActivity();
        listener.onTimeSet(tag, view, hourOfDay, minute);
    }
}
  

Комментарии:

1. Это отлично сработало, спасибо!! Теперь я пытаюсь сделать то же самое с помощью средства выбора времени, но, поскольку TimePickerDialog не является getTimePicker() методом, я немного застрял там

Ответ №2:

Как я вижу, вы установили тег для фрагмента, но то, что вы пытаетесь получить, — это тег представления. Это не одно и то же, поскольку тег представления является объектом, а тег фрагмента — строкой.

Комментарии:

1. Я вижу. И как я мог бы тогда получить тег фрагмента?

2. Либо отправьте тег фрагмента вместе с onDateSet , либо установите тег представления в onViewCreated.

Ответ №3:

Как вы можете видеть, ваше представление в onDateSet — это DatePicker, и вы устанавливаете свой тег на фрагмент, содержащий DatePicker, который является DatePickerDialog.

Итак, чтобы получить свой тег, вы должны попробовать что-то вроде:

 @Override
    public void onDateSet(DatePicker view, int year, int month, int dayOfMonth) {
        if (view.getParent() != null amp;amp; view.getParent().getTag().equals(START_DATE_PICKER_TAG)) {
            calendarStartDate.set(Calendar.YEAR, year);
            calendarStartDate.set(Calendar.MONTH, month);
            calendarStartDate.set(Calendar.DAY_OF_MONTH, dayOfMonth);
            start_date_btn.setText(dayOfMonth   "/"   (month   1)   "/"   year);
        } else {
            calendarEndDate.set(Calendar.YEAR, year);
            calendarEndDate.set(Calendar.MONTH, month);
            calendarEndDate.set(Calendar.DAY_OF_MONTH, dayOfMonth);
            end_date_btn.setText(dayOfMonth   "/"   (month   1)   "/"   year);
        }
    }
  

Комментарии:

1. Только что попробовал это, и хотя фрагмент имеет метод getTag, в view.getParent().getTag() метод не может быть разрешен