Search code examples
androidandroid-fragmentsandroid-nested-fragment

Class Cast Exception retrieving Chosen date from childfragment to show in parent fragment


I have a parentfragment called Planning in which I want to show a DialogFragment called DatePickerfragment.The DatePickerFragment has a button that when clicked, will show a datepicker for the user. The user selects a date and that date should be passed to the Parent Fragment in a textview called 'date'.

Unfortunately, everytime I click the button the app crashes with this error:

java.lang.ClassCastException: com.example.android.meat_timealpha10.Activities.MainActivity cannot be cast to android.app.DatePickerDialog$OnDateSetListener
    at com.example.android.meat_timealpha10.Fragments.DatePickerFragment.onCreateDialog(DatePickerFragment.java:29)

I know where the error is but I don't know how to fix it. It refers to this line in the DatePickerDialogFragment:

return new DatePickerDialog(getActivity(), (DatePickerDialog.OnDateSetListener)getActivity(), year, month, day );

The thing is I followed a youtube video and the guy doesn't seem to have any issues. Then again, he doesn't use nested fragments like me. Does anyone know how to fix that error so that the chosen date gets displayed in the textview?

Here is my code:

XML of parent fragment :

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".Fragments.planning">


    <Button
        android:id="@+id/chooseDate"
        style="@style/Widget.AppCompat.Button.Borderless.Colored"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:layout_marginBottom="5dp"
        android:elevation="0dp"
        android:hint="touch here to select date"

        android:textSize="20sp" />

    <TextView
        android:id="@+id/date"
        android:layout_width="match_parent"
        android:layout_height="30dp"
        android:textColor="@color/blue" />
</LinearLayout>

Following is Child Fragment DatePickerFragment:

package com.example.android.meat_timealpha10.Fragments;

import android.app.DatePickerDialog;
import android.app.Dialog;
import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v4.app.DialogFragment;
import android.widget.DatePicker;
import android.widget.TextView;

import com.example.android.meat_timealpha10.R;

import org.w3c.dom.Text;

import java.text.DateFormat;
import java.util.Calendar;

public class DatePickerFragment extends DialogFragment {

    public String dateHolder;
    @NonNull
    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        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(), (DatePickerDialog.OnDateSetListener)getActivity(), year, month, day );
    }   

}

Code of parent fragment ( without imports )

public class planning extends Fragment implements DatePickerDialog.OnDateSetListener{
    // 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";

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

    private OnFragmentInteractionListener mListener;

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

    /**
     * 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 planning.
     */
    // TODO: Rename and change types and number of parameters
    public static planning newInstance(String param1, String param2) {
        planning fragment = new planning();
        Bundle args = new Bundle();
        args.putString(ARG_PARAM1, param1);
        args.putString(ARG_PARAM2, param2);
        fragment.setArguments(args);
        return fragment;
    }



    @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) {

        View view = inflater.inflate(R.layout.fragment_planning,
                container, false);
        final Button chooseDate = (Button)view.findViewById(R.id.chooseDate);




        chooseDate.setOnClickListener(new View.OnClickListener() {
                                      @Override
                                      public void onClick(View v) {

                                        DialogFragment datePicker = new DatePickerFragment();
                                        datePicker.show(getChildFragmentManager(), "date picker");

                                      }
                                      });

        return view;
    }

    @Override
    public void onDateSet(DatePicker view, int year, int month, int day) {
        Calendar c = Calendar.getInstance();
        c.set(Calendar.YEAR, year);
        c.set(Calendar.MONTH, month);
        c.set(Calendar.DAY_OF_MONTH, day);
        String currentDateString = DateFormat.getDateInstance(DateFormat.FULL).format(c.getTime());
        TextView date = (TextView)view.findViewById(R.id.date);
        date.setText(currentDateString);

    }


    // 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(Context context) {
        super.onAttach(context);

    }

    @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
        void onFragmentInteraction(Uri uri);
    }
}

I am fairly new at this so please try to make it easy enough to understand when answering my question. Thanks in advance people!


Solution

  • as it suggested, you can not cast activity to be a Listener, the error occurs in this line: (DatePickerDialog.OnDateSetListener)getActivity().

    you need to implement DatePickerDialog.OnDateSetListener in your fragment and override onDateSet function:

    public class DatePickerFragment extends DialogFragment implements DatePickerDialog.OnDateSetListener {
    
    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        ...
        return new DatePickerDialog(getActivity(), this, year, month, day);
    }  
    
    @Override
    public void onDateSet(DatePicker view, int year, int month, int day) {
        ...        
    }}