TimePicker onTimeSet不会被调用 [英] TimePicker onTimeSet not being called

查看:203
本文介绍了TimePicker onTimeSet不会被调用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用的是时间选择器,让用户输入自己需要的时间做了具体的任务,我使用的DialogFragment类,它提供了与旧的Andr​​oid版本的向后兼容性的支持库。

下面是我的code创建TimePickerFragment类,在一个单独的文件中创建,来自的 http://developer.android.com/guide/topics/ui/controls/pickers.html

 包com.calls.only;
进口的java.util.Calendar;
进口android.app.Dialog;
进口android.app.TimePickerDialog;
进口android.os.Bundle;
进口android.support.v4.app.DialogFragment;
进口android.widget.TimePicker;


公共类TimePickerFragment扩展DialogFragment
                            实现TimePickerDialog.OnTimeSetListener {

    @覆盖
    公共对话onCreateDialog(包savedInstanceState){
        //使用当前时间作为选择器的默认值
        最后的日历C = Calendar.getInstance();
        INT小时= c.get(Calendar.HOUR_OF_DAY);
        INT分钟= c.get(Calendar.MINUTE);

        //创建TimePickerDialog的新实例,并将其返回
        返回新TimePickerDialog(getActivity(),这一点,小时,分钟,FALSE);
    }

    公共无效onTimeSet(TimePicker观点,诠释hourOfDay,INT分钟){
        //做一些与用户所选择的时间
    }
}
 

主要活动:

 包com.calls.only;


进口的java.util.Calendar;
进口java.util.TimeZone中;
进口android.os.Bundle;
进口android.app.AlarmManager;
进口android.app.PendingIntent;
进口android.content.Context;
进口android.content.Intent;
进口android.support.v4.app.FragmentActivity;
进口android.support.v4.app.DialogFragment;
进口android.view.Menu;
进口android.view.View;
进口android.widget.RadioButton;
进口android.widget.TextView;

公共类MainActivity扩展FragmentActivity {

公共无效InputStartTime(视图v){
    DialogFragment newFragment =新TimePickerFragment();
    newFragment.show(getSupportFragmentManager(),timePicker);

}

私人TimePickerDialog.OnTimeSetListener mTimeSetListener =
        新TimePickerDialog.OnTimeSetListener(){
                    //重写onTimeSet导致一个错误,请参阅以下
            公共无效onTimeSet(TimePicker观点,诠释hourOfDay,INT分钟){
               Log.i(TimePicker,时间选取一套!);
            }
        };

公共无效的onCreate(包savedInstanceState){
    super.onCreate(savedInstanceState);
    的setContentView(R.layout.activity_main);

}

@覆盖
公共布尔onCreateOptionsMenu(功能菜单){
    。getMenuInflater()膨胀(R.menu.activity_main,菜单);
    返回true;
}
}
 

在onTimeset方法不会被调用,因为我可以从日志中看到,如果我尝试重写这个方法,我得到的错误: 型新TimePickerDialog.OnTimeSetListener的方法onTimeSet(TimePicker,INT,INT)(){}必须覆盖一个超类方法

谁能告诉我是什么问题? 我一直在试图弄明白,这给我留下了太多的无奈!

解决方案
  

在onTimeset方法不会被调用,因为我可以从日志中看到

嗯,那是因为当你创建 TimePickerDialog ,您提供的片段 OnTimeSetListener

 返回新TimePickerDialog(getActivity(),这一点,小时,分钟,FALSE);
                                             ^
 

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

您可以很容易地通过两种铸造片段附着到活动中解决这个问题您 MainActivity ,或者,如果你preFER更多的东西可重复使用的,有它的回调通过一个接口。在这种情况下,你可以重复使用 OnTimeSetListener 界面,但你也可以设置自己的,例如,通过在日历对象返回到活动中,而不是原始小时/分钟值。

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

 公共类TimePickerFragment扩展DialogFragment {

    @覆盖公共对话onCreateDialog(包savedInstanceState){
        // ...省略

        如果(!(getActivity()的instanceof OnTimeSetListener))抛出新IllegalStateException异常(活动应实施OnTimeSetListener!);
        OnTimeSetListener timeSetListener =(OnTimeSetListener)getActivity();

        //创建TimePickerDialog的新实例,并将其返回
        返回新TimePickerDialog(getActivity(),timeSetListener,小时,分钟,FALSE);
    }
}
 

,然后让 MainActivity 实现同样的接口,使用匿名内部类的代替:

 公共类MainActivity扩展FragmentActivity实现TimePickerDialog.OnTimeSetListener {

    @覆盖公共无效onTimeSet(TimePicker观点,诠释hourOfDay,INT分钟){
        Log.i(TimePicker,时间选取一套!);
    }
}
 


更新:正如在评论中,为多个采摘启用的支持,你有几种选择。之一是跟踪什么对话框被显示在主机的活动;一个布尔会做很好,如果你只需要两个选择器来区分,否则枚举是实施两个以上的国家以适当的方式。你要确保在配置更改保留这条信息虽然...

不过,我倒是preFER是做,是为了能够识别在 onTimeSet(...)返回的结果的来源提供一个id到每一个选择器。该ID随后包括在结果,这样我们就可以知道它是从哪里来的。我将概述如下总体思路:

 公共类TimePickerFragment扩展DialogFragment实现OnTimeSetListener {

    私人诠释MID;
    私人TimePickerDialogListener mListener;

    私有静态TimePickerFragment的newInstance(INT ID){
        捆绑的args =新包();
        args.putInt(picker_id,身份证);
        TimePickerFragment片段=新TimePickerFragment();
        fragment.setArguments(参数);
        返回片段;
    }

    @覆盖公共对话onCreateDialog(包savedInstanceState){
        // ...省略

        。MID = getArguments()调用getInt(picker_id);
        mListener = getActivity()的instanceof TimePickerDialogListener? (TimePickerDialogListener)getActivity():空;

        //创建TimePickerDialog的新实例,并将其返回
        返回新TimePickerDialog(getActivity(),这一点,小时,分钟,FALSE);
    }

    @覆盖公共无效onTimeSet(TimePicker观点,诠释hourOfDay,INT分钟){
        如果(mListener!= NULL)mListener.onTimeSet(MID,查看,hourOfDay,分钟);
    }

    公共静态接口TimePickerDialogListener {
        公共无效onTimeSet(INT ID,TimePicker观点,诠释hourOfDay,INT分钟);
    }

}
 

我们上面已经改变就是有对话框本身注册为 OnTimeSetListener ,为此,它就会传递的数据通过 TimePickerDialogListener ,提供托管活动实现该接口。所以,这就是我们需要做的下一个步骤。另外请注意,我添加了一个静态便捷方法来创建一个新的 TimePickerFragment 接受一个I​​D。该值将被设置为参数的片段,以确保它成为片段的状态的一部分,所以你不必担心配置改变自己 - 框架会为你做

因此​​,让我们改变 MainActivity 来实现我们的自定义接口,并将其使用的newInstance 方法:

 公共类MainActivity扩展FragmentActivity实现TimePickerFragment.TimePickerDialogListener {

    私有静态最终诠释START_TIME_PICKER_ID = 1;
    私有静态最终诠释END_TIME_PICKER_ID = 2;

    公共无效InputStartTime(视图v){
        //提供相应的ID  - 我假设你会添加InputEndTime方法的地方,然后将提供END_TIME_PICKER_ID
        DialogFragment newFragment = TimePickerFragment.newInstance(START_TIME_PICKER_ID);
        newFragment.show(getSupportFragmentManager(),timePicker);
    }

    @覆盖公共无效onTimeSet(INT ID,TimePicker观点,诠释hourOfDay,INT分钟){
        Log.i(TimePicker,时间选择器从ID设为+编号+!);

        //这里你可以比较值id找出选取器从这个数据来
    }
}
 

只是最后要注意的:我打这个直接到我的浏览器,所以要知道任何明显的错别字

I'm using a time picker to let the user enter his desired time to do a specific task, I'm using the DialogFragment class that's available in the support library for backward compatibility with older Android versions.

Here is my code to create the TimePickerFragment class, created in a seperate file, taken from: 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
    }
}

Main Activity:

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

the onTimeset method is not being called as I can see from the log, if I try to override this method, I get the error: "The method onTimeSet(TimePicker, int, int) of type new TimePickerDialog.OnTimeSetListener(){} must override a superclass method"

can anyone tell me what the problem is? I've been trying to figure it out and it left me with too much frustration!

解决方案

the onTimeset method is not being called as I can see from the log

Well, that's because when you create the TimePickerDialog, you supply the fragment as OnTimeSetListener:

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

In other words: you're not seeing the log statement because the mTimeSetListener variable in your activity never gets set as listener to the dialog you create in the fragment.

You can easily fix this by either casting the activity the fragment is attached to to your MainActivity, or, if you prefer something more reusable, have it callback through an interface. In this case you could reuse the OnTimeSetListener interface, but you could also set up your own that, for instance, passes on a Calendar object back to the activity rather than the raw hour/minute values.

In it's most basic form, it would look somewhat like this:

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

And then have your MainActivity implement that same interface, in stead of using an anonymous innerclass:

public class MainActivity extends FragmentActivity implements TimePickerDialog.OnTimeSetListener { 

    @Override public void onTimeSet(TimePicker view, int hourOfDay, int minute) {
        Log.i("TimePicker", "Time picker set!");
    }
}


Update: As mentioned in the comments, to enabled support for multiple pickers, you have several options. One is to keep track of what dialog is displayed in the hosting activity; a boolean would do fine if you only need to differentiate between two pickers, otherwise an enum would be an appropriate way to implement more than two states. You'll want to make sure that this piece of information is retained during configuration changes though...

However, what I'd prefer is to do, is to be able to identify the source of the result returned in onTimeSet(...) by supplying an id to every picker. That id is then included in the result so that we can tell where it came from. I'll outline the general idea below:

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

}

What we've changed above is to have the dialog itself be registered as OnTimeSetListener, for which it will then pass on data through the TimePickerDialogListener, provided the hosting activity implements that interface. So that's what we need to do in the next step. Also, note that I've added a static convenience method to create a new TimePickerFragment that takes an id. This value will be set as argument to the fragment, ensuring that it becomes part of the fragment's state, so you don't have to worry about configuration changes yourself - the framework will do that for you.

So let's change MainActivity to implement our custom interface, and have it use the newInstance method:

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

Just one final note: I typed this directly into my browser, so be aware of any obvious typos.

这篇关于TimePicker onTimeSet不会被调用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆