SlideDateTimePicker icon indicating copy to clipboard operation
SlideDateTimePicker copied to clipboard

how to set the minTime?

Open suchttta opened this issue 9 years ago • 6 comments

only minDate,i want to set minTime,how to do? just like not earlier than the current moment,now is 2015-10-22 15:37,date can set,but time not.

suchttta avatar Oct 22 '15 07:10 suchttta

Maybe provide a full min-datetime check - not only min-time? Would be much easier.

Rainer-Lang avatar Jan 15 '16 10:01 Rainer-Lang

I meet the same issue, is there any solution?

haogev6 avatar Apr 21 '16 06:04 haogev6

@suchttta @Rainer-Lang @haogev6 Did any of you found the solution?

SkyTreasure avatar May 23 '16 19:05 SkyTreasure

@SkyTreasure @haogev6 @Rainer-Lang @suchttta

Did you guys have a solution to this problem? I have been struggling with this for a while now

PatriceTP avatar Sep 06 '16 16:09 PatriceTP

I have fetching same issue, is there any one found solutions for same ?

sanjaysiliconithub avatar Feb 23 '17 10:02 sanjaysiliconithub

new SlideDateTimePicker.Builder(((FragmentActivity) mcontext).getSupportFragmentManager())
                        .setListener(listener)
                        .setInitialDate(new Date())
                        .setMinDate(minCalendar.getTime())
                        .setMaxDate(maxCalendar.getTime())
                        .setMinTime(minCalendar.getTime())
                        .setMaxTime(maxCalendar.getTime())
                        .build()
                        .show();

changes for setMinTime() and setMaxTime()

SlideDateTimeDialogFragment.java

package com.slidedatetimepicker;

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

import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.content.DialogInterface;
import android.os.Bundle;
import android.support.v4.app.DialogFragment;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.text.format.DateFormat;
import android.text.format.DateUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.Button;

/**
 * <p>The {@code DialogFragment} that contains the {@link SlidingTabLayout}
 * and {@link CustomViewPager}.</p>
 *
 * <p>The {@code CustomViewPager} contains the {@link DateFragment} and {@link TimeFragment}.</p>
 *
 * <p>This {@code DialogFragment} is managed by {@link SlideDateTimePicker}.</p>
 *
 * @author jjobes
 *
 */
public class SlideDateTimeDialogFragment extends DialogFragment implements DateFragment.DateChangedListener,
                                                                           TimeFragment.TimeChangedListener
{
    public static final String TAG_SLIDE_DATE_TIME_DIALOG_FRAGMENT = "tagSlideDateTimeDialogFragment";

    private static SlideDateTimeListener mListener;

    private Context mContext;
    private CustomViewPager mViewPager;
    private ViewPagerAdapter mViewPagerAdapter;
    private SlidingTabLayout mSlidingTabLayout;
    private View mButtonHorizontalDivider;
    private View mButtonVerticalDivider;
    private Button mOkButton;
    private Button mCancelButton;
    private Date mInitialDate;
    private int mTheme;
    private int mIndicatorColor;
    private Date mMinDate;
    private Date mMaxDate;
    private Date mMinTime;
    private Date mMaxTime;
    private boolean mIsClientSpecified24HourTime;
    private boolean mIs24HourTime;
    private Calendar mCalendar;
    private int mDateFlags =
        DateUtils.FORMAT_SHOW_WEEKDAY |
        DateUtils.FORMAT_SHOW_DATE |
        DateUtils.FORMAT_ABBREV_ALL;

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

    /**
     * <p>Return a new instance of {@code SlideDateTimeDialogFragment} with its bundle
     * filled with the incoming arguments.</p>
     *
     * <p>Called by {@link SlideDateTimePicker#show()}.</p>
     *
     * @param listener
     * @param initialDate
     * @param minDate
     * @param maxDate
     * @param isClientSpecified24HourTime
     * @param is24HourTime
     * @param theme
     * @param indicatorColor
     * @return
     */
    public static SlideDateTimeDialogFragment newInstance(SlideDateTimeListener listener,
            Date initialDate, Date minDate, Date maxDate, Date minTime, Date maxTime, boolean isClientSpecified24HourTime,
            boolean is24HourTime, int theme, int indicatorColor)
    {
        mListener = listener;

        // Create a new instance of SlideDateTimeDialogFragment
        SlideDateTimeDialogFragment dialogFragment = new SlideDateTimeDialogFragment();

        // Store the arguments and attach the bundle to the fragment
        Bundle bundle = new Bundle();
        bundle.putSerializable("initialDate", initialDate);
        bundle.putSerializable("minDate", minDate);
        bundle.putSerializable("maxDate", maxDate);
        bundle.putSerializable("minTime", minTime);
        bundle.putSerializable("maxTime", maxTime);
        bundle.putBoolean("isClientSpecified24HourTime", isClientSpecified24HourTime);
        bundle.putBoolean("is24HourTime", is24HourTime);
        bundle.putInt("theme", theme);
        bundle.putInt("indicatorColor", indicatorColor);
        dialogFragment.setArguments(bundle);

        // Return the fragment with its bundle
        return dialogFragment;
    }

    @Override
    public void onAttach(Activity activity)
    {
        super.onAttach(activity);

        mContext = activity;
    }

    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);

        setRetainInstance(true);

        unpackBundle();

        mCalendar = Calendar.getInstance();
        mCalendar.setTime(mInitialDate);

        switch (mTheme)
        {
        case SlideDateTimePicker.HOLO_DARK:
            setStyle(DialogFragment.STYLE_NO_TITLE, android.R.style.Theme_Holo_Dialog_NoActionBar);
            break;
        case SlideDateTimePicker.HOLO_LIGHT:
            setStyle(DialogFragment.STYLE_NO_TITLE, android.R.style.Theme_Holo_Light_Dialog_NoActionBar);
            break;
        default:  // if no theme was specified, default to holo light
            setStyle(DialogFragment.STYLE_NO_TITLE, android.R.style.Theme_Holo_Light_Dialog_NoActionBar);
        }
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
    {
        View view = inflater.inflate(R.layout.slide_date_time_picker, container);

        setupViews(view);
        customizeViews();
        initViewPager();
        initTabs();
        initButtons();

        return view;
    }

    @Override
    public void onDestroyView()
    {
        // Workaround for a bug in the compatibility library where calling
        // setRetainInstance(true) does not retain the instance across
        // orientation changes.
        if (getDialog() != null && getRetainInstance())
        {
            getDialog().setDismissMessage(null);
        }

        super.onDestroyView();
    }

    private void unpackBundle()
    {
        Bundle args = getArguments();

        mInitialDate = (Date) args.getSerializable("initialDate");
        mMinDate = (Date) args.getSerializable("minDate");
        mMaxDate = (Date) args.getSerializable("maxDate");
        mMinTime = (Date) args.getSerializable("minTime");
        mMaxTime = (Date) args.getSerializable("maxTime");
        mIsClientSpecified24HourTime = args.getBoolean("isClientSpecified24HourTime");
        mIs24HourTime = args.getBoolean("is24HourTime");
        mTheme = args.getInt("theme");
        mIndicatorColor = args.getInt("indicatorColor");
    }

    private void setupViews(View v)
    {
        mViewPager = (CustomViewPager) v.findViewById(R.id.viewPager);
        mSlidingTabLayout = (SlidingTabLayout) v.findViewById(R.id.slidingTabLayout);
        mButtonHorizontalDivider = v.findViewById(R.id.buttonHorizontalDivider);
        mButtonVerticalDivider = v.findViewById(R.id.buttonVerticalDivider);
        mOkButton = (Button) v.findViewById(R.id.okButton);
        mCancelButton = (Button) v.findViewById(R.id.cancelButton);
    }

    private void customizeViews()
    {
        int lineColor = mTheme == SlideDateTimePicker.HOLO_DARK ?
                getResources().getColor(R.color.gray_holo_dark) :
                getResources().getColor(R.color.gray_holo_light);

        // Set the colors of the horizontal and vertical lines for the
        // bottom buttons depending on the theme.
        switch (mTheme)
        {
        case SlideDateTimePicker.HOLO_LIGHT:
        case SlideDateTimePicker.HOLO_DARK:
            mButtonHorizontalDivider.setBackgroundColor(lineColor);
            mButtonVerticalDivider.setBackgroundColor(lineColor);
            break;

        default:  // if no theme was specified, default to holo light
            mButtonHorizontalDivider.setBackgroundColor(getResources().getColor(R.color.gray_holo_light));
            mButtonVerticalDivider.setBackgroundColor(getResources().getColor(R.color.gray_holo_light));
        }

        // Set the color of the selected tab underline if one was specified.
        if (mIndicatorColor != 0)
            mSlidingTabLayout.setSelectedIndicatorColors(mIndicatorColor);
    }

    private void initViewPager()
    {
        mViewPagerAdapter = new ViewPagerAdapter(getChildFragmentManager());
        mViewPager.setAdapter(mViewPagerAdapter);

        // Setting this custom layout for each tab ensures that the tabs will
        // fill all available horizontal space.
        mSlidingTabLayout.setCustomTabView(R.layout.custom_tab, R.id.tabText);
        mSlidingTabLayout.setViewPager(mViewPager);
    }

    private void initTabs()
    {
        // Set intial date on date tab
        updateDateTab();

        // Set initial time on time tab
        updateTimeTab();
    }

    private void initButtons()
    {
        mOkButton.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v)
            {
                if (mListener == null)
                {
                    throw new NullPointerException(
                            "Listener no longer exists for mOkButton");
                }

                mListener.onDateTimeSet(new Date(mCalendar.getTimeInMillis()));

                dismiss();
            }
        });

        mCancelButton.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v)
            {
                if (mListener == null)
                {
                    throw new NullPointerException(
                            "Listener no longer exists for mCancelButton");
                }

                mListener.onDateTimeCancel();

                dismiss();
            }
        });
    }

    /**
     * <p>The callback used by the DatePicker to update {@code mCalendar} as
     * the user changes the date. Each time this is called, we also update
     * the text on the date tab to reflect the date the user has currenly
     * selected.</p>
     *
     * <p>Implements the {@link DateFragment.DateChangedListener}
     * interface.</p>
     */
    @Override
    public void onDateChanged(int year, int month, int day)
    {
        mCalendar.set(year, month, day);

        updateDateTab();
    }

    /**
     * <p>The callback used by the TimePicker to update {@code mCalendar} as
     * the user changes the time. Each time this is called, we also update
     * the text on the time tab to reflect the time the user has currenly
     * selected.</p>
     *
     * <p>Implements the {@link TimeFragment.TimeChangedListener}
     * interface.</p>
     */
    @Override
    public void onTimeChanged(int hour, int minute)
    {
        mCalendar.set(Calendar.HOUR_OF_DAY, hour);
        mCalendar.set(Calendar.MINUTE, minute);

        updateTimeTab();
    }

    private void updateDateTab()
    {
        mSlidingTabLayout.setTabText(0, DateUtils.formatDateTime(
                mContext, mCalendar.getTimeInMillis(), mDateFlags));
    }

    @SuppressLint("SimpleDateFormat")
    private void updateTimeTab()
    {
        if (mIsClientSpecified24HourTime)
        {
            SimpleDateFormat formatter;

            if (mIs24HourTime)
            {
                formatter = new SimpleDateFormat("HH:mm");
                mSlidingTabLayout.setTabText(1, formatter.format(mCalendar.getTime()));
            }
            else
            {
                formatter = new SimpleDateFormat("h:mm aa");
                mSlidingTabLayout.setTabText(1, formatter.format(mCalendar.getTime()));
            }
        }
        else  // display time using the device's default 12/24 hour format preference
        {
            mSlidingTabLayout.setTabText(1, DateFormat.getTimeFormat(
                    mContext).format(mCalendar.getTimeInMillis()));
        }
    }

    /**
     * <p>Called when the user clicks outside the dialog or presses the <b>Back</b>
     * button.</p>
     *
     * <p><b>Note:</b> Actual <b>Cancel</b> button clicks are handled by {@code mCancelButton}'s
     * event handler.</p>
     */
    @Override
    public void onCancel(DialogInterface dialog)
    {
        super.onCancel(dialog);

        if (mListener == null)
        {
            throw new NullPointerException(
                    "Listener no longer exists in onCancel()");
        }

        mListener.onDateTimeCancel();
    }

    private class ViewPagerAdapter extends FragmentPagerAdapter
    {
        public ViewPagerAdapter(FragmentManager fm)
        {
            super(fm);
        }

        @Override
        public Fragment getItem(int position)
        {
            switch (position)
            {
                case 0:
                    DateFragment dateFragment = DateFragment.newInstance(
                            mTheme,
                            mCalendar.get(Calendar.YEAR),
                            mCalendar.get(Calendar.MONTH),
                            mCalendar.get(Calendar.DAY_OF_MONTH),
                            mMinDate,
                            mMaxDate);
                    //  dateFragment.setTargetFragment(SlideDateTimeDialogFragment.this, 100);
                    return dateFragment;
                case 1:
                    TimeFragment timeFragment = TimeFragment.newInstance(
                            mTheme,
                            mCalendar,
                            mCalendar.get(Calendar.HOUR_OF_DAY),
                            mCalendar.get(Calendar.MINUTE),
                            mIsClientSpecified24HourTime,
                            mIs24HourTime,
                            mMinTime,
                            mMaxTime);
                    // timeFragment.setTargetFragment(SlideDateTimeDialogFragment.this, 200);
                    return timeFragment;
                default:
                    return null;
            }
        }

        @Override
        public int getCount()
        {
            return 2;
        }
    }
}

SlideDateTimePicker.java

package com.slidedatetimepicker;

import java.util.Date;

import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;

/**
 * <p>This class contains methods for the library client to create
 * a new {@code SlideDateTimePicker}.</p>
 *
 * <p>It also implements a Builder API that offers more convenient
 * object creation.</p>
 *
 * @author jjobes
 *
 */
public class SlideDateTimePicker
{
    public static final int HOLO_DARK = 1;
    public static final int HOLO_LIGHT = 2;

    private FragmentManager mFragmentManager;
    private SlideDateTimeListener mListener;
    private Date mInitialDate;
    private Date mMinDate;
    private Date mMaxDate;
    private Date mMinTime;
    private Date mMaxTime;
    private boolean mIsClientSpecified24HourTime;
    private boolean mIs24HourTime;
    private int mTheme;
    private int mIndicatorColor;

    /**
     * Creates a new instance of {@code SlideDateTimePicker}.
     *
     * @param fm  The {@code FragmentManager} from the calling activity that is used
     *            internally to show the {@code DialogFragment}.
     */
    public SlideDateTimePicker(FragmentManager fm)
    {
        // See if there are any DialogFragments from the FragmentManager
        FragmentTransaction ft = fm.beginTransaction();
        Fragment prev = fm.findFragmentByTag(SlideDateTimeDialogFragment.TAG_SLIDE_DATE_TIME_DIALOG_FRAGMENT);

        // Remove if found
        if (prev != null)
        {
            ft.remove(prev);
            ft.commit();
        }

        mFragmentManager = fm;
    }

    /**
     * <p>Sets the listener that is used to inform the client when
     * the user selects a new date and time.</p>
     *
     * <p>This must be called before {@link #show()}.</p>
     *
     * @param listener
     */
    public void setListener(SlideDateTimeListener listener)
    {
        mListener = listener;
    }

    /**
     * <p>Sets the initial date and time to display in the date
     * and time pickers.</p>
     *
     * <p>If this method is not called, the current date and time
     * will be displayed.</p>
     *
     * @param initialDate  the {@code Date} object used to determine the
     *                     initial date and time to display
     */
    public void setInitialDate(Date initialDate)
    {
        mInitialDate = initialDate;
    }

    /**
     * <p>Sets the minimum date that the DatePicker should show.</p>
     *
     * <p>This must be called before {@link #show()}.</p>
     *
     * @param minDate  the minimum selectable date for the DatePicker
     */
    public void setMinDate(Date minDate)
    {
        mMinDate = minDate;
    }

    /**
     * <p>Sets the maximum date that the DatePicker should show.</p>
     *
     * <p>This must be called before {@link #show()}.</p>
     *
     * @param maxDate  the maximum selectable date for the DatePicker
     */
    public void setMaxDate(Date maxDate)
    {
        mMaxDate = maxDate;
    }

    /**
     * <p>Sets the minimum date time that the DatePicker should show.</p>
     *
     * <p>This must be called before {@link #show()}.</p>
     *
     * @param minTime  the minimum selectable date for the DatePicker
     */
    public void setMinTime(Date minTime)
    {
        mMinTime = minTime;
    }

    /**
     * <p>Sets the maximum date that the DatePicker should show.</p>
     *
     * <p>This must be called before {@link #show()}.</p>
     *
     * @param maxTime  the maximum selectable date for the DatePicker
     */
    public void setMaxTime(Date maxTime)
    {
        mMaxTime = maxTime;
    }

    private void setIsClientSpecified24HourTime(boolean isClientSpecified24HourTime)
    {
        mIsClientSpecified24HourTime = isClientSpecified24HourTime;
    }

    /**
     * <p>Sets whether the TimePicker displays its time in 12-hour
     * (AM/PM) or 24-hour format.</p>
     *
     * <p>If this method is not called, the device's default time
     * format is used.</p>
     *
     * <p>This also affects the time displayed in the tab.</p>
     *
     * <p>Must be called before {@link #show()}.</p>
     *
     * @param is24HourTime  <tt>true</tt> to force 24-hour time format,
     *                      <tt>false</tt> to force 12-hour (AM/PM) time
     *                      format.
     */
    public void setIs24HourTime(boolean is24HourTime)
    {
        setIsClientSpecified24HourTime(true);
        mIs24HourTime = is24HourTime;
    }

    /**
     * Sets the theme of the dialog. If no theme is specified, it
     * defaults to holo light.
     *
     * @param theme  {@code SlideDateTimePicker.HOLO_DARK} for a dark theme, or
     *               {@code SlideDateTimePicker.HOLO_LIGHT} for a light theme
     */
    public void setTheme(int theme)
    {
        mTheme = theme;
    }

    /**
     * Sets the color of the underline for the currently selected tab.
     *
     * @param indicatorColor  the color of the selected tab's underline
     */
    public void setIndicatorColor(int indicatorColor)
    {
        mIndicatorColor = indicatorColor;
    }

    /**
     * Shows the dialog to the user. Make sure to call
     * before calling this.
     */
    public void show()
    {
        if (mListener == null)
        {
            throw new NullPointerException(
                    "Attempting to bind null listener to SlideDateTimePicker");
        }

        if (mInitialDate == null)
        {
            setInitialDate(new Date());
        }

        SlideDateTimeDialogFragment dialogFragment =
                SlideDateTimeDialogFragment.newInstance(
                        mListener,
                        mInitialDate,
                        mMinDate,
                        mMaxDate,
                        mMinTime,
                        mMaxTime,
                        mIsClientSpecified24HourTime,
                        mIs24HourTime,
                        mTheme,
                        mIndicatorColor);

        dialogFragment.show(mFragmentManager,
                SlideDateTimeDialogFragment.TAG_SLIDE_DATE_TIME_DIALOG_FRAGMENT);
    }

    /*
     * The following implements the builder API to simplify
     * creation and display of the dialog.
     */
    public static class Builder
    {
        // Required
        private FragmentManager fm;
        private SlideDateTimeListener listener;

        // Optional
        private Date initialDate;
        private Date minDate;
        private Date maxDate;
        private Date minTime;
        private Date maxTime;
        private boolean isClientSpecified24HourTime;
        private boolean is24HourTime;
        private int theme;
        private int indicatorColor;

        public Builder(FragmentManager fm)
        {
            this.fm = fm;
        }

        /**
         * @see SlideDateTimePicker#setListener(SlideDateTimeListener)
         */
        public Builder setListener(SlideDateTimeListener listener)
        {
            this.listener = listener;
            return this;
        }

        /**
         * @see SlideDateTimePicker#setInitialDate(Date)
         */
        public Builder setInitialDate(Date initialDate)
        {
            this.initialDate = initialDate;
            return this;
        }

        /**
         * @see SlideDateTimePicker#setMinDate(Date)
         */
        public Builder setMinDate(Date minDate)
        {
            this.minDate = minDate;
            return this;
        }

        /**
         * @see SlideDateTimePicker#setMaxDate(Date)
         */
        public Builder setMaxDate(Date maxDate)
        {
            this.maxDate = maxDate;
            return this;
        }

        /**
         * @see SlideDateTimePicker#setMinTime(Date)
         */
        public Builder setMinTime(Date minTime)
        {
            this.minTime = minTime;
            return this;
        }

        /**
         * @see SlideDateTimePicker#setMaxTime(Date)
         */
        public Builder setMaxTime(Date maxTime)
        {
            this.maxTime = maxTime;
            return this;
        }

        /**
         * @see SlideDateTimePicker#setIs24HourTime(boolean)
         */
        public Builder setIs24HourTime(boolean is24HourTime)
        {
            this.isClientSpecified24HourTime = true;
            this.is24HourTime = is24HourTime;
            return this;
        }

        /**
         * @see SlideDateTimePicker#setTheme(int)
         */
        public Builder setTheme(int theme)
        {
            this.theme = theme;
            return this;
        }

        /**
         * @see SlideDateTimePicker#setIndicatorColor(int)
         */
        public Builder setIndicatorColor(int indicatorColor)
        {
            this.indicatorColor = indicatorColor;
            return this;
        }

        /**
         * <p>Build and return a {@code SlideDateTimePicker} object based on the previously
         * supplied parameters.</p>
         *
         * <p>You should call {@link #show()} immediately after this.</p>
         *
         * @return
         */
        public SlideDateTimePicker build()
        {
            SlideDateTimePicker picker = new SlideDateTimePicker(fm);
            picker.setListener(listener);
            picker.setInitialDate(initialDate);
            picker.setMinDate(minDate);
            picker.setMaxDate(maxDate);
            picker.setMinTime(minTime);
            picker.setMaxTime(maxTime);
            picker.setIsClientSpecified24HourTime(isClientSpecified24HourTime);
            picker.setIs24HourTime(is24HourTime);
            picker.setTheme(theme);
            picker.setIndicatorColor(indicatorColor);

            return picker;
        }
    }
}

TimeFragment.java

package com.slidedatetimepicker;

import android.content.Context;
import android.os.Build;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.text.format.DateFormat;
import android.util.Log;
import android.view.ContextThemeWrapper;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.DatePicker;
import android.widget.NumberPicker;
import android.widget.NumberPicker.OnValueChangeListener;
import android.widget.TimePicker;

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

/**
 * The fragment for the second page in the ViewPager that holds
 * the TimePicker.
 *
 * @author jjobes
 *
 */
public class TimeFragment extends Fragment
{
    /**
     * Used to communicate back to the parent fragment as the user
     * is changing the time spinners so we can dynamically update
     * the tab text.
     */
    public static final String TAG = TimeFragment.class.getName();
    Date minTime;
    Date maxTime;
    Calendar mCalendar;

    private int currentHour = 0;
    private int currentMinute = 0;

    public interface TimeChangedListener
    {
        void onTimeChanged(int hour, int minute);
    }

    private TimeChangedListener mCallback;
    private TimePicker mTimePicker;

    public TimeFragment()
    {
        // Required empty public constructor for fragment.
    }

    /**
     * Cast the reference to {@link SlideDateTimeDialogFragment} to a
     * {@link TimeChangedListener}.
     */
    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);

        try
        {
            mCallback = (TimeChangedListener) getParentFragment();
        }
        catch (ClassCastException e)
        {
            throw new ClassCastException("Calling fragment must implement " +
                "TimeFragment.TimeChangedListener interface");
        }
    }

    /**
     * Return an instance of TimeFragment with its bundle filled with the
     * constructor arguments. The values in the bundle are retrieved in
     * below to properly initialize the TimePicker.
     *
     * @param theme
     * @param hour
     * @param minute
     * @param isClientSpecified24HourTime
     * @param is24HourTime
     * @return
     */
    public static final TimeFragment newInstance(int theme, Calendar mCalendar, int hour, int minute,
        boolean isClientSpecified24HourTime, boolean is24HourTime, Date mMinTime, Date mMaxTime)
    {
        TimeFragment f = new TimeFragment();

        Bundle b = new Bundle();
        b.putInt("theme", theme);
        b.putSerializable("calendar", mCalendar);
        b.putInt("hour", hour);
        b.putInt("minute", minute);
        b.putBoolean("isClientSpecified24HourTime", isClientSpecified24HourTime);
        b.putBoolean("is24HourTime", is24HourTime);
        b.putSerializable("minTime", mMinTime);
        b.putSerializable("maxTime", mMaxTime);
        f.setArguments(b);

        return f;
    }

    /**
     * Create and return the user interface view for this fragment.
     */
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState)
    {
        int theme = getArguments().getInt("theme");

        mCalendar = (Calendar) getArguments().getSerializable("calendar");

        int initialHour = getArguments().getInt("hour");
        int initialMinute = getArguments().getInt("minute");

        currentHour = initialHour;
        currentMinute = initialMinute;

        boolean isClientSpecified24HourTime = getArguments().getBoolean("isClientSpecified24HourTime");
        boolean is24HourTime = getArguments().getBoolean("is24HourTime");
        minTime = (Date) getArguments().getSerializable("minTime");
        maxTime = (Date) getArguments().getSerializable("maxTime");

        if (minTime != null)
        {
            Calendar minTimeCalendar = Calendar.getInstance();
            minTimeCalendar.setTime(minTime);

            if (minTimeCalendar.get(Calendar.DAY_OF_MONTH) == mCalendar.get(Calendar.DAY_OF_MONTH) &&
                    minTimeCalendar.get(Calendar.MONTH) == mCalendar.get(Calendar.MONTH) &&
                    minTimeCalendar.get(Calendar.YEAR) == mCalendar.get(Calendar.YEAR)) {
                initialHour = 0;
                initialMinute = 0;
            }
        }

        if (maxTime != null)
        {
            Calendar maxTimeCalendar = Calendar.getInstance();
            maxTimeCalendar.setTime(maxTime);

            if (maxTimeCalendar.get(Calendar.DAY_OF_MONTH) == mCalendar.get(Calendar.DAY_OF_MONTH) &&
                    maxTimeCalendar.get(Calendar.MONTH) == mCalendar.get(Calendar.MONTH) &&
                    maxTimeCalendar.get(Calendar.YEAR) == mCalendar.get(Calendar.YEAR)) {
                initialHour = 0;
                initialMinute = 0;
            }
        }

        // Unless we inflate using a cloned inflater with a Holo theme,
        // on Lollipop devices the TimePicker will be the new-style
        // radial TimePicker, which is not what we want. So we will
        // clone the inflater that we're given but with our specified
        // theme, then inflate the layout with this new inflater.

        Context contextThemeWrapper = new ContextThemeWrapper(
                getActivity(),
                theme == SlideDateTimePicker.HOLO_DARK ?
                         android.R.style.Theme_Holo :
                         android.R.style.Theme_Holo_Light);

        LayoutInflater localInflater = inflater.cloneInContext(contextThemeWrapper);

        View v = localInflater.inflate(R.layout.fragment_time, container, false);

        mTimePicker = (TimePicker) v.findViewById(R.id.timePicker);
        // block keyboard popping up on touch
        mTimePicker.setDescendantFocusability(DatePicker.FOCUS_BLOCK_DESCENDANTS);
        mTimePicker.setOnTimeChangedListener(new TimePicker.OnTimeChangedListener() {

            @Override
            public void onTimeChanged(TimePicker view, int hourOfDay, int minute)
            {
                mCallback.onTimeChanged(hourOfDay, minute);
            }
        });

        // If the client specifies a 24-hour time format, set it on
        // the TimePicker.
        if (isClientSpecified24HourTime)
        {
            mTimePicker.setIs24HourView(is24HourTime);
        }
        else
        {
            // If the client does not specify a 24-hour time format, use the
            // device default.
            mTimePicker.setIs24HourView(DateFormat.is24HourFormat(
                getTargetFragment().getActivity()));
        }

        mTimePicker.setCurrentHour(initialHour);
        mTimePicker.setCurrentMinute(initialMinute);

        // Fix for the bug where a TimePicker's onTimeChanged() is not called when
        // the user toggles the AM/PM button. Only applies to 4.0.0 and 4.0.3.
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH &&
            Build.VERSION.SDK_INT <= Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1)
        {
            fixTimePickerBug18982();
        }

        mTimePicker.setOnTimeChangedListener(new TimePicker.OnTimeChangedListener() {
            @Override
            public void onTimeChanged(TimePicker view, int hourOfDay, int minute) {
                Log.d(TAG, "onTimeChanged:\nhourOfDay:" + hourOfDay + "\nminute:" + minute + "\nDAY_OF_MONTH:" + mCalendar.get(Calendar.DAY_OF_MONTH) + "\nMONTH:" + mCalendar.get(Calendar.MONTH) + "\nYEAR:" + mCalendar.get(Calendar.YEAR));
                boolean validTime = true;

                if (minTime != null) {
                    Calendar minTimeCalendar = Calendar.getInstance();
                    minTimeCalendar.setTime(minTime);

                    if (minTimeCalendar.get(Calendar.DAY_OF_MONTH) == mCalendar.get(Calendar.DAY_OF_MONTH) &&
                            minTimeCalendar.get(Calendar.MONTH) == mCalendar.get(Calendar.MONTH) &&
                            minTimeCalendar.get(Calendar.YEAR) == mCalendar.get(Calendar.YEAR)) {
                        if (hourOfDay < minTimeCalendar.get(Calendar.HOUR_OF_DAY) || (hourOfDay == minTimeCalendar.get(Calendar.HOUR_OF_DAY) && minute < minTimeCalendar.get(Calendar.MINUTE))) {
                            validTime = false;
                        }
                    }
                }

                if (maxTime != null) {
                    Calendar maxTimeCalendar = Calendar.getInstance();
                    maxTimeCalendar.setTime(maxTime);

                    if (maxTimeCalendar.get(Calendar.DAY_OF_MONTH) == mCalendar.get(Calendar.DAY_OF_MONTH) &&
                            maxTimeCalendar.get(Calendar.MONTH) == mCalendar.get(Calendar.MONTH) &&
                            maxTimeCalendar.get(Calendar.YEAR) == mCalendar.get(Calendar.YEAR)) {
                        if (hourOfDay > maxTimeCalendar.get(Calendar.HOUR_OF_DAY) || (hourOfDay == maxTimeCalendar.get(Calendar.HOUR_OF_DAY) && minute > maxTimeCalendar.get(Calendar.MINUTE))) {
                            validTime = false;
                        }
                    }
                }

                if (validTime) {
                    currentHour = hourOfDay;
                    currentMinute = minute;
                }

                updateTime(currentHour, currentMinute);
            }
        });

        return v;
    }

    /**
     * Sets the current time.
     *
     * @param hourOfDay The current hour within the day.
     * @param minuteOfHour The current minute within the hour.
     */
    public void updateTime(int hourOfDay, int minuteOfHour) {
        mTimePicker.setCurrentHour(hourOfDay);
        mTimePicker.setCurrentMinute(minuteOfHour);
    }

    /**
     * Workaround for bug in Android TimePicker where the onTimeChanged() callback
     * is not invoked when the user toggles between AM/PM. But we need to be able
     * to detect this in order to dynamically update the tab title properly when
     * the user toggles between AM/PM.
     *
     * Registered as Issue 18982:
     *
     * https://code.google.com/p/android/issues/detail?id=18982
     */
    private void fixTimePickerBug18982()
    {
        View amPmView = ((ViewGroup) mTimePicker.getChildAt(0)).getChildAt(3);

        if (amPmView instanceof NumberPicker)
        {
            ((NumberPicker) amPmView).setOnValueChangedListener(new OnValueChangeListener() {

                @Override
                public void onValueChange(NumberPicker picker, int oldVal, int newVal)
                {
                    if (picker.getValue() == 1)  // PM
                    {
                        if (mTimePicker.getCurrentHour() < 12)
                            mTimePicker.setCurrentHour(mTimePicker.getCurrentHour() + 12);
                    }
                    else  // AM
                    {
                        if (mTimePicker.getCurrentHour() >= 12)
                            mTimePicker.setCurrentHour(mTimePicker.getCurrentHour() - 12);
                    }

                    mCallback.onTimeChanged(
                        mTimePicker.getCurrentHour(),
                        mTimePicker.getCurrentMinute());
                }
            });
        }
    }
}

patelhari avatar Jun 07 '18 10:06 patelhari