br.com.app.applica.util.DateTimePickerFragment.java Source code

Java tutorial

Introduction

Here is the source code for br.com.app.applica.util.DateTimePickerFragment.java

Source

package br.com.app.applica.util;
/*
 *     Copyright 2016 Makoto Consulting Group, Inc.
 *
 *     Licensed under the Apache License, Version 2.0 (the "License");
 *     you may not use this file except in compliance with the License.
 *     You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 *     Unless required by applicable law or agreed to in writing, software
 *     distributed under the License is distributed on an "AS IS" BASIS,
 *     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *     See the License for the specific language governing permissions and
 *     limitations under the License.
 *
 */

import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.DatePicker;
import android.widget.Spinner;
import android.widget.TimePicker;

import org.joda.time.LocalDateTime;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Objects;

import br.com.app.applica.R;
import br.com.app.applica.fragment.FragmentFactory;

/**
 *
 */
public class DateTimePickerFragment extends AbstractDialogFragment {

    public static final String DIALOG_TAG = DateTimePickerFragment.class.getName();

    public static final String RESULT_DATE_TIME = "result." + DateTimePickerFragment.class.getName();
    public static final String TIME = "Hora";
    public static final String DATE = "Data";
    public static final String BOTH = "BOTH";

    private static final String TAG = DateTimePickerFragment.class.getSimpleName();

    private Date mDate;
    private String mDateType;
    private String mDateOrTimeChoice;

    /**
     * Maintain a reference to the DatePicker to work around a bug in Android 5.
     * The OnWhatever() listener does not work, so whenver we need to pull the values
     * in the Pickers, we have to reference them directly. We do not, however, need
     * to save these in the Bundle because they can always be recreated if necessary
     * (on device rotation, say).
     */
    private DatePicker mDatePicker;
    private TimePicker mTimePicker;

    /**
     * This interface is implemented by the caller, if it wants the result delivered
     * this way. Otherwise, onActivityResult() will be used.
     */
    public interface ResultHandler extends Serializable {
        void setDate(Date result);
    }

    /**
     * The ResultHandler (if used). Basically, this is so we can use this DialogFragment
     * directly from an Activity (rather than a Fragment).
     */
    private ResultHandler mResultHandler;

    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        // Pull the date out of the Fragment Arguments
        processFragmentArguments();
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(mDate);
        int year = calendar.get(Calendar.YEAR);
        int month = calendar.get(Calendar.MONTH);
        int day = calendar.get(Calendar.DAY_OF_MONTH);

        @SuppressLint("InflateParams")
        View view = LayoutInflater.from(getActivity()).inflate(R.layout.fragment_date_time, null);

        // Spinner to choose either Date or Time to edit
        final Spinner dateTimeSpinner = (Spinner) view.findViewById(R.id.spinner_date_time_choice);
        mDatePicker = (DatePicker) view.findViewById(R.id.date_picker);
        mTimePicker = (TimePicker) view.findViewById(R.id.time_picker);
        // Note: the OnDateChangedListener does not work in Android 5 when using the
        /// super cool material style of calendar, which is really slick.
        mDatePicker.init(year, month, day, null);

        int hourOfDay = calendar.get(Calendar.HOUR_OF_DAY);
        int minuteOfHour = calendar.get(Calendar.MINUTE);
        //noinspection deprecation
        mTimePicker.setCurrentHour(hourOfDay);
        //noinspection deprecation
        mTimePicker.setCurrentMinute(minuteOfHour);

        configureDateTimeSpinner(dateTimeSpinner);
        // Now show the Dialog in all its glory!
        return new AlertDialog.Builder(getActivity()).setView(view).setTitle(R.string.choose_date_or_time)
                .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        final String METHOD = "onClick(" + dialog + ", " + which + "): ";
                        if (getTargetFragment() == null && mResultHandler == null) {
                            Log.e(TAG, "Both Target Fragment and ResultHandler are null!");
                        } else {
                            //noinspection deprecation
                            mDate = computeDateFromComponents(mDatePicker.getYear(), mDatePicker.getMonth(),
                                    mDatePicker.getDayOfMonth(), mTimePicker.getCurrentHour(),
                                    mTimePicker.getCurrentMinute());
                            if (mResultHandler == null) {
                                Intent intent = new Intent();
                                intent.putExtra(RESULT_DATE_TIME, mDate);
                                getTargetFragment().onActivityResult(getTargetRequestCode(), Activity.RESULT_OK,
                                        intent);
                                Log.d(TAG, METHOD + "Sending result back to the caller...:"
                                        + new LocalDateTime(mDate.getTime()).toString("MM/dd/yyyy hh:mm a"));
                            } else {
                                mResultHandler.setDate(mDate);
                            }
                        }
                    }
                }).create();
    }

    @Override
    protected void restoreInstanceState(Bundle savedInstanceState) {
        // Nothing to do
    }

    @Override
    protected void saveInstanceState(Bundle outState) {
        // Nothing to do
    }

    private void configureDateTimeSpinner(final Spinner dateTimeSpinner) {
        List<String> choices = new ArrayList<>();
        if (Objects.equals(DATE, mDateOrTimeChoice)) {
            choices.add(computeChoice(DATE));
        } else if (Objects.equals(TIME, mDateOrTimeChoice)) {
            choices.add(computeChoice(TIME));
        } else {
            choices.add(computeChoice(TIME));
            choices.add(computeChoice(DATE));
        }
        dateTimeSpinner.setAdapter(new ArrayAdapter<>(getActivity(), android.R.layout.simple_list_item_1, choices));
        dateTimeSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
                String choice = (String) dateTimeSpinner.getAdapter().getItem(position);
                if (choice.equalsIgnoreCase(computeChoice(DATE))) {
                    // Make the DatePicker visible
                    mDatePicker.setVisibility(View.VISIBLE);
                    mTimePicker.setVisibility(View.GONE);
                } else {
                    // Make the TimePicker visible
                    mTimePicker.setVisibility(View.VISIBLE);
                    mDatePicker.setVisibility(View.GONE);
                }
            }

            @Override
            public void onNothingSelected(AdapterView<?> parent) {

            }
        });
        // Select initial choice if neither preferred.
        if (mDateOrTimeChoice == null) {
            dateTimeSpinner.setSelection(choices.indexOf(computeChoice(TIME)));
        } else {
            dateTimeSpinner.setSelection(choices.indexOf(computeChoice(mDateOrTimeChoice)));
        }
    }

    private String computeChoice(String baseChoice) {
        return baseChoice;
    }

    @Override
    protected void processFragmentArguments() {
        mDate = (Date) getArguments().getSerializable(FragmentFactory.FRAG_ARG_DATE);
        // Sanity check
        if (mDate == null) {
            throw new RuntimeException("Fragment argument (" + FragmentFactory.FRAG_ARG_DATE + ") cannot be null!");
        }
        mDateType = (String) getArguments().getSerializable(FragmentFactory.FRAG_ARG_DATE_TYPE);
        // Sanity check
        if (mDateType == null || mDateType.isEmpty()) {
            throw new RuntimeException(
                    "Fragment argument (" + FragmentFactory.FRAG_ARG_DATE_TYPE + ") cannot be null!");
        }

        mDateOrTimeChoice = (String) getArguments()
                .getSerializable(FragmentFactory.FRAG_ARG_DATETIME_PICKER_CHOICE);

        mResultHandler = (ResultHandler) getArguments()
                .getSerializable(FragmentFactory.FRAG_ARG_DATETIME_PICKER_RESULT_HANDLER);
    }

    private Date computeDateFromComponents(int year, int monthOfYear, int dayOfMonth, int hourOfDay,
            int minuteOfHour) {
        final String METHOD = "computeDateFromComponents(" + year + "," + monthOfYear + "," + dayOfMonth + ","
                + hourOfDay + "," + minuteOfHour + ")";
        Calendar changedDateCalendar = Calendar.getInstance();
        changedDateCalendar.set(Calendar.YEAR, year);
        changedDateCalendar.set(Calendar.MONTH, monthOfYear);
        changedDateCalendar.set(Calendar.DAY_OF_MONTH, dayOfMonth);
        changedDateCalendar.set(Calendar.HOUR_OF_DAY, hourOfDay);
        changedDateCalendar.set(Calendar.MINUTE, minuteOfHour);
        changedDateCalendar.set(Calendar.SECOND, 0);
        changedDateCalendar.set(Calendar.MILLISECOND, 0);
        Date ret = changedDateCalendar.getTime();
        Log.d(TAG, METHOD + "Returning date: " + ret);
        return ret;
    }
}