3

Currently, my main activity displays an arbitrary time, and holds a button that when pressed, brings up a Time Picker Dialog Fragment. After the user sets a new time in the Fragment, closing the fragment, I want my main activity to update it's TextView with the new time the user chose.

My issue right now is that I can't figure out how to update the time displayed in the activity after the user sets the time. I have tried playing with onResume, but it keeps causing the app to crash. What is the best way to refresh an activity after exiting a fragment?

The flow I am trying to achieve is that the user sets the time in the fragment, causing the shared preferences to be updated, and then the main acitivty refreshes, updating the text view with the chosen time. Am I thinking of this incorrectly?

Here is my TimePickerFragment class:

package com.example.habitabilitystudy;

import java.util.Calendar;

import android.app.Activity;
import android.app.Dialog;
import android.app.DialogFragment;
import android.app.TimePickerDialog;
import android.content.Context;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.text.format.DateFormat;
import android.widget.TimePicker;

public class TimePickerFragment extends DialogFragment implements
        TimePickerDialog.OnTimeSetListener {

    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        // Use the current time as the default values for the picker
        Context context = getActivity();
        SharedPreferences sharedPref = context.getSharedPreferences(
                "prediction", Context.MODE_PRIVATE);

        final Calendar c = Calendar.getInstance();
        int defaultHour = c.get(Calendar.HOUR_OF_DAY);
        int defaultMinute = c.get(Calendar.MINUTE);

        int hour = sharedPref.getInt("prediction_hour", defaultHour);
        int minute = sharedPref.getInt("prediction_min", defaultMinute);

        // Create a new instance of TimePickerDialog and return it
        return new TimePickerDialog(getActivity(), this, hour, minute,
                DateFormat.is24HourFormat(getActivity()));
    }

    public void onTimeSet(TimePicker view, int hourOfDay, int minute) {
        Context context = getActivity();
        SharedPreferences sharedPref = context.getSharedPreferences(
                "prediction", Context.MODE_PRIVATE);
        SharedPreferences.Editor editorh = sharedPref.edit();
        editorh.putInt("prediction_hour", hourOfDay);
        editorh.commit();
        SharedPreferences.Editor editorm = sharedPref.edit();
        editorm.putInt("prediction_min", minute);
        editorm.commit();
        mCallbacks.TimeUpdated();

    }

    /**
     * Interface
     */
    private FragmentCallbacks mCallbacks;

    public interface FragmentCallbacks {
        void TimeUpdated();
    }

    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        try {
            mCallbacks = (FragmentCallbacks) activity;
        } catch (ClassCastException e) {
            throw new ClassCastException(
                    "Activity must implement Fragment Two.");
        }
    }

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

}

My Main Activity:

package com.example.habitabilitystudy;

import java.util.Calendar;

import android.app.Activity;
import android.app.DialogFragment;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;

public class MainActivity extends Activity implements
        TimePickerFragment.FragmentCallbacks {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // Use the current time as the default values for the picker
        SharedPreferences sharedPref = this.getSharedPreferences("prediction",
                Context.MODE_PRIVATE);

        final Calendar c = Calendar.getInstance();
        int defaultHour = c.get(Calendar.HOUR_OF_DAY);
        int defaultMinute = c.get(Calendar.MINUTE);

        int hour = sharedPref.getInt("prediction_hour", defaultHour);
        int minute = sharedPref.getInt("prediction_min", defaultMinute);

        String timeString = Integer.toString(hour) + ":"
                + Integer.toString(minute);

        TextView predictionText = (TextView) findViewById(R.id.prediction_time);
        predictionText.setText(timeString);
    }

    public void showTimePickerDialog(View v) {
        DialogFragment newFragment = new TimePickerFragment();
        newFragment.show(getFragmentManager(), "timePicker");
    }

    @Override
    public void TimeUpdated() {
        Toast.makeText(this, "Updated", Toast.LENGTH_SHORT).show();
    }

    public void onClick(View v) {
        switch (v.getId()) {
        case R.id.predictButton:
            startActivity(new Intent(this, MainActivity.class));
            break;
        case R.id.login:
            startActivity(new Intent(this, LoginActivity.class));
            break;
        }
    }
}

My Main Activity xml:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >

    <TextView
        android:id="@+id/prediction_time"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:paddingRight="3dip"
        android:background="#5c755e"
        android:gravity="end"
        android:textColor="#3d4935"
        android:textSize="25sp"
        android:textStyle="italic"
        android:text="(c) appsrox.com" /> 


    <Button 
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content"
    android:text="@string/adjust_time" 
    android:onClick="showTimePickerDialog" />



</RelativeLayout>
Connor O'Doherty
  • 385
  • 1
  • 5
  • 19

1 Answers1

4

You want to create an Interface in the Dialog Fragment. When the time is picked it will notify the Activity. Let me know if this gives you any issues.

Fragment

public class TimePickerFragment extends DialogFragment implements
    TimePickerDialog.OnTimeSetListener {

    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        // Use the current time as the default values for the picker
        Context context = getActivity();
        SharedPreferences sharedPref = context.getSharedPreferences(
            "prediction", Context.MODE_PRIVATE);

        final Calendar c = Calendar.getInstance();
        int defaultHour = c.get(Calendar.HOUR_OF_DAY);
        int defaultMinute = c.get(Calendar.MINUTE);

        int hour = sharedPref.getInt("prediction_hour", defaultHour);
        int minute = sharedPref.getInt("prediction_min", defaultMinute);

        // Create a new instance of TimePickerDialog and return it
        return new TimePickerDialog(getActivity(), this, hour, minute,
            DateFormat.is24HourFormat(getActivity()));
    }


    public void onTimeSet(TimePicker view, int hourOfDay, int minute) {
        Context context = getActivity();
        SharedPreferences sharedPref = context.getSharedPreferences(
            "prediction", Context.MODE_PRIVATE);
        SharedPreferences.Editor editorh = sharedPref.edit();
        editorh.putInt("prediction_hour", hourOfDay);
        editorh.commit();
        SharedPreferences.Editor editorm = sharedPref.edit();
        editorm.putInt("prediction_min", minute);
        editorm.commit();
        mCallbacks.TimeUpdated(hourOfDay, minute);
    }

    /**
     * Interface
     */
    private FragmentCallbacks mCallbacks;

    public interface FragmentCallbacks {
        void TimeUpdated(int hour, int minute);
    }

    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        try {
            mCallbacks = (FragmentCallbacks) activity;
        } catch (ClassCastException e) {
            throw new ClassCastException("Activity must implement Fragment Two.");
        }
    }

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

}

MainActivity

public class MainActivity extends Activity implements TimePickerFragment.FragmentCallbacks {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // Use the current time as the default values for the picker
        SharedPreferences sharedPref = this.getSharedPreferences("prediction",
            Context.MODE_PRIVATE);

        final Calendar c = Calendar.getInstance();
        int defaultHour = c.get(Calendar.HOUR_OF_DAY);
        int defaultMinute = c.get(Calendar.MINUTE);

        int hour = sharedPref.getInt("prediction_hour", defaultHour);
        int minute = sharedPref.getInt("prediction_min", defaultMinute);

        String timeString = Integer.toString(hour) + ":"
            + Integer.toString(minute);

        TextView predictionText = (TextView) findViewById(R.id.prediction_time);
        predictionText.setText(timeString);
    }

    public void showTimePickerDialog(View v) {
        DialogFragment newFragment = new TimePickerFragment();
        newFragment.show(getFragmentManager(), "timePicker");
    }

    @Override
    public void TimeUpdated(int hour, int minute) {
        Toast.makeText(this, "Hour: " + hour + " Minute: " + minute, Toast.LENGTH_SHORT).show();
        String timeString = Integer.toString(hour) + ":" + Integer.toString(minute);
        TextView predictionText = (TextView) findViewById(R.id.prediction_time);
        predictionText.setText(timeString);
    }
}
Eugene H
  • 3,520
  • 3
  • 22
  • 39
  • Thank you so much for helping me out! However, it is still not updating. After I set the time, I receive the "Updated" flash, but the old time is still displayed on the screen. – Connor O'Doherty Jun 02 '15 at 00:37
  • Sorry, it saved my comment before I finished typing, haha. If you see my edited post above, i'm still having issues, and would greatly appreciate your help. – Connor O'Doherty Jun 02 '15 at 00:39
  • @ConnorO'Doherty No worries I updated my answer. Have a look at the Main Activity TimeUpdated(int hour, int minute) . – Eugene H Jun 02 '15 at 00:41
  • @ConnorO'Doherty let me know if it updates the TextView? – Eugene H Jun 02 '15 at 00:45
  • Unfortunately, I now receive a timeout error. Any insight into why this might be happening? It looks like it should work perfectly.I think I may just need to restart my emulator – Connor O'Doherty Jun 02 '15 at 00:57
  • @ConnorO'Doherty I am not sure. You said it showed the Toast earlier, Correct? – Eugene H Jun 02 '15 at 01:02
  • Yeah, that implementation works fine, but when I add the TimeUpdated(int hour, int minute) edits, it timeouts on installation. – Connor O'Doherty Jun 02 '15 at 01:07
  • @ConnorO'Doherty Update your code in the question with what you currently have implemented. – Eugene H Jun 02 '15 at 01:10
  • @ConnorO'Doherty I just ran the code and it worked in mine. If you post your code I believe it is probably just a simple mistake. – Eugene H Jun 02 '15 at 01:15
  • Just uploaded what I reverted to – Connor O'Doherty Jun 02 '15 at 01:30
  • @ConnorO'Doherty Now have a look at my code and copy and paste what I have an put it in your classes – Eugene H Jun 02 '15 at 01:33
  • @ConnorO'Doherty It should toast the hour an minute. Let me know if it does. – Eugene H Jun 02 '15 at 01:35
  • Just did. That edit just made the little pop-up display the new time. The larger text on the original view that the fragment was called from remained exactly the same. The time on the MainActivity view itself did not change. – Connor O'Doherty Jun 02 '15 at 01:37
  • @ConnorO'Doherty good. I was just testing to see if it toasted the minutes and time. Now you can remove the // from the following lines below the toast – Eugene H Jun 02 '15 at 01:39
  • @ConnorO'Doherty No problem, Good Luck with the rest of the project! – Eugene H Jun 02 '15 at 01:43