没有调用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方法,因为我可以从日志中看到,如果我尝试覆盖此方法,我会收到错误:“new TimePickerDialog.OnTimeSetListener(){}类型的方法onTimeSet(TimePicker,int,int)必须覆盖超类方法“

谁能告诉我这是什么问题? 我一直在试图解决这个问题,这让我感到非常沮丧!

我没有调用onTimeset方法,因为我可以从日志中看到

那么,那是因为当你创建TimePickerDialog ,你将片段作为OnTimeSetListener

 return new TimePickerDialog(getActivity(), this, hour, minute, false); ^ 

换句话说:您没有看到日志语句,因为活动中的mTimeSetListener变量永远不会被设置为您在片段中创建的对话框的侦听器。

您可以通过将片段附加到MainActivity的活动强制转换,或者如果您更喜欢可重用的东西,通过接口进行回调来轻松解决此问题。 在这种情况下,您可以重用OnTimeSetListener接口,但您也可以设置自己的接口,例如,将Calendar对象传递回活动而不是原始小时/分钟值。

在它最基本的forms中,它看起来有点像这样:

 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!"); } } 

更新:如评论中所述,要启用对多个选择器的支持,您有几种选择。 一个是跟踪托管活动中显示的对话框; 如果您只需要区分两个选择器,布尔值就可以了,否则枚举将是实现两个以上状态的合适方法。 您需要确保在配置更改期间保留此信息,但…

但是,我更喜欢做的是,能够通过向每个选择器提供一个id来识别onTimeSet(...)返回的结果的来源。 然后将该ID包含在结果中,以便我们可以知道它来自何处。 我将概述以下总体思路:

 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传递数据,前提是托管活动实现了该接口。 这就是我们下一步需要做的事情。 另外,请注意我添加了一个静态便捷方法来创建一个带有id的新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; } }