TimePicker onTimeSet не вызывается
Я использую средство выбора времени, чтобы пользователь мог ввести желаемое время для выполнения определенной задачи, я использую класс DialogFragment, который доступен в библиотеке поддержки для обратной совместимости со старыми версиями Android.
Вот мой код для создания класса TimePickerFragment, созданного в отдельном файле, взятый из: http://developer.android.com/guide/topics/ui/controls/pickers.html:
package com.calls.only;
import java.util.Calendar;
import android.app.Dialog;
import android.app.TimePickerDialog;
import android.os.Bundle;
import android.support.v4.app.DialogFragment;
import android.widget.TimePicker;
public class TimePickerFragment extends DialogFragment
implements TimePickerDialog.OnTimeSetListener {
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
// Use the current time as the default values for the picker
final Calendar c = Calendar.getInstance();
int hour = c.get(Calendar.HOUR_OF_DAY);
int minute = c.get(Calendar.MINUTE);
// Create a new instance of TimePickerDialog and return it
return new TimePickerDialog(getActivity(), this, hour, minute, false);
}
public void onTimeSet(TimePicker view, int hourOfDay, int minute) {
// Do something with the time chosen by the user
}
}
Основная деятельность:
package com.calls.only;
import java.util.Calendar;
import java.util.TimeZone;
import android.os.Bundle;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.DialogFragment;
import android.view.Menu;
import android.view.View;
import android.widget.RadioButton;
import android.widget.TextView;
public class MainActivity extends FragmentActivity {
public void InputStartTime(View v) {
DialogFragment newFragment = new TimePickerFragment();
newFragment.show(getSupportFragmentManager(), "timePicker");
}
private TimePickerDialog.OnTimeSetListener mTimeSetListener =
new TimePickerDialog.OnTimeSetListener() {
//Overriding onTimeSet causes an error, see below
public void onTimeSet(TimePicker view, int hourOfDay, int minute) {
Log.i("TimePicker", "Time picker set!");
}
};
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.activity_main, menu);
return true;
}
}
метод onTimeset не вызывается, как я вижу из журнала, если я пытаюсь переопределить этот метод, я получаю ошибку: "Метод onTimeSet(TimePicker, int, int) типа new TimePickerDialog.OnTimeSetListener(){} должен переопределить метод суперкласса
Может кто-нибудь сказать мне, в чем проблема? Я пытался понять это, и это оставило меня слишком много разочарований!
2 ответа
метод onTimeset не вызывается, как я вижу из журнала
Ну, это потому, что когда вы создаете TimePickerDialog
Вы предоставляете фрагмент как OnTimeSetListener
:
return new TimePickerDialog(getActivity(), this, hour, minute, false);
^
Другими словами: вы не видите оператора журнала, потому что mTimeSetListener
переменная в вашей деятельности никогда не будет установлена как слушатель диалога, который вы создаете во фрагменте.
Вы можете легко исправить это, применив действие, к которому прикреплен фрагмент. MainActivity
или, если вы предпочитаете что-то более повторно используемое, используйте обратный вызов через интерфейс. В этом случае вы можете использовать OnTimeSetListener
интерфейс, но вы также можете настроить свой собственный, который, например, передает Calendar
Возвратитесь к действию, а не к необработанным значениям часа / минуты.
В своей основной форме это будет выглядеть примерно так:
public class TimePickerFragment extends DialogFragment {
@Override public Dialog onCreateDialog(Bundle savedInstanceState) {
// ... omitted
if (!(getActivity() instanceof OnTimeSetListener)) throw new IllegalStateException("Activity should implement OnTimeSetListener!");
OnTimeSetListener timeSetListener = (OnTimeSetListener) getActivity();
// Create a new instance of TimePickerDialog and return it
return new TimePickerDialog(getActivity(), timeSetListener, hour, minute, false);
}
}
И тогда у вас есть MainActivity
реализовать тот же интерфейс вместо использования анонимного внутреннего класса:
public class MainActivity extends FragmentActivity implements TimePickerDialog.OnTimeSetListener {
@Override public void onTimeSet(TimePicker view, int hourOfDay, int minute) {
Log.i("TimePicker", "Time picker set!");
}
}
Обновление: как уже упоминалось в комментариях, чтобы включить поддержку нескольких сборщиков, у вас есть несколько вариантов. Один из них - отслеживать, какой диалог отображается в хостинге; логическое будет хорошо, если вам нужно различать только два средства выбора, в противном случае перечисление будет подходящим способом для реализации более двух состояний. Вы хотите убедиться, что эта часть информации сохраняется во время изменений конфигурации...
Тем не менее, я бы предпочел сделать так, чтобы можно было определить источник результата, возвращенного в onTimeSet(...)
предоставляя идентификатор каждому сборщику. Этот идентификатор затем включается в результат, чтобы мы могли сказать, откуда он пришел. Я изложу общую идею ниже:
public class TimePickerFragment extends DialogFragment implements OnTimeSetListener {
private int mId;
private TimePickerDialogListener mListener;
private static TimePickerFragment newInstance(int id) {
Bundle args = new Bundle();
args.putInt("picker_id", id);
TimePickerFragment fragment = new TimePickerFragment();
fragment.setArguments(args);
return fragment;
}
@Override public Dialog onCreateDialog(Bundle savedInstanceState) {
// ... omitted
mId = getArguments().getInt("picker_id");
mListener = getActivity() instanceof TimePickerDialogListener ? (TimePickerDialogListener) getActivity() : null;
// Create a new instance of TimePickerDialog and return it
return new TimePickerDialog(getActivity(), this, hour, minute, false);
}
@Override public void onTimeSet(TimePicker view, int hourOfDay, int minute) {
if (mListener != null) mListener.onTimeSet(mId, view, hourOfDay, minute);
}
public static interface TimePickerDialogListener {
public void onTimeSet(int id, TimePicker view, int hourOfDay, int minute);
}
}
Что мы изменили выше, так это чтобы сам диалог был зарегистрирован как OnTimeSetListener
, для которого он будет затем передавать данные через TimePickerDialogListener
при условии, что хостинг реализует этот интерфейс. Вот что нам нужно сделать на следующем шаге. Также обратите внимание, что я добавил статический удобный метод для создания нового TimePickerFragment
это берет идентификатор. Это значение будет установлено в качестве аргумента для фрагмента, гарантируя, что оно станет частью состояния фрагмента, поэтому вам не нужно беспокоиться об изменениях конфигурации самостоятельно - инфраструктура сделает это за вас.
Итак, давайте изменим MainActivity
реализовать наш пользовательский интерфейс и использовать его newInstance
метод:
public class MainActivity extends FragmentActivity implements TimePickerFragment.TimePickerDialogListener {
private static final int START_TIME_PICKER_ID = 1;
private static final int END_TIME_PICKER_ID = 2;
public void InputStartTime(View v) {
// supply the appropriate id - I'm assuming you'll be adding an InputEndTime method somewhere that will then supply END_TIME_PICKER_ID
DialogFragment newFragment = TimePickerFragment.newInstance(START_TIME_PICKER_ID);
newFragment.show(getSupportFragmentManager(), "timePicker");
}
@Override public void onTimeSet(int id, TimePicker view, int hourOfDay, int minute) {
Log.i("TimePicker", "Time picker set from id " + id + "!");
// here you can compare the id value to figure out what picker this data came from
}
}
Последнее замечание: я набрал это прямо в своем браузере, так что будьте в курсе любых очевидных опечаток.
Я сделал код использовать его.
public class TimePickerFragment extends DialogFragment{
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
// Use the current time as the default values for the picker
final Calendar c = Calendar.getInstance();
int hour = c.get(Calendar.HOUR_OF_DAY);
int minute = c.get(Calendar.MINUTE);
// Create a new instance of TimePickerDialog and return it
return new TimePickerDialog(getActivity(), (MainActivity)getActivity(), hour, minute, false);
}
}
public class MainActivity extends FragmentActivity implements TimePickerDialog.OnTimeSetListener{
public void InputStartTime(View v) {
DialogFragment newFragment = new TimePickerFragment();
newFragment.show(getSupportFragmentManager(), "timePicker");
}
@Override
public void onTimeSet(TimePicker view, int hourOfDay, int minute) {
// TODO Auto-generated method stub
Log.i("TimePicker", "Time picker set!");
}
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.activity_main, menu);
return true;
}
}