0

使用 DialogFragment 在 Fragment 中实现 TimePicker 对话框并获取 ClassCastException

日志猫:

02-15 02:44:29.199: E/AndroidRuntime(1297): FATAL EXCEPTION: main
02-15 02:44:29.199: E/AndroidRuntime(1297): Process: com.example.datetimeabs, PID: 1297
02-15 02:44:29.199: E/AndroidRuntime(1297): java.lang.ClassCastException: com.example.datetimeabs.MainActivity@b1d75900 must implement com.example.datetimeabs.TimePickerFragment$TimePickedListener
02-15 02:44:29.199: E/AndroidRuntime(1297):     at com.example.datetimeabs.TimePickerFragment.onAttach(TimePickerFragment.java:40)
02-15 02:44:29.199: E/AndroidRuntime(1297):     at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:883)
02-15 02:44:29.199: E/AndroidRuntime(1297):     at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1104)
02-15 02:44:29.199: E/AndroidRuntime(1297):     at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:682)
02-15 02:44:29.199: E/AndroidRuntime(1297):     at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1460)
02-15 02:44:29.199: E/AndroidRuntime(1297):     at android.support.v4.app.FragmentManagerImpl$1.run(FragmentManager.java:440)
02-15 02:44:29.199: E/AndroidRuntime(1297):     at android.os.Handler.handleCallback(Handler.java:733)
02-15 02:44:29.199: E/AndroidRuntime(1297):     at android.os.Handler.dispatchMessage(Handler.java:95)
02-15 02:44:29.199: E/AndroidRuntime(1297):     at android.os.Looper.loop(Looper.java:136)
02-15 02:44:29.199: E/AndroidRuntime(1297):     at android.app.ActivityThread.main(ActivityThread.java:5017)
02-15 02:44:29.199: E/AndroidRuntime(1297):     at java.lang.reflect.Method.invokeNative(Native Method)
02-15 02:44:29.199: E/AndroidRuntime(1297):     at java.lang.reflect.Method.invoke(Method.java:515)
02-15 02:44:29.199: E/AndroidRuntime(1297):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:779)
02-15 02:44:29.199: E/AndroidRuntime(1297):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:595)
02-15 02:44:29.199: E/AndroidRuntime(1297):     at dalvik.system.NativeStart.main(Native Method)
02-15 02:44:32.679: I/Process(1297): Sending signal. PID: 1297 SIG: 9

我正在关注本教程: http ://www.lukehorvat.com/blog/android-time-picker-example/你也可以看到我在代码中使用的TimePickerFragment.java !

FragmentTab1.java:

public class FragmentTab1 extends SherlockFragment  implements TimePickedListener{

    Button buttonDate;  
    Button buttonTime;  

    TextView textDate;  
    TextView textTime;  

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        View rootView = inflater.inflate(R.layout.fragmenttab1, container, false);

        buttonDate = (Button) rootView.findViewById(R.id.btnDate);
        buttonTime = (Button) rootView.findViewById(R.id.btnTime);        

        textDate = (TextView) rootView.findViewById(R.id.txtDate);
        textTime = (TextView) rootView.findViewById(R.id.txtTime);  

        //  calendar class get the current instance of android phone clock
         Calendar c = Calendar.getInstance();

         // a formatted object for date and time
         SimpleDateFormat sdfTime = new SimpleDateFormat("HH:mm a");

         // save date and time in string object.
         String strTime = sdfTime.format(c.getTime());
         textTime.setText(strTime);

         SimpleDateFormat sdfDate = new SimpleDateFormat("dd-MMM-yyyy");
         String strDate = sdfDate.format(c.getTime());
         textDate.setText(strDate);

         buttonTime.setOnClickListener(new OnClickListener()
         {
             @Override
             public void onClick(View v)
             {
                 // show the time picker dialog
                 TimePickerFragment newFragment = new TimePickerFragment();
                 newFragment.show(getActivity().getSupportFragmentManager(), "timePicker");
             }
         });


        return rootView;
    }

    @Override
    public void onTimePicked(Calendar time)
    {
        // display the selected time in the TextView
        textTime.setText(DateFormat.format("HH:mm a", time));
    }

}

MainActivity.java:-

public class MainActivity extends SherlockFragmentActivity{
    // Declare Variables    
    private FragmentTabHost mTabHost;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // Set the view from main_fragment.xml
        setContentView(R.layout.main_fragment);

        // Locate android.R.id.tabhost in main_fragment.xml
        mTabHost = (FragmentTabHost) findViewById(android.R.id.tabhost);

        // Create the tabs in main_fragment.xml
        mTabHost.setup(this, getSupportFragmentManager(), R.id.tabcontent);

        // Create Tab1 with a custom image in res folder
        mTabHost.addTab(mTabHost.newTabSpec("tab1").setIndicator("", getResources().getDrawable(R.drawable.tab1)),
                FragmentTab1.class, null);

        // Create Tab2
        mTabHost.addTab(mTabHost.newTabSpec("tab2").setIndicator("Tab2"),
                FragmentTab2.class, null);

        // Create Tab3
        mTabHost.addTab(mTabHost.newTabSpec("tab3").setIndicator("Tab3"),
                FragmentTab3.class, null);
    }
}

TimePickerFragment.java:-

public class TimePickerFragment extends DialogFragment implements TimePickerDialog.OnTimeSetListener
{
private TimePickedListener mListener;

@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, DateFormat.is24HourFormat(getActivity()));
}

@Override
public void onAttach(Activity activity)
{
// when the fragment is initially shown (i.e. attached to the activity), cast the activity to the callback interface type
super.onAttach(activity);
try
{
mListener = (TimePickedListener) activity;
}
catch (ClassCastException e)
{
throw new ClassCastException(activity.toString() + " must implement " + TimePickedListener.class.getName());
}
}

@Override
public void onTimeSet(TimePicker view, int hourOfDay, int minute)
{
// when the time is selected, send it to the activity via its callback interface method
Calendar c = Calendar.getInstance();
c.set(Calendar.HOUR_OF_DAY, hourOfDay);
c.set(Calendar.MINUTE, minute);

mListener.onTimePicked(c);
}

public static interface TimePickedListener
{
public void onTimePicked(Calendar time);
}
}

编辑的代码: 归功于@Luksprog

FragmentTab1.java:

public class FragmentTab1 extends SherlockFragment{

Button buttonDate;  
Button buttonTime;  

TextView textDate;  
TextView textTime;  

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {
    View rootView = inflater.inflate(R.layout.fragmenttab1, container, false);

    buttonDate = (Button) rootView.findViewById(R.id.btnDate);
    buttonTime = (Button) rootView.findViewById(R.id.btnTime);        

    textDate = (TextView) rootView.findViewById(R.id.txtDate);
    textTime = (TextView) rootView.findViewById(R.id.txtTime);  

    //  calendar class get the current instance of android phone clock
     Calendar c = Calendar.getInstance();

     // a formatted object for date and time
     SimpleDateFormat sdfTime = new SimpleDateFormat("HH:mm a");

     // save date and time in string object.
     String strTime = sdfTime.format(c.getTime());
     textTime.setText(strTime);

     SimpleDateFormat sdfDate = new SimpleDateFormat("dd-MMM-yyyy");
     String strDate = sdfDate.format(c.getTime());
     textDate.setText(strDate);

     buttonTime.setOnClickListener(new OnClickListener()
     {
         @Override
         public void onClick(View v)
         {
             // show the time picker dialog
             TimePickerFragment newFragment = new TimePickerFragment();
             newFragment.show(getActivity().getSupportFragmentManager(), "timePicker");
         }
     });


    return rootView;
}

public void onTimePicked(Calendar time)
{
    SimpleDateFormat sdfTime = new SimpleDateFormat("HH:mm a");
    String strTime = sdfTime.format(time.getTime());
    Log.i("onTimePicked >>> ", strTime);
    // display the selected time in the TextView
    textTime.setText(DateFormat.format("HH:mm a", time));
 }

}

MainActivity.java:

public class MainActivity extends SherlockFragmentActivity implements TimePickedListener {
    // Declare Variables    
    private FragmentTabHost mTabHost;

    FragmentTab1 fragmentTab1;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // Set the view from main_fragment.xml
        setContentView(R.layout.main_fragment);

        fragmentTab1 = new FragmentTab1();

        // Locate android.R.id.tabhost in main_fragment.xml
        mTabHost = (FragmentTabHost) findViewById(android.R.id.tabhost);

        // Create the tabs in main_fragment.xml
        mTabHost.setup(this, getSupportFragmentManager(), R.id.tabcontent);

        // Create Tab1 with a custom image in res folder
        mTabHost.addTab(mTabHost.newTabSpec("tab1").setIndicator("", getResources().getDrawable(R.drawable.tab1)),
                FragmentTab1.class, null);

        // Create Tab2
        mTabHost.addTab(mTabHost.newTabSpec("tab2").setIndicator("Tab2"),
                FragmentTab2.class, null);

        // Create Tab3
        mTabHost.addTab(mTabHost.newTabSpec("tab3").setIndicator("Tab3"),
                FragmentTab3.class, null);
    }

    @Override
    public void onTimePicked(Calendar time) {
        // TODO Auto-generated method stub
        fragmentTab1.onTimePicked(time);
    }

}

例外线:

 textTime.setText(DateFormat.format("HH:mm a", time));

新日志:

02-15 04:18:40.149: D/dalvikvm(1469): GC_FOR_ALLOC freed <1K, 4% free 5141K/5324K, paused 42ms, total 42ms
02-15 04:18:40.349: I/Choreographer(1469): Skipped 126 frames!  The application may be doing too much work on its main thread.
02-15 04:18:40.939: I/Choreographer(1469): Skipped 46 frames!  The application may be doing too much work on its main thread.
02-15 04:18:49.669: I/onTimePicked >>>(1469): 08:25 AM
02-15 04:18:49.669: D/AndroidRuntime(1469): Shutting down VM
02-15 04:18:49.729: W/dalvikvm(1469): threadid=1: thread exiting with uncaught exception (group=0xb1a94ba8)
02-15 04:18:49.739: E/AndroidRuntime(1469): FATAL EXCEPTION: main
02-15 04:18:49.739: E/AndroidRuntime(1469): Process: com.example.datetimeabs, PID: 1469
02-15 04:18:49.739: E/AndroidRuntime(1469): java.lang.NullPointerException
02-15 04:18:49.739: E/AndroidRuntime(1469):     at com.example.datetimeabs.FragmentTab1.onTimePicked(FragmentTab1.java:73)
02-15 04:18:49.739: E/AndroidRuntime(1469):     at com.example.datetimeabs.MainActivity.onTimePicked(MainActivity.java:47)
02-15 04:18:49.739: E/AndroidRuntime(1469):     at com.example.datetimeabs.TimePickerFragment.onTimeSet(TimePickerFragment.java:52)
02-15 04:18:49.739: E/AndroidRuntime(1469):     at android.app.TimePickerDialog.tryNotifyTimeSet(TimePickerDialog.java:130)
02-15 04:18:49.739: E/AndroidRuntime(1469):     at android.app.TimePickerDialog.onClick(TimePickerDialog.java:115)
02-15 04:18:49.739: E/AndroidRuntime(1469):     at com.android.internal.app.AlertController$ButtonHandler.handleMessage(AlertController.java:166)
02-15 04:18:49.739: E/AndroidRuntime(1469):     at android.os.Handler.dispatchMessage(Handler.java:102)
02-15 04:18:49.739: E/AndroidRuntime(1469):     at android.os.Looper.loop(Looper.java:136)
02-15 04:18:49.739: E/AndroidRuntime(1469):     at android.app.ActivityThread.main(ActivityThread.java:5017)
02-15 04:18:49.739: E/AndroidRuntime(1469):     at java.lang.reflect.Method.invokeNative(Native Method)
02-15 04:18:49.739: E/AndroidRuntime(1469):     at java.lang.reflect.Method.invoke(Method.java:515)
02-15 04:18:49.739: E/AndroidRuntime(1469):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:779)
02-15 04:18:49.739: E/AndroidRuntime(1469):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:595)
02-15 04:18:49.739: E/AndroidRuntime(1469):     at dalvik.system.NativeStart.main(Native Method)
4

1 回答 1

1

使用 DialogFragment 在 Fragment 中实现 TimePicker 对话框并获取 ClassCastException

异常告诉您MainActivity需要实现TimePickerFragment$TimePickedListener接口并提供onTimePicked()方法的实现。

新日志:

出现该异常是因为您没有与片段正确交互,在onTimePicked回调中您调用onTimePicked(time)了错误的第一个片段选项卡。该片段不是FragmentTabHost用于其第一个选项卡的片段,它只是您手动实例化的片段(使用fragmentTab1 = new FragmentTab1();)。这个手动实例化的片段没有附加到Activity并且没有视图,因为没有调用它的回调。

要访问正确的片段,请使用FragmentManager首先找到它:

@Override
public void onTimePicked(Calendar time) {
    FragmentTab1 ft1 = (FragmentTab1) getSupportFragmentManager().findFragmentByTag("tab1");
    fragmentTab1.onTimePicked(time);
}
于 2014-02-15T10:06:46.667 回答