├── README.md ├── android ├── build.gradle └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── com │ │ └── hijridatepicker │ │ ├── HijriDatePickerAndroidModule.java │ │ ├── HijriDatePickerDialogFragment.java │ │ ├── HijriDialogViewManagerPackage.java │ │ └── SupportHijriDatePickerDialogFragment.java │ └── res │ ├── layout │ └── dialog_basic.xml │ ├── values-ar │ └── strings.xml │ └── values │ └── strings.xml ├── index.android.js ├── index.ios.js └── package.json /README.md: -------------------------------------------------------------------------------- 1 | 2 | # react-native-hijri-date-picker-android 3 | [![Codelab](http://www.codelabsys.com/images/logo.png)](http://www.codelabsys.com/) 4 | 5 | 6 | #This Module version is experimental, if you found any issues, kindly submit. 7 | 8 | ## Getting started 9 | ### Versions 10 | For React Native >= 0.47.0 use v2.+ 11 | For React Native < 0.47.0 use v1.0.8 12 | 13 | ### Installing 14 | [![NPM](https://nodei.co/npm/react-native-hijri-date-picker-android.png?downloads=true&downloadRank=true&stars=true)](https://nodei.co/npm/react-native-hijri-date-picker-android/) 15 | 16 | `$ npm install react-native-hijri-date-picker-android --save` 17 | 18 | ### Mostly automatic installation 19 | 20 | `$ react-native link react-native-hijri-date-picker-android` 21 | 22 | ### Manual installation 23 | 24 | #### Android 25 | 26 | 1. Open up `android/app/src/main/java/[...]/MainActivity.java` 27 | - Add `import com.reactlibrary.HijriDatePickerAndroidPackage;` to the imports at the top of the file 28 | - Add `new HijriDatePickerAndroidPackage()` to the list returned by the `getPackages()` method 29 | 2. Append the following lines to `android/settings.gradle`: 30 | ``` 31 | include ':react-native-hijri-date-picker-android' 32 | project(':react-native-hijri-date-picker-android').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-hijri-date-picker-android/android') 33 | ``` 34 | 3. Insert the following lines inside the dependencies block in `android/app/build.gradle`: 35 | ``` 36 | compile project(':react-native-hijri-date-picker-android') 37 | ``` 38 | 39 | 40 | ## Usage 41 | ```javascript 42 | //first include HijriDatePickerAndroid 43 | import HijriDatePickerAndroid from "react-native-hijri-date-picker-android"; 44 | 45 | 46 | let options = { date: new Date(), minDate: new Date(new Date().getTime() - (1 * 30 * 24 * 60 * 60 * 1000)), maxDate: new Date(new Date().getTime() + (1 * 30 * 24 * 60 * 60 * 1000)) }; 47 | let stringOptions = { date: "27-7-1438", minDate: "25-6-1438", maxDate: "29-8-1438" }; 48 | //mode:"no_arrows" hide the arrows at the bar of the calendar 49 | //weekDayLabels, override the default day labels at the calendar 50 | let moreOptions = { date: "27-7-1438", minDate: "25-6-1438", maxDate: "29-8-1438", mode:"no_arrows", weekDayLabels:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"]}; 51 | //accepts option dates with date objects or strings in the following format ['dd-MM-yyyy'] 52 | HijriDatePickerAndroid.open(stringOptions).then(function (result) { 53 | if (result.action == HijriDatePickerAndroid.dismissedAction) { 54 | console.warn("Dismissed"); 55 | } else { 56 | let { year, day, month } = result; 57 | console.warn("Hijri Date: " + day + "/" +( month + 1) + "/" + year + "/"); 58 | } 59 | }); 60 | 61 | //convert string Hijri date ['dd-MM-yyyy'] to a gregorian timestamp 62 | HijriDatePickerAndroid.convertHijriDateToGregorianDate("12-7-1438").then(function (result) { 63 | console.warn("Gregorian Timestamp" + JSON.stringify(result)); 64 | 65 | }); 66 | 67 | 68 | //convert gregorian date object to hijri {year,month,day} 69 | HijriDatePickerAndroid.convertGregorianDateToHijriDate(new Date()).then(function ({ year, day, month }) { 70 | console.warn("Hijri Date: " + day + "/" + month + 1 + "/" + year + "/"); 71 | 72 | ``` 73 | 74 | ## For IOS 75 | 76 | Check out our IOS project [react-native-universal-datepicker-ios](https://github.com/Codelabsys/react-native-universal-datepicker-ios) 77 | 78 | 79 | ## Credits 80 | 81 | This project was made by the help of [Assem-Hafez](https://github.com/Assem-Hafez) and [Mohamed-Abbas](https://github.com/Mohamed-Abbas) 82 | for the company we're working at [Codelabsys](http://www.codelabsys.com/) 83 | 84 | And is based on the following projects, [material-hijri-calendarview](https://github.com/eltohamy/material-hijri-calendarview) and [ummalqura-calendar](https://github.com/msarhan/ummalqura-calendar) 85 | -------------------------------------------------------------------------------- /android/build.gradle: -------------------------------------------------------------------------------- 1 | 2 | buildscript { 3 | repositories { 4 | jcenter() 5 | } 6 | 7 | dependencies { 8 | classpath 'com.android.tools.build:gradle:1.3.1' 9 | } 10 | } 11 | 12 | apply plugin: 'com.android.library' 13 | 14 | android { 15 | compileSdkVersion 23 16 | buildToolsVersion "23.0.1" 17 | 18 | defaultConfig { 19 | minSdkVersion 16 20 | targetSdkVersion 22 21 | versionCode 1 22 | versionName "1.0" 23 | } 24 | lintOptions { 25 | abortOnError false 26 | } 27 | } 28 | 29 | repositories { 30 | mavenCentral() 31 | } 32 | 33 | dependencies { 34 | compile 'com.facebook.react:react-native:+' 35 | compile 'com.github.eltohamy:material-hijri-calendarview:1.1.0@aar' 36 | compile group: 'com.github.msarhan', name: 'ummalqura-calendar', version:'1.1.7' 37 | } 38 | -------------------------------------------------------------------------------- /android/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /android/src/main/java/com/hijridatepicker/HijriDatePickerAndroidModule.java: -------------------------------------------------------------------------------- 1 | package com.hijridatepicker; 2 | 3 | 4 | import android.app.Activity; 5 | import android.app.DatePickerDialog; 6 | import android.app.DialogFragment; 7 | import android.app.FragmentManager; 8 | import android.content.DialogInterface; 9 | import android.os.Bundle; 10 | import android.support.annotation.Nullable; 11 | import android.widget.DatePicker; 12 | 13 | import com.facebook.react.bridge.Promise; 14 | import com.facebook.react.bridge.ReactApplicationContext; 15 | import com.facebook.react.bridge.ReactContextBaseJavaModule; 16 | import com.facebook.react.bridge.ReactMethod; 17 | import com.facebook.react.bridge.ReadableArray; 18 | import com.facebook.react.bridge.ReadableMap; 19 | import com.facebook.react.bridge.ReadableType; 20 | import com.facebook.react.bridge.WritableMap; 21 | import com.facebook.react.bridge.WritableNativeMap; 22 | import com.github.msarhan.ummalqura.calendar.UmmalquraCalendar; 23 | 24 | import java.util.ArrayList; 25 | import java.util.Calendar; 26 | import java.util.HashMap; 27 | import java.util.Map; 28 | import java.util.regex.PatternSyntaxException; 29 | 30 | public class HijriDatePickerAndroidModule extends ReactContextBaseJavaModule { 31 | private static final String REACT_CLASS = "HijriDatePickerAndroid"; 32 | 33 | public static final String ERROR_NO_ACTIVITY = "E_NO_ACTIVITY"; 34 | public static final String ERROR_OPEN = "E_OPEN"; 35 | public static final String ERROR_PARSING_OPTIONS = "E_PARSING_OPTIONS"; 36 | private static final String ERROR_CONVERT = "E_CONVERT"; 37 | 38 | private static final String ACTION_DATE_SET = "dateSetAction"; 39 | private static final String ACTION_DISMISSED = "dismissedAction"; 40 | 41 | private static final String FRAGMENT_TAG = "DatePickerAndroid"; 42 | static final String ARG_DATE = "date"; 43 | static final String ARG_MINDATE = "minDate"; 44 | static final String ARG_MAXDATE = "maxDate"; 45 | static final String ARG_WEEK_DAY_LABELS = "weekDayLabels"; 46 | public static final String ARG_MODE = "mode"; 47 | 48 | 49 | public HijriDatePickerAndroidModule(final ReactApplicationContext reactContext) { 50 | super(reactContext); 51 | } 52 | 53 | @Override 54 | public String getName() { 55 | return REACT_CLASS; 56 | } 57 | 58 | @Nullable 59 | @Override 60 | public Map getConstants() { 61 | Map constants = new HashMap<>(); 62 | constants.put(ACTION_DATE_SET, ACTION_DATE_SET); 63 | constants.put(ACTION_DISMISSED, ACTION_DISMISSED); 64 | constants.put(ERROR_NO_ACTIVITY, ERROR_NO_ACTIVITY); 65 | constants.put(ERROR_OPEN, ERROR_OPEN); 66 | constants.put(ERROR_CONVERT, ERROR_CONVERT); 67 | constants.put(ERROR_PARSING_OPTIONS, ERROR_PARSING_OPTIONS); 68 | return constants; 69 | } 70 | 71 | /** 72 | * Copyright (c) 2015-present, Facebook, Inc. 73 | * All rights reserved. 74 | *

75 | * This source code is licensed under the BSD-style license found in the 76 | * LICENSE file in the root directory of this source tree. An additional grant 77 | * of patent rights can be found in the PATENTS file in the same directory. 78 | * Show a date picker dialog. 79 | * 80 | * @param options a map containing options. Available keys are: 81 | *

82 | *

100 | * @param promise This will be invoked with parameters action, year, 101 | * month (0-11), day, where action is {@code dateSetAction} or 102 | * {@code dismissedAction}, depending on what the user did. If the action is 103 | * dismiss, year, month and date are undefined. 104 | */ 105 | @ReactMethod 106 | public void open(@Nullable final ReadableMap options, Promise promise) { 107 | try { 108 | Activity activity = getCurrentActivity(); 109 | if (activity == null) { 110 | promise.reject(ERROR_NO_ACTIVITY, "Tried to open a DatePicker dialog while not attached to an Activity"); 111 | return; 112 | } 113 | // We want to support both android.app.Activity and the pre-Honeycomb FragmentActivity 114 | // (for apps that use it for legacy reasons). This unfortunately leads to some code duplication. 115 | if (activity instanceof android.support.v4.app.FragmentActivity) { 116 | android.support.v4.app.FragmentManager fragmentManager = ((android.support.v4.app.FragmentActivity) activity).getSupportFragmentManager(); 117 | android.support.v4.app.DialogFragment oldFragment = (android.support.v4.app.DialogFragment) fragmentManager.findFragmentByTag(FRAGMENT_TAG); 118 | if (oldFragment != null) { 119 | oldFragment.dismiss(); 120 | } 121 | SupportHijriDatePickerDialogFragment fragment = new SupportHijriDatePickerDialogFragment(); 122 | if (options != null) { 123 | final Bundle args = createFragmentArguments(options, promise); 124 | if (args == null) 125 | return; 126 | fragment.setArguments(args); 127 | } 128 | final DatePickerDialogListener listener = new DatePickerDialogListener(promise); 129 | fragment.setOnDismissListener(listener); 130 | fragment.setOnDateSetListener(listener); 131 | fragment.setOnExceptionListener(listener); 132 | fragment.show(fragmentManager, FRAGMENT_TAG); 133 | } else { 134 | FragmentManager fragmentManager = activity.getFragmentManager(); 135 | DialogFragment oldFragment = (DialogFragment) fragmentManager.findFragmentByTag(FRAGMENT_TAG); 136 | if (oldFragment != null) { 137 | oldFragment.dismiss(); 138 | } 139 | HijriDatePickerDialogFragment fragment = new HijriDatePickerDialogFragment(); 140 | if (options != null) { 141 | final Bundle args = createFragmentArguments(options, promise); 142 | if (args == null) 143 | return; 144 | fragment.setArguments(args); 145 | } 146 | final DatePickerDialogListener listener = new DatePickerDialogListener(promise); 147 | fragment.setOnDismissListener(listener); 148 | fragment.setOnDateSetListener(listener); 149 | fragment.setOnExceptionListener(listener); 150 | fragment.show(fragmentManager, FRAGMENT_TAG); 151 | } 152 | } catch (Exception e) { 153 | promise.reject(ERROR_OPEN, "Exception happened while executing open method, details: " + e.getMessage()); 154 | } 155 | } 156 | 157 | private Bundle createFragmentArguments(ReadableMap options, Promise promise) { 158 | final Bundle args = new Bundle(); 159 | try { 160 | if (options.hasKey(ARG_DATE) && !options.isNull(ARG_DATE)) { 161 | if (!parseOptionsWithKey(ARG_DATE, options, args, promise)) 162 | return null; 163 | } 164 | if (options.hasKey(ARG_MINDATE) && !options.isNull(ARG_MINDATE)) { 165 | if (!parseOptionsWithKey(ARG_MINDATE, options, args, promise)) 166 | return null; 167 | } 168 | if (options.hasKey(ARG_MAXDATE) && !options.isNull(ARG_MAXDATE)) { 169 | if (!parseOptionsWithKey(ARG_MAXDATE, options, args, promise)) 170 | return null; 171 | } 172 | if (options.hasKey(ARG_MODE) && !options.isNull(ARG_MODE)) { 173 | args.putString(ARG_MODE, options.getString(ARG_MODE)); 174 | } 175 | if (options.hasKey(ARG_WEEK_DAY_LABELS) && !options.isNull(ARG_WEEK_DAY_LABELS)) { 176 | args.putStringArrayList(ARG_WEEK_DAY_LABELS, toStringArrayList(options.getArray(ARG_WEEK_DAY_LABELS))); 177 | } 178 | } catch (Exception e) { 179 | promise.reject(ERROR_PARSING_OPTIONS, "Exception happened while parsing options, details: " + e.getMessage()); 180 | return null; 181 | } 182 | return args; 183 | } 184 | 185 | private ArrayList toStringArrayList(ReadableArray readableArray) { 186 | ArrayList stringList = new ArrayList<>(); 187 | for (int i = 0; i < readableArray.size(); i++) { 188 | stringList.add(readableArray.getString(i)); 189 | } 190 | return stringList; 191 | } 192 | 193 | private boolean parseOptionsWithKey(String ARG_KEY, ReadableMap options, Bundle args, Promise promise) { 194 | ReadableType argDateType = options.getType(ARG_KEY); 195 | if (ReadableType.String.equals(argDateType)) { 196 | try { 197 | long milliSeconds = 0; 198 | milliSeconds = (long) convertHijriDateToGregorianMilliseconds(options.getString(ARG_KEY)); 199 | args.putLong(ARG_KEY, milliSeconds); 200 | return true; 201 | } catch (PatternSyntaxException | IndexOutOfBoundsException | NumberFormatException e) { 202 | promise.reject(ERROR_PARSING_OPTIONS, "Exception happened while parsing " + ARG_KEY + 203 | " we only accept object of Date or String with the format \"dd-MM-yyyy\" in Hijri"); 204 | return false; 205 | } 206 | } else if (ReadableType.Number.equals(argDateType)) { 207 | args.putLong(ARG_KEY, (long) options.getDouble(ARG_KEY)); 208 | return true; 209 | } else { 210 | promise.reject(ERROR_PARSING_OPTIONS, "Exception happened while parsing " + ARG_KEY + 211 | " we only accept object of Date or String with the format \"dd-MM-yyyy\" in Hijri"); 212 | return false; 213 | } 214 | } 215 | 216 | /** 217 | * @param hijriDate must be at the format dd-MM-yyyy 218 | * @return milliseconds of Gregorian equivalent to the given hijriDate 219 | */ 220 | public double convertHijriDateToGregorianMilliseconds(String hijriDate) { 221 | UmmalquraCalendar ummalquraCalendar = new UmmalquraCalendar(); 222 | 223 | int year = Integer.parseInt(hijriDate.split("-")[2]); 224 | int monthOfYear = Integer.parseInt(hijriDate.split("-")[1]); 225 | int dayOfMonth = Integer.parseInt(hijriDate.split("-")[0]); 226 | 227 | ummalquraCalendar.set(UmmalquraCalendar.YEAR, year); 228 | ummalquraCalendar.set(UmmalquraCalendar.MONTH, monthOfYear - 1); 229 | ummalquraCalendar.set(UmmalquraCalendar.DAY_OF_MONTH, dayOfMonth); 230 | 231 | return ummalquraCalendar.getTime().getTime(); 232 | } 233 | 234 | @ReactMethod 235 | public void convertHijriDateStrToGregorianMilliseconds(String hijriDate, Promise promise) { 236 | try { 237 | double milliseconds = convertHijriDateToGregorianMilliseconds(hijriDate); 238 | promise.resolve(milliseconds); 239 | } catch (Exception e) { 240 | promise.reject(ERROR_CONVERT, "Exception while executing convertHijriDateStrToGregorianMilliseconds, Details: " + e.getMessage()); 241 | 242 | } 243 | } 244 | 245 | /** 246 | * @param milliseconds your gregorian date in milliseconds 247 | * @return hijri date at the format of "dd-MM-yyyy" 248 | */ 249 | @ReactMethod 250 | public void convertMillisecondsToHijriDate(double milliseconds, Promise promise) { 251 | 252 | try { 253 | UmmalquraCalendar ummalquraCalendar = new UmmalquraCalendar(); 254 | ummalquraCalendar.setTimeInMillis((long) milliseconds); 255 | WritableMap result = new WritableNativeMap(); 256 | result.putInt("year", ummalquraCalendar.get(Calendar.YEAR)); 257 | result.putInt("month", ummalquraCalendar.get(Calendar.MONTH)); 258 | result.putInt("day", ummalquraCalendar.get(Calendar.DAY_OF_MONTH)); 259 | promise.resolve(result); 260 | } catch (Exception e) { 261 | promise.reject(ERROR_CONVERT, "Exception while executing convertMillisecondsToHijriDate, Details: " + e.getMessage()); 262 | } 263 | } 264 | 265 | 266 | public interface OnExceptionListener { 267 | void onException(String code, String message); 268 | } 269 | 270 | /** 271 | * Copyright (c) 2015-present, Facebook, Inc. 272 | * All rights reserved. 273 | *

274 | * This source code is licensed under the BSD-style license found in the 275 | * LICENSE file in the root directory of this source tree. An additional grant 276 | * of patent rights can be found in the PATENTS file in the same directory. 277 | */ 278 | private class DatePickerDialogListener implements DatePickerDialog.OnDateSetListener, DialogInterface.OnDismissListener, OnExceptionListener { 279 | 280 | private final Promise mPromise; 281 | private boolean mPromiseResolved = false; 282 | 283 | public DatePickerDialogListener(final Promise promise) { 284 | mPromise = promise; 285 | } 286 | 287 | @Override 288 | public void onDateSet(DatePicker ignored, int year, int month, int day) { 289 | if (!mPromiseResolved && getReactApplicationContext().hasActiveCatalystInstance()) { 290 | WritableMap result = new WritableNativeMap(); 291 | result.putString("action", ACTION_DATE_SET); 292 | result.putInt("year", year); 293 | result.putInt("month", month); 294 | result.putInt("day", day); 295 | mPromise.resolve(result); 296 | mPromiseResolved = true; 297 | } 298 | } 299 | 300 | @Override 301 | public void onDismiss(DialogInterface dialog) { 302 | if (!mPromiseResolved && getReactApplicationContext().hasActiveCatalystInstance()) { 303 | WritableMap result = new WritableNativeMap(); 304 | result.putString("action", ACTION_DISMISSED); 305 | mPromise.resolve(result); 306 | mPromiseResolved = true; 307 | } 308 | } 309 | 310 | @Override 311 | public void onException(String code, String message) { 312 | if (!mPromiseResolved && getReactApplicationContext().hasActiveCatalystInstance()) { 313 | mPromise.reject(code, message); 314 | mPromiseResolved = true; 315 | } 316 | } 317 | } 318 | } 319 | -------------------------------------------------------------------------------- /android/src/main/java/com/hijridatepicker/HijriDatePickerDialogFragment.java: -------------------------------------------------------------------------------- 1 | package com.hijridatepicker; 2 | 3 | import android.app.DatePickerDialog; 4 | import android.app.Dialog; 5 | import android.app.DialogFragment; 6 | import android.content.Context; 7 | import android.content.DialogInterface; 8 | import android.os.Bundle; 9 | import android.support.annotation.NonNull; 10 | import android.support.v4.content.ContextCompat; 11 | import android.view.LayoutInflater; 12 | import android.view.View; 13 | import android.view.ViewGroup; 14 | import android.widget.Button; 15 | 16 | import com.github.eltohamy.materialhijricalendarview.CalendarDay; 17 | import com.github.eltohamy.materialhijricalendarview.MaterialHijriCalendarView; 18 | import com.github.eltohamy.materialhijricalendarview.OnDateSelectedListener; 19 | import com.github.msarhan.ummalqura.calendar.UmmalquraCalendar; 20 | 21 | import java.util.ArrayList; 22 | import java.util.Arrays; 23 | import java.util.Calendar; 24 | import java.util.Locale; 25 | 26 | import javax.annotation.Nullable; 27 | 28 | /** 29 | * Created by Mohamed Habib on 16/10/2016. 30 | */ 31 | public class HijriDatePickerDialogFragment extends DialogFragment implements OnDateSelectedListener { 32 | 33 | @Nullable 34 | private DatePickerDialog.OnDateSetListener mOnDateSetListener; 35 | @Nullable 36 | private DialogInterface.OnDismissListener mOnDismissListener; 37 | @Nullable 38 | private HijriDatePickerAndroidModule.OnExceptionListener mOnExceptionListener; 39 | 40 | Button doneBtn; 41 | MaterialHijriCalendarView widget; 42 | int dayOfMonth; 43 | int monthOfYear; 44 | int year; 45 | 46 | Bundle args; 47 | 48 | @Override 49 | public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 50 | return inflater.inflate(R.layout.dialog_basic, container, false); 51 | } 52 | 53 | @Override 54 | public Dialog onCreateDialog(Bundle savedInstanceState) { 55 | args = getArguments(); 56 | return super.onCreateDialog(savedInstanceState); 57 | } 58 | 59 | @Override 60 | public void onViewCreated(View view, Bundle savedInstanceState) { 61 | super.onViewCreated(view, savedInstanceState); 62 | doneBtn = (Button) view.findViewById(R.id.done_button); 63 | widget = (MaterialHijriCalendarView) view.findViewById(R.id.calendarView); 64 | widget.setOnDateChangedListener(this); 65 | UmmalquraCalendar ummalquraCalendar = new UmmalquraCalendar(); 66 | dayOfMonth = ummalquraCalendar.get(Calendar.DAY_OF_MONTH); 67 | monthOfYear = ummalquraCalendar.get(Calendar.MONTH); 68 | year = ummalquraCalendar.get(Calendar.YEAR); 69 | customizeHijriCalendarView(getActivity(), widget, args, mOnExceptionListener); 70 | if (widget.getSelectedDate() != null) 71 | onDateSelected(widget, widget.getSelectedDate(), true); 72 | 73 | doneBtn.setOnClickListener(new View.OnClickListener() { 74 | @Override 75 | public void onClick(View v) { 76 | if (mOnDateSetListener != null) { 77 | mOnDateSetListener.onDateSet(null, year, monthOfYear, dayOfMonth); 78 | } 79 | dismiss(); 80 | } 81 | }); 82 | } 83 | 84 | public static void customizeHijriCalendarView(Context mContext, MaterialHijriCalendarView widget, Bundle args, HijriDatePickerAndroidModule.OnExceptionListener mOnExceptionListener) { 85 | 86 | UmmalquraCalendar ummalquraCalendar = new UmmalquraCalendar(); 87 | 88 | if (args != null && args.containsKey(HijriDatePickerAndroidModule.ARG_DATE)) { 89 | try { 90 | ummalquraCalendar.setTimeInMillis(args.getLong(HijriDatePickerAndroidModule.ARG_DATE)); 91 | widget.setDateSelected(ummalquraCalendar, true); 92 | } catch (Exception e) { 93 | mOnExceptionListener.onException(HijriDatePickerAndroidModule.ERROR_PARSING_OPTIONS, 94 | "Exception happened while parsing " + HijriDatePickerAndroidModule.ARG_DATE + ", details: " + e.getMessage()); 95 | widget.setSelectedDate(new UmmalquraCalendar()); 96 | } 97 | } else { 98 | widget.setSelectedDate(new UmmalquraCalendar()); 99 | } 100 | 101 | if (args != null && args.containsKey(HijriDatePickerAndroidModule.ARG_WEEK_DAY_LABELS)) { 102 | try { 103 | ArrayList stringArrayList = args.getStringArrayList(HijriDatePickerAndroidModule.ARG_WEEK_DAY_LABELS); 104 | if (stringArrayList != null) { 105 | String[] stringArray = Arrays.copyOf(stringArrayList.toArray(), stringArrayList.toArray().length, String[].class); 106 | widget.setWeekDayLabels(stringArray); 107 | } 108 | } catch (Exception e) { 109 | mOnExceptionListener.onException(HijriDatePickerAndroidModule.ERROR_PARSING_OPTIONS, 110 | "Exception happened while parsing " + HijriDatePickerAndroidModule.ARG_DATE + ", details: " + e.getMessage()); 111 | } 112 | } 113 | 114 | //TODO: customize the Dialog UI for more options 115 | HijriDatePickerMode mode = HijriDatePickerMode.DEFAULT; 116 | if (args != null && args.containsKey(HijriDatePickerAndroidModule.ARG_MODE) && args.getString(HijriDatePickerAndroidModule.ARG_MODE) != null) { 117 | try { 118 | mode = HijriDatePickerMode.valueOf(args.getString(HijriDatePickerAndroidModule.ARG_MODE).toUpperCase(Locale.US)); 119 | } catch (Exception e) { 120 | mOnExceptionListener.onException(HijriDatePickerAndroidModule.ERROR_PARSING_OPTIONS, 121 | "Exception happened while parsing " + HijriDatePickerAndroidModule.ARG_MODE + ", details: " + e.getMessage()); 122 | } 123 | } 124 | switch (mode) { 125 | case NO_ARROWS: 126 | widget.setLeftArrowMask(null); 127 | widget.setRightArrowMask(null); 128 | break; 129 | case DEFAULT: 130 | widget.setLeftArrowMask(ContextCompat.getDrawable(mContext, R.drawable.mcv_action_previous)); 131 | widget.setRightArrowMask(ContextCompat.getDrawable(mContext, R.drawable.mcv_action_next)); 132 | break; 133 | default: 134 | widget.setLeftArrowMask(ContextCompat.getDrawable(mContext, R.drawable.mcv_action_previous)); 135 | widget.setRightArrowMask(ContextCompat.getDrawable(mContext, R.drawable.mcv_action_next)); 136 | break; 137 | } 138 | 139 | if (args != null && args.containsKey(HijriDatePickerAndroidModule.ARG_MINDATE)) { 140 | try { 141 | ummalquraCalendar.setTimeInMillis(args.getLong(HijriDatePickerAndroidModule.ARG_MINDATE)); 142 | widget.setMinimumDate(ummalquraCalendar); 143 | } catch (Exception e) { 144 | mOnExceptionListener.onException(HijriDatePickerAndroidModule.ERROR_PARSING_OPTIONS, 145 | "Exception happened while parsing " + HijriDatePickerAndroidModule.ARG_MINDATE + ", details: " + e.getMessage()); 146 | } 147 | } 148 | 149 | if (args != null && args.containsKey(HijriDatePickerAndroidModule.ARG_MAXDATE)) { 150 | try { 151 | ummalquraCalendar.setTimeInMillis(args.getLong(HijriDatePickerAndroidModule.ARG_MAXDATE)); 152 | widget.setMaximumDate(ummalquraCalendar); 153 | } catch (Exception e) { 154 | mOnExceptionListener.onException(HijriDatePickerAndroidModule.ERROR_PARSING_OPTIONS, 155 | "Exception happened while parsing " + HijriDatePickerAndroidModule.ARG_MAXDATE + ", details: " + e.getMessage()); 156 | } 157 | } 158 | } 159 | 160 | @Override 161 | public void onDateSelected(@NonNull MaterialHijriCalendarView widget, @NonNull CalendarDay date, boolean selected) { 162 | dayOfMonth = date.getDay(); 163 | monthOfYear = date.getMonth(); 164 | year = date.getYear(); 165 | } 166 | 167 | @Override 168 | public void onDismiss(DialogInterface dialog) { 169 | super.onDismiss(dialog); 170 | if (mOnDismissListener != null) { 171 | mOnDismissListener.onDismiss(dialog); 172 | } 173 | } 174 | 175 | void setOnExceptionListener(@Nullable HijriDatePickerAndroidModule.OnExceptionListener onExceptionListener) { 176 | mOnExceptionListener = onExceptionListener; 177 | } 178 | 179 | void setOnDateSetListener(@Nullable DatePickerDialog.OnDateSetListener onDateSetListener) { 180 | mOnDateSetListener = onDateSetListener; 181 | } 182 | 183 | void setOnDismissListener(@Nullable DialogInterface.OnDismissListener onDismissListener) { 184 | mOnDismissListener = onDismissListener; 185 | } 186 | 187 | 188 | /** 189 | * Date picker modes 190 | */ 191 | public enum HijriDatePickerMode { 192 | DEFAULT, 193 | NO_ARROWS 194 | } 195 | 196 | 197 | } 198 | 199 | -------------------------------------------------------------------------------- /android/src/main/java/com/hijridatepicker/HijriDialogViewManagerPackage.java: -------------------------------------------------------------------------------- 1 | package com.hijridatepicker; 2 | 3 | 4 | import com.facebook.react.ReactPackage; 5 | import com.facebook.react.bridge.JavaScriptModule; 6 | import com.facebook.react.bridge.NativeModule; 7 | import com.facebook.react.bridge.ReactApplicationContext; 8 | import com.facebook.react.uimanager.ViewManager; 9 | 10 | import java.util.ArrayList; 11 | import java.util.Collections; 12 | import java.util.List; 13 | 14 | public class HijriDialogViewManagerPackage implements ReactPackage { 15 | 16 | @Override 17 | public List createNativeModules(ReactApplicationContext reactContext) { 18 | List nativeModules = new ArrayList<>(); 19 | nativeModules.add(new HijriDatePickerAndroidModule(reactContext)); 20 | return nativeModules; 21 | } 22 | 23 | @Override 24 | public List createViewManagers(ReactApplicationContext reactContext) { 25 | return Collections.emptyList(); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /android/src/main/java/com/hijridatepicker/SupportHijriDatePickerDialogFragment.java: -------------------------------------------------------------------------------- 1 | package com.hijridatepicker; 2 | 3 | import android.app.DatePickerDialog; 4 | import android.app.Dialog; 5 | import android.content.DialogInterface; 6 | import android.os.Bundle; 7 | import android.support.annotation.NonNull; 8 | import android.support.v4.app.DialogFragment; 9 | import android.view.LayoutInflater; 10 | import android.view.View; 11 | import android.view.ViewGroup; 12 | import android.widget.Button; 13 | 14 | import com.github.eltohamy.materialhijricalendarview.CalendarDay; 15 | import com.github.eltohamy.materialhijricalendarview.MaterialHijriCalendarView; 16 | import com.github.eltohamy.materialhijricalendarview.OnDateSelectedListener; 17 | 18 | import javax.annotation.Nullable; 19 | 20 | import static com.hijridatepicker.HijriDatePickerDialogFragment.customizeHijriCalendarView; 21 | 22 | /** 23 | * Created by Mohamed Habib on 16/10/2016. 24 | */ 25 | public class SupportHijriDatePickerDialogFragment extends DialogFragment implements OnDateSelectedListener { 26 | 27 | @Nullable 28 | private DatePickerDialog.OnDateSetListener mOnDateSetListener; 29 | @Nullable 30 | private DialogInterface.OnDismissListener mOnDismissListener; 31 | @Nullable 32 | private HijriDatePickerAndroidModule.OnExceptionListener mOnExceptionListener; 33 | 34 | Button doneBtn; 35 | MaterialHijriCalendarView widget; 36 | int dayOfMonth = 0; 37 | int monthOfYear = 0; 38 | int year = 0; 39 | 40 | Bundle args; 41 | 42 | @Override 43 | public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 44 | return inflater.inflate(R.layout.dialog_basic, container, false); 45 | } 46 | 47 | @Override 48 | public Dialog onCreateDialog(Bundle savedInstanceState) { 49 | args = getArguments(); 50 | return super.onCreateDialog(savedInstanceState); 51 | } 52 | 53 | @Override 54 | public void onViewCreated(View view, Bundle savedInstanceState) { 55 | super.onViewCreated(view, savedInstanceState); 56 | doneBtn = (Button) view.findViewById(R.id.done_button); 57 | widget = (MaterialHijriCalendarView) view.findViewById(R.id.calendarView); 58 | widget.setOnDateChangedListener(this); 59 | 60 | customizeHijriCalendarView(getActivity(), widget, args, mOnExceptionListener); 61 | onDateSelected(widget, widget.getSelectedDate(), true); 62 | 63 | doneBtn.setOnClickListener(new View.OnClickListener() { 64 | @Override 65 | public void onClick(View v) { 66 | if (mOnDateSetListener != null) { 67 | mOnDateSetListener.onDateSet(null, year, monthOfYear, dayOfMonth); 68 | } 69 | dismiss(); 70 | } 71 | }); 72 | } 73 | 74 | @Override 75 | public void onDateSelected(@NonNull MaterialHijriCalendarView widget, @NonNull CalendarDay date, boolean selected) { 76 | dayOfMonth = date.getDay(); 77 | monthOfYear = date.getMonth(); 78 | year = date.getYear(); 79 | } 80 | 81 | @Override 82 | public void onDismiss(DialogInterface dialog) { 83 | super.onDismiss(dialog); 84 | if (mOnDismissListener != null) { 85 | mOnDismissListener.onDismiss(dialog); 86 | } 87 | } 88 | 89 | void setOnDateSetListener(@Nullable DatePickerDialog.OnDateSetListener onDateSetListener) { 90 | mOnDateSetListener = onDateSetListener; 91 | } 92 | 93 | void setOnExceptionListener(@Nullable HijriDatePickerAndroidModule.OnExceptionListener onExceptionListener) { 94 | mOnExceptionListener = onExceptionListener; 95 | } 96 | 97 | void setOnDismissListener(@Nullable DialogInterface.OnDismissListener onDismissListener) { 98 | mOnDismissListener = onDismissListener; 99 | } 100 | } 101 | 102 | -------------------------------------------------------------------------------- /android/src/main/res/layout/dialog_basic.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 15 | 16 | 20 | 21 |