0

I am having trouble passing the data (the user selected date from the Date Widget) from the widget back to the calling fragment and set it on the Button. The starting fragment successfully passes the current date to the widget but having troubles passing the user selected date back to the calling fragment.

Here is the code for Starting fragment i.e. CrimeFragment

package com.khalsa.gurankassingh.criminalintent;


import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.text.Editable;
import android.text.TextWatcher;
import android.text.format.DateFormat;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.EditText;

import java.util.Date;
import java.util.UUID;

/**
 * Created by Gurankas Singh on 3/12/2017.
 */

public class CrimeFragment extends Fragment
{
    public static final String ARG_CRIME_ID = "crime_id";
    public static final String DIALOG_DATE = "DialogDate";

private static final int REQUEST_DATE = 0;

private Crime mCrime;               //instance of the Crime class
private EditText mTitleField;       // The editable text field in the fragment
private Button mDateButton;         //Displays the date of the crime on the button
private CheckBox mSolvedCheckBox;   //Displays the current status of the crime; solved or unsolved

public static CrimeFragment newInstance(UUID crimeID)           //to pass value to the fragment via an argument to another fragment
{
    Bundle args = new Bundle();
    args.putSerializable(ARG_CRIME_ID,crimeID);

    CrimeFragment fragment = new CrimeFragment();
    fragment.setArguments(args);
    return fragment;
}

@Override
public void onCreate(@Nullable Bundle savedInstanceState)
{
    super.onCreate(savedInstanceState);
    UUID crimeId = (UUID)getArguments().getSerializable(ARG_CRIME_ID);
    mCrime = CrimeLab.get(getActivity()).getCrime(crimeId);

}

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

    mTitleField = (EditText) v.findViewById(R.id.crime_title);
    mTitleField.setText(mCrime.getTitle());
    mTitleField.addTextChangedListener(new TextWatcher()
    {
        @Override
        public void beforeTextChanged(CharSequence s, int start, int count, int after)
        {

        }

        @Override
        public void onTextChanged(CharSequence s, int start, int before, int count)
        {
            mCrime.setTitle(s.toString());
        }

        @Override
        public void afterTextChanged(Editable s)
        {

        }
    });

    mDateButton = (Button) v.findViewById(R.id.crime_date);
    updateDate();
    mDateButton.setOnClickListener(new View.OnClickListener()
    {

        @Override
        public void onClick(View v)
        {
            FragmentManager fragmentManager = getFragmentManager();
            DatePickerFragment dialog = DatePickerFragment.newInstance(mCrime.getDate());
            setTargetFragment(CrimeFragment.this,REQUEST_DATE);
            dialog.show(fragmentManager, DIALOG_DATE);
        }
    });

    mSolvedCheckBox = (CheckBox) v.findViewById(R.id.crime_solved);
    mSolvedCheckBox.setChecked(mCrime.isSolved());
    mSolvedCheckBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener()
    {
        @Override
        public void onCheckedChanged(CompoundButton buttonView, boolean isChecked)
        {
            //set the crime's solved property
            mCrime.setSolved(isChecked);
        }
    });

    return v;
}

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data)
{
    if (resultCode != Activity.RESULT_OK)
    {
        return;
    }
    if (requestCode == REQUEST_DATE)
    {
        Date date = (Date)data.getSerializableExtra(DatePickerFragment.EXTRA_DATE);
        mCrime.setDate(date);
        updateDate();
    }
}

private void updateDate()
{
    mDateButton.setText(DateFormat.format("EEEE, d MMMM, yyy", mCrime.getDate()));
}
}

Here is the code for the datePicker widget hosted by DatePickerFragment

package com.khalsa.gurankassingh.criminalintent;

import android.app.Activity;
import android.app.Dialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v4.app.DialogFragment;
import android.support.v7.app.AlertDialog;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.DatePicker;

import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;

/**
 * Created by Gurankas Singh on 4/9/2017.
 */

public class DatePickerFragment extends DialogFragment
{
    private static final String DATE_ARG = "date";
public static final String EXTRA_DATE = "com.khalsa.gurankassingh.criminalintent.date";

private DatePicker mDatePicker;

public static DatePickerFragment newInstance(Date date)
{
    Bundle args = new Bundle();
    args.putSerializable(DATE_ARG,date);

    DatePickerFragment fragment = new DatePickerFragment();
    fragment.setArguments(args);
    return fragment;
}

@NonNull
@Override
public Dialog onCreateDialog(Bundle savedInstanceState)
{
    Date date = (Date)getArguments().getSerializable(DATE_ARG);

    Calendar calendar = Calendar.getInstance();
    calendar.setTime(date);
    int year = calendar.get(Calendar.YEAR);
    int month = calendar.get(Calendar.MONTH);
    int day = calendar.get(Calendar.DAY_OF_MONTH);

    View v = LayoutInflater.from(getActivity()).inflate(R.layout.dialog_date,null);

    mDatePicker = (DatePicker)v.findViewById(R.id.dialog_date_date_picker);
    mDatePicker.init(year,month,day,null);

    return new AlertDialog.Builder(getActivity()).setView(v).setTitle(R.string.date_picker_title).setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener()
    {
        @Override
        public void onClick(DialogInterface dialog, int which)
        {
            int year = mDatePicker.getYear();
            int month = mDatePicker.getMonth();
            int day = mDatePicker.getDayOfMonth();
            Date date = new GregorianCalendar(year, month, day).getTime();
            sendResult(Activity.RESULT_OK, date);
        }
    }).create();
}
private void sendResult(int resultCode, Date date)
{
    if (getTargetFragment() == null)
    {
        return;
    }
    Intent intent = new Intent();
    intent.putExtra(EXTRA_DATE,date);

    getTargetFragment().onActivityResult(getTargetRequestCode(), resultCode, intent);
}

}

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
Gurankas
  • 229
  • 4
  • 16
  • you mean one fragment to another fragment? – Rajasekhar Apr 26 '17 at 05:33
  • Check this link http://stackoverflow.com/questions/6751583/is-there-a-method-that-works-like-start-fragment-for-result – Vikrant_Dev Apr 26 '17 at 05:34
  • Create an interface in activity and pass the data in between fragment during fragment transaction. refer [here](http://stackoverflow.com/questions/16036572/how-to-pass-values-between-fragments) – Madhukar Hebbar Apr 26 '17 at 05:45
  • @Rajasekhar yes. The two fragments given above are hosted by the same activity. I need to pass the date selected by the user back to the original fragment – Gurankas Apr 26 '17 at 05:45

3 Answers3

1

For passing data between Fragments all you need to know is:

1- For passing data from Activity to Fragment use object instance, as you create your Fragment inside Activity you have one instance from it, so use that to pass data like below:

class Activity1 extend AppCompatActivity {

   Fragment1 fragment;

   void doSomethingInFramgent() {

      fragment.doSomething();
   }
}

2- for passing data from Fragment to Activity, use Interface, create an Interface and use following step:

2-1- create an Interface file:

public interface FragmentInteraction {
     void doSomethingInActivity();
}

2-2- implement Interface in Activity:

 class Activity1 extend AppCompatActivity implement FragmentInteraction {

    void doSomethingInActivity() {
       // do whatever you need
    }
 }

2-3- create one object from Interface and initialize it in onAttach like bellow:

   class Fragment1 extend Fragment {

   FragmentInteraction fragmentInteraction;

    @Override
    public void onAttach(Context context) {
        super.onAttach(context);

        if (context instanceof FragmentInteraction) {
            fragmentInteraction = (FragmentInteraction) context;
        }
    }

}

2-4- use Interfaceinstance to call method in Activity like:

fragmentInteraction.doSomethinInActivity();

with this concept you can pass data between Fragments and Activity, for example if you want pass data from one fragment to another in different activity you can:

Activity1, Fragment1. Activity2, Fragment2

pass data with Interface from Fragment1 to Activity1, start Activity2 with startActivityForResult, pass data with fragment2 object, return data with Interface to Activity2 then use setResult and return to Activity1

PS: if you want pass data while creation Fragment object you can use Argument to pass data.

for this purpose you can use as follow:

1- create static method for get instance of fragment:

 public static Fragment1 getInstance(String data1) {

        Fragment1 fragment = new Fragment1();

        Bundle bundle = new Bundle();
        bundle.putString(KEY, data1);
        fragment.setArguments(bundle);

        return fragment;
    }

then in onCreateView on onViewCreate get your data like:

 if (getArguments() != null) {
     data = getArguments().getString(KEY);    
 }
Shayan Pourvatan
  • 11,898
  • 4
  • 42
  • 63
0

You can try this solution:-

=> Change below code in CrimeFragment

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data)
{
    if (resultCode != Activity.RESULT_OK)
    {
        return;
    }
    if (requestCode == REQUEST_DATE)
    {
        long dateValue = data.getLongExtra(DatePickerFragment.EXTRA_DATE,System.currentTimeMillis());
        Date date = new Date(dateValue);
        mCrime.setDate(date);
        updateDate();
    }
}

And In DatePickerFragment change below code:-

private void sendResult(int resultCode, Date date)
        {
            if (getTargetFragment() == null)
            {
                return;
            }
            Intent intent = new Intent();
            intent.putExtra(EXTRA_DATE, date.getTime());

            getTargetFragment().onActivityResult(getTargetRequestCode(), resultCode, intent);
        }

....

Nitin Patel
  • 1,605
  • 13
  • 31
  • @Gurankas do you need time(hh:MM:ss) in your dateObject ? – Nitin Patel Apr 26 '17 at 06:55
  • @Gurankas Above code is working properly. You should have to debug and check the date object value in sendResult() method of DatePickerFragment. I think it is not properly set. Hope this will help you. – Nitin Patel Apr 26 '17 at 07:05
  • The app crashes when I implement the above code. How do you suggest I debug and check the date object's value which is being sent in sendResult? – Gurankas Apr 26 '17 at 09:05
  • I think so. Any idea how to test it though? – Gurankas Apr 26 '17 at 13:24
0

Hello Try this approach,

You can use shared preferences to store the date and later on you can access it whenever required, it is easier to handle.just keep in mind the date format and choose the SimpleDateFormat accordingly as it gives parse error if a format of input date is not same.

Write into SharedPreferances

SharedPreferences sharedpreferences;
sharedpreferences = getSharedPreferences("myPref", Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sharedpreferences.edit();
            editor.putString("Date",String.valueOf(date);
            editor.commit();

Read SharedPreferances when required

SharedPreferences prefs = this.getSharedPreferences("myPref", Context.MODE_PRIVATE);
String dateCrime = prefs.getString("Date", null);  

//Chose Date format depending on your date
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");  
try {  
    Date date = format.parse(dateCrime);   
} catch (ParseException e) {    
    e.printStackTrace();  
} 
Pratik Vyas
  • 644
  • 7
  • 20