Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: create expo plugin to customize native style #801

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

brunohkbx
Copy link

@brunohkbx brunohkbx commented Aug 10, 2023

Summary

This PR is a proposal to implement an expo plugin to be able to customize both Android native components DatePickerDialog and TimePickerDialog.

Resolves #20

References
https://www.tutorialsbuzz.com/2019/09/android-datepicker-dialog-styling-kotlin.html
https://www.tutorialsbuzz.com/2019/09/android-timepicker-dialog-styling.html

Test Plan

DatePickerDialog TimePickerDialog
Screenshot from 2023-08-10 02-48-29 Screenshot from 2023-08-09 23-10-30

styles.xml

Entries added in the style <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">

<item name="android:datePickerDialogTheme">@style/DatePickerDialogTheme</item>
<item name="android:timePickerStyle">@style/TimePickerTheme</item>

New style entries added

<style name="DatePickerDialogTheme" parent="Theme.AppCompat.Light.Dialog">
  <item name="colorAccent">@color/datePicker_colorAccent</item>
  <item name="colorControlActivated">@color/datePicker_colorControlActivated</item>
  <item name="colorControlHighlight">@color/datePicker_colorControlHighlight</item>
  <item name="android:textColor">@color/datePicker_textColor</item>
  <item name="android:textColorPrimary">@color/datePicker_textColorPrimary</item>
  <item name="android:textColorSecondary">@color/datePicker_textColorSecondary</item>
  <item name="android:windowBackground">@color/datePicker_windowBackground</item>
</style>

<style name="TimePickerTheme" parent="android:Widget.Material.Light.TimePicker">
  <item name="android:background">@color/timePicker_background</item>
</style>

colors.xml

<resources>
  <color name="datePicker_colorAccent">...</color>
  <color name="datePicker_colorControlActivated">...</color>
  <color name="datePicker_colorControlHighlight">...</color>
  <color name="datePicker_textColor">...</color>
  <color name="datePicker_textColorPrimary">...</color>
  <color name="datePicker_textColorSecondary">...</color>
  <color name="datePicker_windowBackground">...</color>
  <color name="timePicker_background">...</color>
</resources>

values-night/colors.xml

<resources>
  <color name="datePicker_colorAccent">...</color>
  <color name="datePicker_colorControlActivated">...</color>
  <color name="datePicker_colorControlHighlight">...</color>
  <color name="datePicker_textColor">...</color>
  <color name="datePicker_textColorPrimary">...</color>
  <color name="datePicker_textColorSecondary">...</color>
  <color name="datePicker_windowBackground">...</color>
  <color name="timePicker_background">...</color>
</resources>

What's required for testing (prerequisites)?

  1. First of, set up a new expo project with expo init
  2. Install this library with expo install @react-native-community/datetimepicker
  3. Configure the new plugin in app.json/app.config.js as described in the new documentation

What are the steps to reproduce (after prerequisites)?

You should see the new styles applied to either a RNDateTimePicker with mode="date" or mode="time"

Compatibility

OS Implemented
iOS
Android

Checklist

  • I have tested this on a device and a simulator
  • I added the documentation in README.md
  • I updated the typed files (TS and Flow)
  • I added a sample use of the API in the example project (example/App.js)
  • I have added automated tests, either in JS or e2e tests, as applicable

colorAccent: {attrName: 'colorAccent', colorName: 'datePicker_colorAccent'},
colorControlActivated: {
attrName: 'colorControlActivated',
colorName: 'datePicker_colorControlActivated',
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure if this is a good idea, but I added the prefix datePicker_ and timePicker_ for the new colors to avoid polluting the global scope just in case.

}
```

Due to a limitation in the way the plugin system works, works, it's not possible to write a custom styles.xml for the values-night, so when customizing a specific property, you must declare a value for both the `light` and `dark` themes. If you don't, the plugin will not work and the following error will be thrown:
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Due to a limitation in the way the plugin system works, works, it's not possible to write a custom styles.xml for the values-night, so when customizing a specific property, you must declare a value for both the `light` and `dark` themes. If you don't, the plugin will not work and the following error will be thrown:
Due to a limitation in the way the plugin system works, it's not possible to write a custom styles.xml for the values-night, so when customizing a specific property, you must declare a value for both the `light` and `dark` themes. If you don't, the plugin will not work and the following error will be thrown:

Comment on lines +180 to +236
const setAndroidDatePickerStyles = (
styles: ResourceXML,
{light, dark}: DatePickerTheme,
): ResourceXML => {
styles = Object.keys({...light, ...dark}).reduce((acc, attr) => {
const {attrName, colorName} =
DATE_PICKER_ALLOWED_ATTRIBUTES[attr as keyof DatePickerProps];

return assignStylesValue(acc, {
add: true,
parent: {
name: DATE_PICKER_STYLE_NAME,
parent: 'Theme.AppCompat.Light.Dialog',
},
name: attrName,
value: `@color/${colorName}`,
});
}, styles);

styles = assignStylesValue(styles, {
add: true,
parent: getAppThemeLightNoActionBarGroup(),
name: DATE_PICKER_THEME_ATTRIBUTE,
value: `@style/${DATE_PICKER_STYLE_NAME}`,
});

return styles;
};

const setAndroidTimePickerStyles = (
styles: ResourceXML,
{light, dark}: TimePickerTheme,
): ResourceXML => {
styles = Object.keys({...light, ...dark}).reduce((acc, attr) => {
const {attrName, colorName} =
TIME_PICKER_ALLOWED_ATTRIBUTES[attr as keyof TimePickerProps];

return assignStylesValue(acc, {
add: true,
parent: {
name: TIME_PICKER_STYLE_NAME,
parent: 'android:Widget.Material.Light.TimePicker',
},
name: attrName,
value: `@color/${colorName}`,
});
}, styles);

styles = assignStylesValue(styles, {
add: true,
parent: getAppThemeLightNoActionBarGroup(),
name: TIME_PICKER_THEME_ATTRIBUTE,
value: `@style/${TIME_PICKER_STYLE_NAME}`,
});

return styles;
};
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we have a generic method to dedupe these two functions? They're doing the same thing with different arguments.

@Haukez
Copy link

Haukez commented Nov 28, 2023

I guess we'll have to wait until like 2025.

@mribbons
Copy link

@brunohkbx anything we can do to help move this forward?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Please add props to change theme color of the picker.
4 participants