在片段内实现DatePicker

问题描述:

我有下面的代码来显示一个Activity中的日期选择器,但是当我试图将我的活动转换为Fragment时,我收到错误。我无法真正看到代码中的任何区别,只能在SO中实现DialogFragment。在片段内实现DatePicker

请你指出我错过了什么?

MainFragment:

public class AddEntryFragment extends Fragment implements DatePickerFragment.TheListener{ 
    EditText datpurchased; 
    public AddEntryFragment(){} 

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

    @Override 
    public void onStart() { 
     super.onStart(); 
     datpurchased = (EditText) getView().findViewById(R.id.datepurchased); 
     datpurchased.setOnClickListener(onClickListener); 
    } 

    private OnClickListener onClickListener = new OnClickListener() { 
     @Override 
     public void onClick(View v) { 
      switch(v.getId()){ 
       case R.id.datepurchased: 
        showdate(v); 
       break; 
       default: 
       break; 
      } 

     } 
    }; 

    public void showdate(View v) { 
     DialogFragment newFragment = new DatePickerFragment(); 
     Bundle bundle = new Bundle(); 
     bundle.putString("dateAsText",datpurchased.getText().toString()); 
     newFragment.setArguments(bundle); 
     newFragment.show(getFragmentManager(), "datePicker"); 
    } 

    public void returnDate(String date) { 
     datpurchased.setText(date); 
    } 
} 

DatePickerFragment:

public class DatePickerFragment extends DialogFragment implements DatePickerDialog.OnDateSetListener { 
    TheListener listener; 

    public interface TheListener{ 
     public void returnDate(String date); 
    } 

    @Override 
    public Dialog onCreateDialog(Bundle savedInstanceState){ 
     Bundle bundle = getArguments(); 
     String date = bundle.getString("dateAsText"); 
     int year, month, day; 
     SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd",Locale.US); 
     df.setLenient(false); 
     Date d = null; 
     Calendar c=Calendar.getInstance(); 
     try { 
      d = df.parse(date); 
      c.setTime(d); 
     } catch (ParseException e) { 
      //e.printStackTrace(); 
     } 
     year=c.get(Calendar.YEAR); 
     month=c.get(Calendar.MONTH); 
     day=c.get(Calendar.DAY_OF_MONTH); 
     listener = (TheListener) getActivity(); 
     return new DatePickerDialog(getActivity(), this, year, month, day); 
    } 

    public void onDateSet(DatePicker view, int year, int month, int day){ 
     Calendar c = Calendar.getInstance(); 
     c.set(year, month, day); 

     SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd",Locale.US); 
     String formattedDate = sdf.format(c.getTime()); 
     if (listener != null) 
     { 
      listener.returnDate(formattedDate); 

     } 
    } 
} 

logcat的:

12-18 23:35:41.094: D/AndroidRuntime(1058): Shutting down VM 
12-18 23:35:41.094: W/dalvikvm(1058): threadid=1: thread exiting with uncaught exception (group=0xb4a65b90) 
12-18 23:35:41.124: E/AndroidRuntime(1058): FATAL EXCEPTION: main 
12-18 23:35:41.124: E/AndroidRuntime(1058): Process: com.migrationdesk.mylibman, PID: 1058 
12-18 23:35:41.124: E/AndroidRuntime(1058): java.lang.ClassCastException: com.migrationdesk.mylibman.NavContainer cannot be cast to com.migrationdesk.mylibman.DatePickerFragment$TheListener 
12-18 23:35:41.124: E/AndroidRuntime(1058):  at com.migrationdesk.mylibman.DatePickerFragment.onCreateDialog(DatePickerFragment.java:41) 
12-18 23:35:41.124: E/AndroidRuntime(1058):  at android.app.DialogFragment.getLayoutInflater(DialogFragment.java:398) 
12-18 23:35:41.124: E/AndroidRuntime(1058):  at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:890) 
12-18 23:35:41.124: E/AndroidRuntime(1058):  at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:1062) 
12-18 23:35:41.124: E/AndroidRuntime(1058):  at android.app.BackStackRecord.run(BackStackRecord.java:684) 
12-18 23:35:41.124: E/AndroidRuntime(1058):  at android.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1447) 
12-18 23:35:41.124: E/AndroidRuntime(1058):  at android.app.FragmentManagerImpl$1.run(FragmentManager.java:443) 
12-18 23:35:41.124: E/AndroidRuntime(1058):  at android.os.Handler.handleCallback(Handler.java:733) 
12-18 23:35:41.124: E/AndroidRuntime(1058):  at android.os.Handler.dispatchMessage(Handler.java:95) 
12-18 23:35:41.124: E/AndroidRuntime(1058):  at android.os.Looper.loop(Looper.java:137) 
12-18 23:35:41.124: E/AndroidRuntime(1058):  at android.app.ActivityThread.main(ActivityThread.java:4998) 
12-18 23:35:41.124: E/AndroidRuntime(1058):  at java.lang.reflect.Method.invokeNative(Native Method) 
12-18 23:35:41.124: E/AndroidRuntime(1058):  at java.lang.reflect.Method.invoke(Method.java:515) 
12-18 23:35:41.124: E/AndroidRuntime(1058):  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:777) 
12-18 23:35:41.124: E/AndroidRuntime(1058):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:593) 
12-18 23:35:41.124: E/AndroidRuntime(1058):  at dalvik.system.NativeStart.main(Native Method) 

试试这个S充足的代码....

public class student extends Fragment { 
    public void onCreate(Bundle savedInstanceState){ 
     super.onCreate(savedInstanceState); 
    } 

    public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) { 
     View view= inflater.inflate(R.layout.layout_main, container, false); 
     return view; 
    } 

    public void onViewCreated(View view, Bundle savedInstanceState) { 
     super.onViewCreated(view, savedInstanceState); 
     edittext.setOnClickListener(new OnClickListener() { 
       @Override 
       public void onClick(View v) { 
        // TODO Auto-generated method stub 
        showDatePicker(); 
       } 
      }); 
    } 

    private void showDatePicker() { 
     DatePickerFragment date = new DatePickerFragment(); 
     /** 
     * Set Up Current Date Into dialog 
     */ 
     Calendar calender = Calendar.getInstance(); 
     Bundle args = new Bundle(); 
     args.putInt("year", calender.get(Calendar.YEAR)); 
     args.putInt("month", calender.get(Calendar.MONTH)); 
     args.putInt("day", calender.get(Calendar.DAY_OF_MONTH)); 
     date.setArguments(args); 
     /** 
     * Set Call back to capture selected date 
     */ 
     date.setCallBack(ondate); 
     date.show(getFragmentManager(), "Date Picker"); 
    } 

    OnDateSetListener ondate = new OnDateSetListener() { 

     public void onDateSet(DatePicker view, int year, int monthOfYear, 
      int dayOfMonth) { 

      edittext.setText(String.valueOf(dayOfMonth) + "-" + String.valueOf(monthOfYear+1) 
       + "-" + String.valueOf(year)); 
     } 
    };    
} 

创建另一个类DatePickerFragment。

public class DatePickerFragment extends DialogFragment { 
    OnDateSetListener ondateSet; 
    private int year, month, day; 

    public DatePickerFragment() {} 

    public void setCallBack(OnDateSetListener ondate) { 
     ondateSet = ondate; 
    } 

    @SuppressLint("NewApi") 
    @Override 
    public void setArguments(Bundle args) { 
     super.setArguments(args); 
     year = args.getInt("year"); 
     month = args.getInt("month"); 
     day = args.getInt("day"); 
    } 

    @Override 
    public Dialog onCreateDialog(Bundle savedInstanceState) { 
     return new DatePickerDialog(getActivity(), ondateSet, year, month, day); 
    } 
} 
+0

很好的例子,运作良好。 –

+0

k.thanks for trying .. – Amritha

+2

有一种方法需要更少的代码。你可以使用setTargetFragment(student.class,0)和getTargetFragment()来得到相同的结果。看到这个http://lookingintoandroid.blogspot.com/2016/04/how-to-get-date-from-datepickerdialog.html – SajithK

我使用了实现Date Listeners的AppCompatActivity。由于我需要编写日期范围选择器,所以碎片成为必需品。

对于容器的活动,这是类声明:

public class AppCompatDateRange extends AppCompatActivity implements 
    DateIniRangeFragment.OnDateIniSelectedListener, DateFimRangeFragment.OnDateFimSelectedListener 

而对于回调接口:

@Override 
public void onDateIniSelected(String dataIni) { 
    Log.i("data inicial:", dataIni); 
} 

@Override 
public void onDateFimSelected(String dataFim) { 
    Log.i("data final:", dataFim); 
} 

的回调是字符串,因为日期是在查询中选择PARAMS。

的片段的代码(基于初始日期片段):

public class DateIniRangeFragment extends Fragment { 
OnDateIniSelectedListener callbackIni; 

private DatePicker startDatePicker; 

public DateIniRangeFragment() { 
    ///required empty constructor 
} 

@Override 
public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
} 

///through this interface the fragment sends data to the container activity 
public interface OnDateIniSelectedListener { 
    void onDateIniSelected(String dataIni); 
} 

@Override 
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 
    ///layout for the fragment 
    View v = inflater.inflate(R.layout.date_ini_fragment, container, false); 

    ///initial date for the picker, in this case, current date 
    startDatePicker = (DatePicker) v.findViewById(R.id.start_date_picker_appcompat); 
    Calendar c = Calendar.getInstance(); 
    int ano = c.get(Calendar.YEAR); 
    int mes = c.get(Calendar.MONTH); 
    int dia = c.get(Calendar.DAY_OF_MONTH); 
    startDatePicker.setSpinnersShown(false); 
    startDatePicker.init(ano, mes, dia, dateSetListener); 

    return v; 
} 

///listener that receives the selected date 
private DatePicker.OnDateChangedListener dateSetListener = new DatePicker.OnDateChangedListener() { 
    public void onDateChanged(DatePicker view, int year, int monthOfYear, int dayOfMonth) { 
     if (view.isShown()) { ///if the datepicker is on the screen 
      String sDataIni = year + "-" + (monthOfYear + 1) + "-" + dayOfMonth; 
      callbackIni.onDateIniSelected(sDataIni); //apply date to callback, string format 
     } 
    } 
}; 

@Override 
public void onAttach(Activity activity) { 
    super.onAttach(activity); 

    /* 
    * this function guarantees that the container activity implemented the callback interface 
    * */ 
    try { 
     callbackIni = (OnDateIniSelectedListener) activity; 
    } catch (ClassCastException e) { 
     throw new ClassCastException(activity.toString() + " deve implementar OnDateIniSelectedListener"); 
    } 
} 

}

要撰写的容器+片段,我使用的ViewPager(程序兼容性)具有延伸自定义类FragmentPagerAdapter。没有对话框。

import android.app.Activity; 
import android.app.FragmentManager; 
import android.content.Context; 
import android.content.DialogInterface; 
import android.content.SharedPreferences; 
import android.graphics.Color; 
import android.graphics.drawable.GradientDrawable; 
import android.net.Uri; 
import android.os.Bundle; 
import android.support.v4.app.Fragment; 
import android.support.v7.app.AppCompatActivity; 
import android.support.v7.widget.Toolbar; 
import android.view.LayoutInflater; 
import android.view.View; 
import android.view.ViewGroup; 
import android.widget.Button; 
import android.widget.DatePicker; 
import android.widget.EditText; 
import android.widget.TextView; 
import android.widget.Toast; 

import com.nepal.peace.ilovemydiet.R; 
import com.wdullaer.materialdatetimepicker.Utils; 
import com.wdullaer.materialdatetimepicker.date.DatePickerDialog; 

import java.util.Calendar; 


/** 
* A simple {@link Fragment} subclass. 
* Activities that contain this fragment must implement the 
* {@link UserPhysicalCharacter.OnFragmentInteractionListener} interface 
* to handle interaction events. 
* Use the {@link UserPhysicalCharacter#newInstance} factory method to 
* create an instance of this fragment. 
*/ 
public class UserPhysicalCharacter extends Fragment { 
    // TODO: Rename parameter arguments, choose names that match 
    // the fragment initialization parameters, e.g. ARG_ITEM_NUMBER 
    private static final String ARG_PARAM1 = "param1"; 
    private static final String ARG_PARAM2 = "param2"; 

    EditText f_name, l_name, u_height, u_weight, u_obj_weight; 

    TextView u_birth; 

    SharedPreferences sharedpreferences; 
    public static final String MyPREFERENCES = "LoginData"; 


    // TODO: Rename and change types of parameters 
    private String mParam1; 
    private String mParam2; 

    private OnFragmentInteractionListener mListener; 

    /** 
    * Use this factory method to create a new instance of 
    * this fragment using the provided parameters. 
    * 
    * @param param1 Parameter 1. 
    * @param param2 Parameter 2. 
    * @return A new instance of fragment UserPhysicalCharacter. 
    */ 
    // TODO: Rename and change types and number of parameters 
    public static UserPhysicalCharacter newInstance(String param1, String param2) { 
     UserPhysicalCharacter fragment = new UserPhysicalCharacter(); 
     Bundle args = new Bundle(); 
     args.putString(ARG_PARAM1, param1); 
     args.putString(ARG_PARAM2, param2); 
     fragment.setArguments(args); 
     return fragment; 
    } 

    public UserPhysicalCharacter() { 
     // Required empty public constructor 
    } 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     if (getArguments() != null) { 
      mParam1 = getArguments().getString(ARG_PARAM1); 
      mParam2 = getArguments().getString(ARG_PARAM2); 
     } 
    } 

    @Override 
    public View onCreateView(LayoutInflater inflater, ViewGroup container, 
          Bundle savedInstanceState) { 
     // Inflate the layout for this fragment 

     View rootView = inflater.inflate(R.layout.fragment_relpace, container, false); 
     final UserPhysicalCharacter userPhysicalCharacter=new UserPhysicalCharacter(); 

     Toolbar toolbar = (Toolbar) rootView.findViewById(R.id.toolbar); 



     u_birth = (TextView) rootView.findViewById(R.id.birthday); 

     u_birth.setOnClickListener(new View.OnClickListener() { 
      @Override 
      public void onClick(View v) { 
       Calendar now = Calendar.getInstance(); 
       DatePickerDialog dpd = DatePickerDialog.newInstance(
         new DateListener(), 
         now.get(Calendar.YEAR), 
         now.get(Calendar.MONTH), 
         now.get(Calendar.DAY_OF_MONTH) 
       ); 
       dpd.setThemeDark(true); 
       dpd.vibrate(true); 
       dpd.dismissOnPause(true); 
       dpd.setAccentColor(Color.parseColor("#9C27B0")); 
       dpd.setTitle("DatePicker Title"); 
       dpd.show(getActivity().getFragmentManager(),"Datepickerdialog"); 
      } 
     }); 


     return rootView; 
    } 

    // TODO: Rename method, update argument and hook method into UI event 
    public void onButtonPressed(Uri uri) { 
     if (mListener != null) { 
      mListener.onFragmentInteraction(uri); 
     } 
    } 

    @Override 
    public void onAttach(Activity activity) { 
     super.onAttach(activity); 
     try { 
      mListener = (OnFragmentInteractionListener) activity; 
     } catch (ClassCastException e) { 
      throw new ClassCastException(activity.toString() 
        + " must implement OnFragmentInteractionListener"); 
     } 
    } 

    @Override 
    public void onDetach() { 
     super.onDetach(); 
     mListener = null; 
    } 






    /** 
    * This interface must be implemented by activities that contain this 
    * fragment to allow an interaction in this fragment to be communicated 
    * to the activity and potentially other fragments contained in that 
    * activity. 
    * <p/> 
    * See the Android Training lesson <a href= 
    * "http://developer.android.com/training/basics/fragments/communicating.html" 
    * >Communicating with Other Fragments</a> for more information. 
    */ 
    public interface OnFragmentInteractionListener { 
     // TODO: Update argument type and name 
     public void onFragmentInteraction(Uri uri); 
    } 

    public class DateListener implements DatePickerDialog.OnDateSetListener { 

     @Override 
     public void onDateSet(DatePickerDialog view, int year, int monthOfYear, int dayOfMonth) { 
      String date = dayOfMonth+"/"+(++monthOfYear)+"/"+year; 
      Toast.makeText(getActivity(),date, Toast.LENGTH_SHORT).show(); 
      u_birth.setText(date); 
     } 
    } 
} 

我得到了完全相同的铸造的错误,并寻找一个解决方案,但没有找到一个行之有效后,我决定拿出我自己的一个。

我的方法是使用一个小技巧。我没有试图让扩展DialogFragment的类接受我的Fragment作为DatePickerDialog.OnDateSetListener,而是允许DialogFragment类实现接口并接收回调。当回调被调用时,它会将它传递给我的Fragment,它也实现了相同的接口。实际上,DialogFragment类将转发回调。这里是DialogFragment类,你可能已经在其他很多的*帖子中看到过,除了它有一个公共方法setListeningActivity()。 setListeningActivity()需要一个片段,一个活动或任何实现DatePickerDialog.OnDateSetListener的类。这是DialogFragment类将被转发的任何回调的类。

public class DatePickerFragment extends DialogFragment implements DatePickerDialog.OnDateSetListener { 

    private DatePickerDialog.OnDateSetListener m_listener = null; 

    @Override 
    public Dialog onCreateDialog(Bundle savedInstanceState) { 
     final Calendar c = Calendar.getInstance(); 
     int year = c.get(Calendar.YEAR); 
     int month = c.get(Calendar.MONTH); 
     int day = c.get(Calendar.DAY_OF_MONTH); 

     return new DatePickerDialog(getActivity(), 
       this, 
       year, month, day); 
    } 

    public void setListeningActivity(DatePickerDialog.OnDateSetListener listener) 
    { 
     m_listener = listener; 
    } 

    @Override 
    public void onDateSet(DatePicker view, int year, int month, int day) { 
     if (m_listener != null) { 
      m_listener.onDateSet(view, year, month, day); 
     } 
    } 

接下来是使用它的代码:

public class AppPatientInfoFragment extends Fragment implements DatePickerDialog.OnDateSetListener { 
... 
    private void setDate(final Calendar calendar) { 
     final DateFormat dateFormat = DateFormat.getDateInstance(DateFormat.MEDIUM); 
     ((TextView) m_activity.findViewById(R.id.dob)).setText(dateFormat.format(calendar.getTime())); 
    } 

    public void onDateSet(DatePicker view, int year, int month, int day) { 
     Calendar c = Calendar.getInstance(); 
     c.set(year, month, day); 
     setDate(c); 
    } 

... 

DatePickerFragment fragment = new DatePickerFragment(); 
        fragment.setListeningActivity(AppPatientInfoFragment.this); 
        fragment.show(m_activity.getFragmentManager(), "date"); 

基本上,会发生什么情况是DatePickerFragment的onDateSet()被调用,因为它是实际的回调与DatePicker的,然后DatePickerFragment的onDateSet(注册)会将其转发给AppPatientInfoFragment的onDateSet()。