Browse Source

Merge pull request #148 from henninghall/Bugfix--iOS-13-text-color

Bugfix: Text color on iOS 13 not displayed properly
master
Henning Hall 5 years ago
committed by GitHub
parent
commit
ab6e77697b
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 87 additions and 44 deletions
  1. +39
    -40
      README.md
  2. +40
    -3
      ios/RNDatePicker/DatePicker.m
  3. +8
    -1
      propChecker.js

+ 39
- 40
README.md View File

@ -1,27 +1,22 @@
# React Native Date Picker [![npm](https://img.shields.io/npm/v/react-native-date-picker.svg)](https://www.npmjs.com/package/react-native-date-picker) [![Build status](https://img.shields.io/bitrise/288d828c2f6731e6/master.svg?token=mGBI2QhCJBx18ffiS-MfpA&label=build)](https://app.bitrise.io/app/288d828c2f6731e6#/builds) [![npm](https://img.shields.io/npm/dm/react-native-date-picker.svg)](https://www.npmjs.com/package/react-native-date-picker)
# React Native Date Picker [![npm](https://img.shields.io/npm/v/react-native-date-picker.svg)](https://www.npmjs.com/package/react-native-date-picker) [![Build status](https://img.shields.io/bitrise/288d828c2f6731e6/master.svg?token=mGBI2QhCJBx18ffiS-MfpA&label=build)](https://app.bitrise.io/app/288d828c2f6731e6#/builds) [![npm](https://img.shields.io/npm/dm/react-native-date-picker.svg)](https://www.npmjs.com/package/react-native-date-picker)
<!-- <!--
[![Foo](https://7pjewxutn7.execute-api.us-east-1.amazonaws.com/default/date-picker-badge)](https://app.bitrise.io/app/288d828c2f6731e6#/builds)
[![Foo](https://7pjewxutn7.execute-api.us-east-1.amazonaws.com/default/date-picker-badge)](https://app.bitrise.io/app/288d828c2f6731e6#/builds)
[![Foo](https://app.bitrise.io/app/288d828c2f6731e6/status.svg?token=mGBI2QhCJBx18ffiS-MfpA&branch=master)](https://app.bitrise.io/app/288d828c2f6731e6#/builds)
[![Foo](https://app.bitrise.io/app/288d828c2f6731e6/status.svg?token=mGBI2QhCJBx18ffiS-MfpA&branch=master)](https://app.bitrise.io/app/288d828c2f6731e6#/builds)
--> -->
This is a React Native Date Picker with following main features:
This is a React Native Date Picker with following main features:
📱 Supporting iOS and Android <br> 📱 Supporting iOS and Android <br>
🕑 3 different modes: Time, Date, DateTime <br> 🕑 3 different modes: Time, Date, DateTime <br>
🌍 Multiple languages<br> 🌍 Multiple languages<br>
🎨 Customizable<br> 🎨 Customizable<br>
<!--
<!--
[![Monthly download](https://img.shields.io/npm/dm/react-native-date-picker.svg)](https://img.shields.io/npm/dm/react-native-date-picker.svg) [![Monthly download](https://img.shields.io/npm/dm/react-native-date-picker.svg)](https://img.shields.io/npm/dm/react-native-date-picker.svg)
[![Total downloads](https://img.shields.io/npm/dt/react-native-date-picker.svg)](https://img.shields.io/npm/dt/react-native-date- picker.svg) --> [![Total downloads](https://img.shields.io/npm/dt/react-native-date-picker.svg)](https://img.shields.io/npm/dt/react-native-date- picker.svg) -->
<table> <table>
<tr> <tr>
<td align="center"><b>iOS</b></td> <td align="center"><b>iOS</b></td>
@ -45,73 +40,78 @@ This is a React Native Date Picker with following main features:
1. `npm install react-native-date-picker --save` 1. `npm install react-native-date-picker --save`
2. `react-native link react-native-date-picker` (Only needed for React Native <= 0.59) 2. `react-native link react-native-date-picker` (Only needed for React Native <= 0.59)
## Minimal Example ## Minimal Example
```js ```js
import React, { Component } from 'react';
import DatePicker from 'react-native-date-picker';
import React, { Component } from 'react'
import DatePicker from 'react-native-date-picker'
export default class App extends Component { export default class App extends Component {
state = { date: new Date() } state = { date: new Date() }
render = () =>
render = () => (
<DatePicker <DatePicker
date={this.state.date} date={this.state.date}
onDateChange={date => this.setState({ date })} onDateChange={date => this.setState({ date })}
/> />
)
} }
``` ```
## Properties ## Properties
Prop | Description | Screenshots iOS | Screenshot Android
------------- | ------------- | ------------- | -------------
date | The currently selected date. |
onDateChange | Date change handler |
fadeToColor | Android picker is fading towards this background color. {color, 'none'} |
maximumDate | Maximum selectable date. |
minimumDate | Minimum selectable date |
minuteInterval | The interval at which minutes can be selected. | <img src="docs/minute-interval-ios.png" alt="Date picker minute interval IOS" height="120px" />|<img src="docs/minute-interval-android.png" alt="Date picker minute interval Android" height="120px" />
mode | The date picker mode. {'datetime', 'date', 'time'} | <img src="docs/datetime-mode-ios.png" alt="Datepicker datetime mode ios" height="120px" /><img src="docs/date-mode-ios.png" alt="date mode ios" height="120px" /><img src="docs/time-mode-ios.png" alt="time mode ios" height="120px" />|<img src="docs/datetime-mode-android.png" alt="react native datetime mode android" height="120px" /><img src="docs/date-mode-android.png" alt="date mode android" height="120px" /><img src="docs/time-mode-android.png" alt="time mode android" height="120px" /> |
locale | The locale for the date picker. Changes language, date order and am/pm preferences. Value needs to be a <a title="react native datepicker locale id" href="https://developer.apple.com/library/content/documentation/MacOSX/Conceptual/BPInternational/LanguageandLocaleIDs/LanguageandLocaleIDs.html">Locale ID.</a>| <img src="docs/locale-ios.png" alt="React Native Date picker locale language ios" height="120px" />|<img src="docs/locale-android.png" alt="React Native Date picker locale language android" height="120px" />
textColor | Changes the text color. | <img src="docs/colors-ios.png" alt="react native datepicker text color background color ios" height="120px" />|<img src="docs/colors-android.png" alt="Text color background color android" height="120px" />
timeZoneOffsetInMinutes | Timezone offset in minutes (default: device's timezone)
| Prop | Description | Screenshots iOS | Screenshot Android |
| ----------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| date | The currently selected date. |
| onDateChange | Date change handler |
| fadeToColor | Android picker is fading towards this background color. {color, 'none'} |
| maximumDate | Maximum selectable date. |
| minimumDate | Minimum selectable date |
| minuteInterval | The interval at which minutes can be selected. | <img src="docs/minute-interval-ios.png" alt="Date picker minute interval IOS" height="120px" /> | <img src="docs/minute-interval-android.png" alt="Date picker minute interval Android" height="120px" /> |
| mode | The date picker mode. {'datetime', 'date', 'time'} | <img src="docs/datetime-mode-ios.png" alt="Datepicker datetime mode ios" height="120px" /><img src="docs/date-mode-ios.png" alt="date mode ios" height="120px" /><img src="docs/time-mode-ios.png" alt="time mode ios" height="120px" /> | <img src="docs/datetime-mode-android.png" alt="react native datetime mode android" height="120px" /><img src="docs/date-mode-android.png" alt="date mode android" height="120px" /><img src="docs/time-mode-android.png" alt="time mode android" height="120px" /> |
| locale | The locale for the date picker. Changes language, date order and am/pm preferences. Value needs to be a <a title="react native datepicker locale id" href="https://developer.apple.com/library/content/documentation/MacOSX/Conceptual/BPInternational/LanguageandLocaleIDs/LanguageandLocaleIDs.html">Locale ID.</a> | <img src="docs/locale-ios.png" alt="React Native Date picker locale language ios" height="120px" /> | <img src="docs/locale-android.png" alt="React Native Date picker locale language android" height="120px" /> |
| textColor | Changes the text color. ⚠ Colors other than black (#000000) or white (#ffffff) will replace the "Today" string with a date on iOS 13. | <img src="docs/colors-ios.png" alt="react native datepicker text color background color ios" height="120px" /> | <img src="docs/colors-android.png" alt="Text color background color android" height="120px" /> |
| timeZoneOffsetInMinutes | Timezone offset in minutes (default: device's timezone) |
## About ## About
📅 &nbsp; React Native Date Picker is a cross platform component working on both iOS and Android. It uses the slightly improved DatePickerIOS on iOS and a custom picker on Android which has similar look and feel. The datetime mode might be particulary interesting if you looking for a way to avoid two different popup pickers on android.
📅 &nbsp; React Native Date Picker is a cross platform component working on both iOS and Android. It uses the slightly improved DatePickerIOS on iOS and a custom picker on Android which has similar look and feel. The datetime mode might be particulary interesting if you looking for a way to avoid two different popup pickers on android.
## FAQ ## FAQ
### Can I use expo? ### Can I use expo?
Unfortunately, expo does not support this date picker at the moment. Upvote <a href="https://expo.canny.io/feature-requests/p/support-react-native-date-picker">this feature request</a> if you would like to have it included.
Unfortunately, expo does not support this date picker at the moment. Upvote <a href="https://expo.canny.io/feature-requests/p/support-react-native-date-picker">this feature request</a> if you would like to have it included.
### How do i change the date order? (To YYYY-MM-DD etc) ### How do i change the date order? (To YYYY-MM-DD etc)
The order is determined by the `locale` prop. Set for instance `locale='fr'`to get the France preference. The order is determined by the `locale` prop. Set for instance `locale='fr'`to get the France preference.
### How do i change the 12/24h or AM/PM format? ### How do i change the 12/24h or AM/PM format?
On iOS the 12/24h preference is determined by the `locale` prop. Set for instance `locale='fr'`to get the France preference. On Android the 12/24h format is determined by the device setting. When using 12h mode the AM/PM part of the picker will be displayed.
On iOS the 12/24h preference is determined by the `locale` prop. Set for instance `locale='fr'`to get the France preference. On Android the 12/24h format is determined by the device setting. When using 12h mode the AM/PM part of the picker will be displayed.
### Is it possible to show only month and year? ### Is it possible to show only month and year?
This is unfortunately not possible due to the limitation in DatePickerIOS. You should be able to create your own month-year picker with for instance https://github.com/TronNatthakorn/react-native-wheel-pick. This is unfortunately not possible due to the limitation in DatePickerIOS. You should be able to create your own month-year picker with for instance https://github.com/TronNatthakorn/react-native-wheel-pick.
### Why does the Android app crash in production? ### Why does the Android app crash in production?
If you have enabled <a href="https://facebook.github.io/react-native/docs/signed-apk-android#enabling-proguard-to-reduce-the-size-of-the-apk-optional">Proguard</a> for Android you might need to ignore some classes to get the the picker to work propery in android production/release mode. Add these lines to you proguard file (often called `proguard-rules.pro`):
If you have enabled <a href="https://facebook.github.io/react-native/docs/signed-apk-android#enabling-proguard-to-reduce-the-size-of-the-apk-optional">Proguard</a> for Android you might need to ignore some classes to get the the picker to work propery in android production/release mode. Add these lines to you proguard file (often called `proguard-rules.pro`):
``` ```
-keep public class net.time4j.android.ApplicationStarter -keep public class net.time4j.android.ApplicationStarter
-keep public class net.time4j.PrettyTime -keep public class net.time4j.PrettyTime
``` ```
## Roadmap ## Roadmap
- [x] Mode: datetime - [x] Mode: datetime
- [x] Mode: date - [x] Mode: date
- [x] Mode: time - [x] Mode: time
- [x] Locale support. (AM/PM, 12h/24h toggled and strings translated)
- [x] Locale support. (AM/PM, 12h/24h toggled and strings translated)
- [x] Replace todays date with the string "Today" (considering locale) - [x] Replace todays date with the string "Today" (considering locale)
- [x] Animate to date when state change occur.
- [x] Animate to date when state change occur.
- [x] Switch between AM/PM when scrolling between forenoon and afternoon. - [x] Switch between AM/PM when scrolling between forenoon and afternoon.
- [x] Support maximumDate/minimumDate. - [x] Support maximumDate/minimumDate.
- [x] Minute interval prop. - [x] Minute interval prop.
@ -119,16 +119,15 @@ If you have enabled - [x] Colored text support. - [x] Colored text support.
## Why another React Native date picker? ## Why another React Native date picker?
One of the strongest reason to use react native is its cross platform compatibility. Most of the official components are working seamlessly on both platforms but there are some with single platform support only. The react native datepicker is one example where both <a href="https://facebook.github.io/react-native/docs/datepickerios">DatePickerIOS</a> and <a href="https://facebook.github.io/react-native/docs/datepickerandroid">DatePickerAndroid</a> are present. The reason for this is that the default date picker is implemented in seperate ways, iOS normally have an integrated view picker wheel where android has different pickers in a dialog format.
If you want to use these pickers you can combile the official ones or a third party module that already done that for you. If you on the other hand want have a more unified design between your android and ios app, this module is for you. The datetime mode can be particularly helpful to avoid 2 separate picker dialogs on android.
One of the strongest reason to use react native is its cross platform compatibility. Most of the official components are working seamlessly on both platforms but there are some with single platform support only. The react native datepicker is one example where both <a href="https://facebook.github.io/react-native/docs/datepickerios">DatePickerIOS</a> and <a href="https://facebook.github.io/react-native/docs/datepickerandroid">DatePickerAndroid</a> are present. The reason for this is that the default date picker is implemented in seperate ways, iOS normally have an integrated view picker wheel where android has different pickers in a dialog format.
If you want to use these pickers you can combile the official ones or a third party module that already done that for you. If you on the other hand want have a more unified design between your android and ios app, this module is for you. The datetime mode can be particularly helpful to avoid 2 separate picker dialogs on android.
<!-- <!--
## TODO EXTRA ## TODO EXTRA
- [ ] Transparent background support. (Probably need to include transparent gradient). - [ ] Transparent background support. (Probably need to include transparent gradient).
- [ ] Screen recordings - [ ] Screen recordings
- [ ] Gray out max/min values.
- [ ] Gray out max/min values.
- [ ] Align text to right. - [ ] Align text to right.
--> -->

+ 40
- 3
ios/RNDatePicker/DatePicker.m View File

@ -50,22 +50,59 @@
if ((self = [super initWithFrame:frame])) { if ((self = [super initWithFrame:frame])) {
[self addTarget:self action:@selector(didChange) [self addTarget:self action:@selector(didChange)
forControlEvents:UIControlEventValueChanged]; forControlEvents:UIControlEventValueChanged];
if(@available(iOS 13, *)) {
self.overrideUserInterfaceStyle = UIUserInterfaceStyleLight;
}
} }
return self; return self;
} }
- (void)setTextColorProp:(NSString *)hexColor
{
- (void)setColor:(NSString *)hexColor {
// Hex to int color // Hex to int color
unsigned intColor = 0; unsigned intColor = 0;
NSScanner *scanner = [NSScanner scannerWithString:hexColor]; NSScanner *scanner = [NSScanner scannerWithString:hexColor];
[scanner setScanLocation:1]; // bypass '#' character [scanner setScanLocation:1]; // bypass '#' character
[scanner scanHexInt:&intColor]; [scanner scanHexInt:&intColor];
// Setting picker text color // Setting picker text color
[self setValue:UIColorFromRGB(intColor) forKeyPath:@"textColor"]; [self setValue:UIColorFromRGB(intColor) forKeyPath:@"textColor"];
} }
- (void)removeTodayString {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wundeclared-selector"
[self performSelector:@selector(setHighlightsToday:) withObject:[NSNumber numberWithBool:NO]];
#pragma clang diagnostic pop
}
- (void)setTextColorProp:(NSString *)hexColor
{
if(@available(iOS 13, *)) {
// black text -> set light mode
if([hexColor isEqualToString:@"#000000"]){
self.overrideUserInterfaceStyle = UIUserInterfaceStyleLight;
}
// white text -> set dark mode
else if([hexColor isEqualToString:@"#FFFFFF"] || [hexColor isEqualToString:@"#ffffff"]){
self.overrideUserInterfaceStyle = UIUserInterfaceStyleDark;
}
// other colors -> remove "Today" string since it cannot be colored from iOS 13.
else {
[self removeTodayString];
[self setColor:hexColor];
}
}
// if ios 12 and earlier -> no need to remove today string since it can be colored.
else {
[self setColor:hexColor];
}
}
RCT_NOT_IMPLEMENTED(- (instancetype)initWithCoder:(NSCoder *)aDecoder) RCT_NOT_IMPLEMENTED(- (instancetype)initWithCoder:(NSCoder *)aDecoder)

+ 8
- 1
propChecker.js View File

@ -40,4 +40,11 @@ const modeCheck = new PropCheck(
"Invalid mode. Valid modes: 'datetime', 'date', 'time'" "Invalid mode. Valid modes: 'datetime', 'date', 'time'"
) )
const checks = [widthCheck, heightCheck, modeCheck]
const colorCheck = new PropCheck(
props =>
props && props.textColor && !props.textColor.startsWith("#"),
"Invalid text color. Must be a hex string."
)
const checks = [widthCheck, heightCheck, modeCheck, colorCheck]

Loading…
Cancel
Save