I have below codes to display a date picker inside an Activity, but when I tried to convert my activity to Fragment, I am getting error. I can't really see any difference in code compare to solutions in SO to implement a DialogFragment inside a Fragment.
Can you please point out what am I missing?
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)
Try this sample code....
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));
}
};
}
Create another class 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);
}
}
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);
}
}
}
I got that exact same casting error, and after looking for a solution, but not finding one that worked well, I decided to come up with one of my own.
My approach is to use a little trick. Instead of trying to get the class that extends DialogFragment to accept my Fragment as a DatePickerDialog.OnDateSetListener, I allow the DialogFragment class to implement the interface and receive the callback. When the callback is invoked, it will then pass it along to my Fragment, which also implements the same interface. In effect, the DialogFragment class forwards the callback. Here is the DialogFragment class, which you might have seen in many other stackoverflow posts, with the exception it has a public method, setListeningActivity(). setListeningActivity() takes a fragment, an activity, or really any class that implements DatePickerDialog.OnDateSetListener. This is the class to which any callbacks to the DialogFragment class will be forwarded.
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);
}
}
Next is the code that uses it:
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");
Basically, what happens is DatePickerFragment's onDateSet() gets called, because it is the actually callback registered with the DatePicker, and then DatePickerFragment's onDateSet() will forward it to AppPatientInfoFragment's onDateSet().
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With