2

I can't seem to set up my DateTimeDialogFragment because it keeps crashing at the part where i put:

datePicker = (DatePicker) getView().findViewById(R.id.DatePicker);

Error Log:

02-14 21:38:43.262: E/AndroidRuntime(2435): FATAL EXCEPTION: main
02-14 21:38:43.262: E/AndroidRuntime(2435): java.lang.NullPointerException
02-14 21:38:43.262: E/AndroidRuntime(2435):     at com.test.DateTimeDialogFragment.onActivityCreated(DateTimeDialogFragment.java:98)
02-14 21:38:43.262: E/AndroidRuntime(2435):     at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:847)
02-14 21:38:43.262: E/AndroidRuntime(2435):     at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:1032)
02-14 21:38:43.262: E/AndroidRuntime(2435):     at android.app.BackStackRecord.run(BackStackRecord.java:622)
02-14 21:38:43.262: E/AndroidRuntime(2435):     at android.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1382)
02-14 21:38:43.262: E/AndroidRuntime(2435):     at android.app.FragmentManagerImpl$1.run(FragmentManager.java:426)
02-14 21:38:43.262: E/AndroidRuntime(2435):     at android.os.Handler.handleCallback(Handler.java:605)
02-14 21:38:43.262: E/AndroidRuntime(2435):     at android.os.Handler.dispatchMessage(Handler.java:92)
02-14 21:38:43.262: E/AndroidRuntime(2435):     at android.os.Looper.loop(Looper.java:137)
02-14 21:38:43.262: E/AndroidRuntime(2435):     at android.app.ActivityThread.main(ActivityThread.java:4424)
02-14 21:38:43.262: E/AndroidRuntime(2435):     at java.lang.reflect.Method.invokeNative(Native Method)
02-14 21:38:43.262: E/AndroidRuntime(2435):     at java.lang.reflect.Method.invoke(Method.java:511)
02-14 21:38:43.262: E/AndroidRuntime(2435):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)
02-14 21:38:43.262: E/AndroidRuntime(2435):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
02-14 21:38:43.262: E/AndroidRuntime(2435):     at dalvik.system.NativeStart.main(Native Method)

Here's the full code:

public class DateTimeDialogFragment extends DialogFragment implements
        OnDateChangedListener, OnTimeChangedListener {
    // Define constants for date-time picker.
    public final int DATE_PICKER = 1;
    public final int TIME_PICKER = 2;
    public final int DATE_TIME_PICKER = 3;

    // DatePicker reference
    private DatePicker datePicker;

    // TimePicker reference
    private TimePicker timePicker;

    // Calendar reference
    private Calendar mCalendar;

    // Define activity
    private Activity activity;

    // Define Dialog type
    private int intDialogType;

    // Constructor start
    public DateTimeDialogFragment(Activity activity) {
        this.activity = activity;
    }

    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        // Use the Builder class for convenient dialog construction
        AlertDialog.Builder builder = new AlertDialog.Builder(activity);

        // Get the layout inflater
        LayoutInflater inflater = activity.getLayoutInflater();

        // Inflate and set the layout for the dialog
        // Pass null as the parent view because its going in the dialog layout
        builder.setView(inflater.inflate(R.layout.date_time_dialog, null));

        // Set title of dialog
        builder.setMessage("Set Date")
                // Set Ok button
                .setPositiveButton("Set",
                        new DialogInterface.OnClickListener() {
                            public void onClick(DialogInterface dialog, int id) {
                                // User ok the dialog
                            }
                        })
                // Set Cancel button
                .setNegativeButton("Cancel",
                        new DialogInterface.OnClickListener() {
                            public void onClick(DialogInterface dialog, int id) {
                                // User cancelled the dialog
                            }
                        })
                // Set Neutral button (reset Time / Date)
                .setNeutralButton("Reset",
                        new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog, int id) {
                                // User reset the dialog
                                // reset();
                            }
                        });

        // Create the AlertDialog object and return it
        return builder.create();
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        super.onActivityCreated(savedInstanceState);
        // Grab a Calendar instance
        mCalendar = Calendar.getInstance();

        // Init date picker
        datePicker = (DatePicker) getView().findViewById(R.id.DatePicker);
        datePicker.init(mCalendar.get(Calendar.YEAR), mCalendar.get(Calendar.MONTH), mCalendar.get(Calendar.DAY_OF_MONTH), this);

        // Init time picker
        timePicker = (TimePicker) getView().findViewById(R.id.TimePicker);
        timePicker.setOnTimeChangedListener(this);
    }

    public void setIntDialogType(int intDialogType) {
        this.intDialogType = intDialogType;
    }

    // Convenience wrapper for internal Calendar instance
    public int get(final int field) {
        return mCalendar.get(field);
    }

    // Reset DatePicker, TimePicker and internal Calendar instance
    public void reset() {
        final Calendar c = Calendar.getInstance();
        updateDate(c.get(Calendar.YEAR), c.get(Calendar.MONTH), c.get(Calendar.DAY_OF_MONTH));
        updateTime(c.get(Calendar.HOUR_OF_DAY), c.get(Calendar.MINUTE));
    }

    // Convenience wrapper for internal Calendar instance
    public long getDateTimeMillis() {
        return mCalendar.getTimeInMillis();
    }

    // Convenience wrapper for internal TimePicker instance
    public void setIs24HourView(boolean is24HourView) {
        timePicker.setIs24HourView(is24HourView);
    }

    // Convenience wrapper for internal TimePicker instance
    public boolean is24HourView() {
        return timePicker.is24HourView();
    }

    // Convenience wrapper for internal DatePicker instance
    public void setCalendarViewShown(boolean calendarView) {
        datePicker.setCalendarViewShown(calendarView);
    }

    // Convenience wrapper for internal DatePicker instance
    public boolean CalendarViewShown() {
        return datePicker.getCalendarViewShown();
    }

    // Convenience wrapper for internal DatePicker instance
    public void updateDate(int year, int monthOfYear, int dayOfMonth) {
        datePicker.updateDate(year, monthOfYear, dayOfMonth);
    }

    // Convenience wrapper for internal TimePicker instance
    public void updateTime(int currentHour, int currentMinute) {
        timePicker.setCurrentHour(currentHour);
        timePicker.setCurrentMinute(currentMinute);
    }

    public String getDateTime() {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.US);
        return sdf.format(mCalendar.getTime());
    }

    // Called every time the user changes DatePicker values
    @Override
    public void onDateChanged(DatePicker view, int year, int monthOfYear, int dayOfMonth) {
        // Update the internal Calendar instance
        mCalendar.set(year, monthOfYear, dayOfMonth, mCalendar.get(Calendar.HOUR_OF_DAY), mCalendar.get(Calendar.MINUTE));
    }

    // Called every time the user changes TimePicker values
    @Override
    public void onTimeChanged(TimePicker view, int hourOfDay, int minute) {
        // Update the internal Calendar instance
        mCalendar.set(mCalendar.get(Calendar.YEAR), mCalendar.get(Calendar.MONTH), mCalendar.get(Calendar.DAY_OF_MONTH), hourOfDay, minute);
    }

Here's the date_time_dialog.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/DateTimePicker"
    android:layout_width="wrap_content"
    android:layout_height="fill_parent"
    android:gravity="center"
    android:orientation="horizontal"
    android:padding="5dip" >

    <DatePicker
        android:id="@+id/DatePicker"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:layout_marginRight="40dp" />

    <TimePicker
        android:id="@+id/TimePicker"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center" />

</LinearLayout>
user1848850
  • 463
  • 7
  • 20
  • what i'm a little bit confused about, is how do i access he R.id.DatePicker from the layout that i used in "builder.setView" this way i can access timePicker and datePicker. I tried cleaning the project but i still get the same error. For some reason the datePicker object remains null after executing the line you mentioned above this comment – user1848850 Feb 15 '13 at 05:06
  • 1
    Try instead of `getView()` using `getDialog()`. – A--C Feb 15 '13 at 05:08
  • same thing, Null pointer reference, it can't find the R.id.DatePicker I wonder if i'm not supposed to do this in onActivityCreated method. I'm confused – user1848850 Feb 15 '13 at 05:18
  • 1
    Use the `getActivity()` instead of `getView()` and try out. – GrIsHu Feb 15 '13 at 05:25

3 Answers3

5

I want to say thanks to everyone for helping me out and leading me in the right direction. I now have a much better understanding of Android. Here's the full working class:

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Locale;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.AlertDialog.Builder;
import android.app.Dialog;
import android.app.DialogFragment;
import android.content.DialogInterface;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.DatePicker;
import android.widget.DatePicker.OnDateChangedListener;
import android.widget.TimePicker;
import android.widget.TimePicker.OnTimeChangedListener;

public class DateTimeDialogFragment extends DialogFragment implements OnDateChangedListener, OnTimeChangedListener {
    // Define constants for date-time picker.
    public final static int DATE_PICKER = 1;
    public final static int TIME_PICKER = 2;
    public final static int DATE_TIME_PICKER = 3;

    // DatePicker reference
    private DatePicker datePicker;

    // TimePicker reference
    private TimePicker timePicker;

    // Calendar reference
    private Calendar mCalendar;

    // Define activity
    private Activity activity;

    // Define Dialog type
    private int DialogType;

    // Define Dialog view
    private View mView;

    // Constructor start
    public DateTimeDialogFragment(Activity activity) {
        this(activity, DATE_TIME_PICKER);
    }

    public DateTimeDialogFragment(Activity activity, int DialogType) {
        this.activity = activity;
        this.DialogType = DialogType;

        // Inflate layout for the view
        // Pass null as the parent view because its going in the dialog layout
        LayoutInflater inflater = activity.getLayoutInflater();
        mView = inflater.inflate(R.layout.date_time_dialog, null);  

        // Grab a Calendar instance
        mCalendar = Calendar.getInstance();

        // Init date picker
        datePicker = (DatePicker) mView.findViewById(R.id.DatePicker);
        datePicker.init(mCalendar.get(Calendar.YEAR), mCalendar.get(Calendar.MONTH), mCalendar.get(Calendar.DAY_OF_MONTH), this);

        // Init time picker
        timePicker = (TimePicker) mView.findViewById(R.id.TimePicker);

        // Set default Calendar and Time Style
        setIs24HourView(true);
        setCalendarViewShown(false);

        switch (DialogType) {
        case DATE_PICKER:
            timePicker.setVisibility(View.GONE);
            break;
        case TIME_PICKER:
            datePicker.setVisibility(View.GONE);
            break;
        }
    }

    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {

        // Use the Builder class for convenient dialog construction
        Builder builder = new AlertDialog.Builder(activity);

        // Set the layout for the dialog
        builder.setView(mView);

        // Set title of dialog
        builder.setMessage("Set Date")
                // Set Ok button
                .setPositiveButton("Set",
                        new DialogInterface.OnClickListener() {
                            public void onClick(DialogInterface dialog, int id) {
                                // User ok the dialog
                            }
                        })
                // Set Cancel button
                .setNegativeButton("Cancel",
                        new DialogInterface.OnClickListener() {
                            public void onClick(DialogInterface dialog, int id) {
                                // User cancelled the dialog
                                DateTimeDialogFragment.this.getDialog().cancel();
                            }
                        }); 

        // Create the AlertDialog object and return it
        return builder.create();
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        timePicker.setOnTimeChangedListener(this);
    }

    // Convenience wrapper for internal Calendar instance
    public int get(final int field) {
        return mCalendar.get(field);
    }

    // Convenience wrapper for internal Calendar instance
    public long getDateTimeMillis() {
        return mCalendar.getTimeInMillis();
    }

    // Convenience wrapper for internal TimePicker instance
    public void setIs24HourView(boolean is24HourView) {
        timePicker.setIs24HourView(is24HourView);
    }

    // Convenience wrapper for internal TimePicker instance
    public boolean is24HourView() {
        return timePicker.is24HourView();
    }

    // Convenience wrapper for internal DatePicker instance
    public void setCalendarViewShown(boolean calendarView) {
        datePicker.setCalendarViewShown(calendarView);
    }

    // Convenience wrapper for internal DatePicker instance
    public boolean CalendarViewShown() {
        return datePicker.getCalendarViewShown();
    }

    // Convenience wrapper for internal DatePicker instance
    public void updateDate(int year, int monthOfYear, int dayOfMonth) {
        datePicker.updateDate(year, monthOfYear, dayOfMonth);
    }

    // Convenience wrapper for internal TimePicker instance
    public void updateTime(int currentHour, int currentMinute) {
        timePicker.setCurrentHour(currentHour);
        timePicker.setCurrentMinute(currentMinute);
    }

    public String getDateTime() {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.US);
        return sdf.format(mCalendar.getTime());
    }

    // Called every time the user changes DatePicker values
    @Override
    public void onDateChanged(DatePicker view, int year, int monthOfYear, int dayOfMonth) {
        // Update the internal Calendar instance
        mCalendar.set(year, monthOfYear, dayOfMonth, mCalendar.get(Calendar.HOUR_OF_DAY), mCalendar.get(Calendar.MINUTE));
    }

    // Called every time the user changes TimePicker values
    @Override
    public void onTimeChanged(TimePicker view, int hourOfDay, int minute) {
        // Update the internal Calendar instance
        mCalendar.set(mCalendar.get(Calendar.YEAR), mCalendar.get(Calendar.MONTH), mCalendar.get(Calendar.DAY_OF_MONTH), hourOfDay, minute);
    }
}
user1848850
  • 463
  • 7
  • 20
  • Thanks so much! This is a perfect implementation. I have been searching for something like this since 2-3 days! – sleeping_dragon May 28 '13 at 09:44
  • Fragment is not suppose to use constructor. [link](http://stackoverflow.com/questions/10450348/do-fragments-really-need-an-empty-constructor) – minhaz Jul 01 '14 at 20:40
  • How to get the selected date and time from this @user1848850 – Manu May 06 '15 at 10:58
3

Edit:

Hi I have worked with your same code and I am able open Date and Time picker dialog... Where you have missed is you haven't inflated the layout to get the view

Try to change your onActivityCreate like this

public void onActivityCreated(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onActivityCreated(savedInstanceState);
// Grab a Calendar instance
mCalendar = Calendar.getInstance();
LayoutInflater inflater = activity.getLayoutInflater();

//Inflate and set the layout for the dialog
//Pass null as the parent view because its going in the dialog layout
View v=inflater.inflate(R.layout.date_time_dialog, null);

// Init date picker
datePicker = (DatePicker)v.findViewById(R.id.DatePicker);
datePicker.init(mCalendar.get(Calendar.YEAR), mCalendar.get(Calendar.MONTH), mCalendar.get(Calendar.DAY_OF_MONTH), this);

// Init time picker
timePicker = (TimePicker) v.findViewById(R.id.TimePicker);
timePicker.setOnTimeChangedListener(this);
}

This will solve your problem....I was confident because with your same code I have successfully opened the dialog.


Hi please refer this documentation regarding OnActivityCreate

According to the documentation This is called after onCreateView(LayoutInflater, ViewGroup, Bundle) and before onViewStateRestored(Bundle). you need to use onCreateView to get datePicker = (DatePicker) getView().findViewById(R.id.DatePicker); this... I am not sure but I have implemented the DatePicker with the dialog like this it might be helpful

public class DateDialogFragment extends DialogFragment implements
            OnDateSetListener {
        boolean fired = false;

        @Override
        public Dialog onCreateDialog(Bundle savedInstanceState) {
            Calendar cal = Calendar.getInstance();
            int year = cal.get(Calendar.YEAR);
            int month = cal.get(Calendar.MONTH);
            int day = cal.get(Calendar.DAY_OF_MONTH);
            return new DatePickerDialog(getActivity(), this, year, month, day);
        }

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

            if (fired == true) {
                return;
            } else {
                // first time fired
                fired = true;
            }
            String date = checkDigit(monthOfYear + 1) + "/"
                    + checkDigit(dayOfMonth) + "/" + year;
            strDate = date;
            getAppointments(date);
        }
    }

To Format the result date

   public String checkDigit(int number) {
            return number <= 9 ? "0" + number : String.valueOf(number);
        }

and use it like this in your Activity (recommended to use FragmentActivity)

 DateDialogFragment datepicker = new DateDialogFragment();
                datepicker.show(getSupportFragmentManager(), "DatePicker");
Pragnani
  • 20,075
  • 6
  • 49
  • 74
  • Question for u, does onCreateDialog fire after onActivityCreated ? – user1848850 Feb 15 '13 at 05:52
  • The reason i was using AlertDialog.Builder was to create the Positive/Neutral/Negative buttons. I got the idea from here: [link](http://developer.android.com/guide/topics/ui/dialogs.html#DialogFragment) – user1848850 Feb 15 '13 at 05:53
  • lol OMG i'm a noob. OH MY, THANK YOU SO MUCH! I can go to bed now, i think 15 hours is enough for one day. THANK EVERYONE WHO HELPED. THANK YOU ALL! i would like to know oneeee thing, why do you have to do what you did? I really don't understand that part. I thought the resource was already inflated, so i thought you can't inflate twice! – user1848850 Feb 15 '13 at 06:36
  • although i can't change the is24HourView and the setCalendarViewShown it's working, i'm going to sleep and have a crack at it tomorrow, thank you – user1848850 Feb 15 '13 at 06:41
  • @user1848850 welcome friend....I am also newbee like you...I haven't worked with this earlier..Thanks for you also because I have learned something today...and Have a great sleep... – Pragnani Feb 15 '13 at 06:51
1

You can try this implementation which does not use AlertDialog.Builder and you can have a reference to the view. So that you can call view.findViewById(R.id.yourViewItem).

Edit:Pragnani's solution and suggestions helped me as well. Thank you very much.

Chris Margonis
  • 935
  • 11
  • 16
  • that allowed me to run it but if i run the setter: setCalendarViewShown it crashes. obviously i'm missing something here, i've been reading for hours and haven't found a clue as to why it can't find R.id.DatePicker, i tried to clean the project even reset the emulator, still – user1848850 Feb 15 '13 at 05:25
  • 1
    Do you have the same issue with R.id.TimePicker? – Chris Margonis Feb 15 '13 at 05:31
  • my mistake, i've done what you suggested and i don't get null pointer reference when using your method posted. Although i can't make changes to the datePicker because that would crash it. And i also lose the ability to use the setNegativeButton/setNeutralButton when using your method. I'm gonna have to keep trying to figure out why i can't access the R.id.DatePicker when using AlertDialog.Builder – user1848850 Feb 15 '13 at 05:33
  • 1
    About negative and positive buttons, you can define 2 buttons in your layout file and set `onClickListener` on them ;) – Chris Margonis Feb 15 '13 at 05:35
  • I think i can't make changes to it because the view is created After the constructor is ran (obviously). so basically the view method doesn't really allow me to use the setter methods to change hour format and calendar display. man i'm losing my mind, i've been at this thing for 14 hours lol – user1848850 Feb 15 '13 at 05:35
  • yes i understand, i actually have this dialogbox working using public class DateTimePicker extends RelativeLayout implements View.OnClickListener, OnDateChangedListener, OnTimeChangedListener and this works but i'm trying to use the AlertDialog as per the android documentation, i read it about 8 times, they say nothing about accessing resources, i tried getDialog() getView activity. not sure what's going on, still a noob – user1848850 Feb 15 '13 at 05:37
  • Maybe if you move datePicker = (DatePicker) getView().findViewById(R.id.DatePicker); from activityCreated to onCreateView will solve your problem. – Chris Margonis Feb 15 '13 at 05:38
  • if i move it to onCreateview i still have to return the view right? and that view was already set in builder.setView. I don't see it, i'll try it though – user1848850 Feb 15 '13 at 05:44
  • Do you use the `onCreateView` like at the example I posted? `@Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment_edit_name, container); mEditText = (EditText) view.findViewById(R.id.txt_your_name); getDialog().setTitle("Hello"); return view; }` – Chris Margonis Feb 15 '13 at 05:48
  • yes i did, it allows me to get the activity going and allows me to access the R.id.DatePicker, but unfortunately i lose the Positive/Neutral/Negative buttons, and the reason i wanted to use AlertDialog.Builder was so it can take care of the buttons for me (as per the Android documentation). The other issue when using onCreateView is i can't use the setters because they crash it, so when i instantiate the object and then go to modify the hour format or set the Calendar display to off, it crashes – user1848850 Feb 15 '13 at 05:55