Support tintColor and thumbTintColor for Switch on Android

Summary:
**Motivation**

`Switch` on Android doesn't allow changing the colors unlike iOS. Changing the colors is desirable in a lot of cases to match the brand colors.

The PR adds support for the `tintColor`, `onTintColor` and `thumbTintColor` props on Android, which more or less behave the same as iOS. The only difference is `tintColor` styles the border color on iOS, whereas it styles the background color on Android.

**Test plan (required)**

Run UIExplorer with the changes, and ensure that the switch example works properly. Here are screenshots from iOS and Android to compare.

![image](https://cloud.githubusercontent.com/assets/1174278/22018002/b05d6482-dcd2-11e6-9c00-f55a71d6ce29.png)

![image](https://cloud.githubusercontent.com/assets/1174278/22018012/b923e974-dcd2-11e6-8d4e-86994f5a66e6.png)

cc brentvatne
Closes https://github.com/facebook/react-native/pull/11940

Differential Revision: D4427491

fbshipit-source-id: 16c569d2e2261daaea93fffa83198f8f6b59a6c8
This commit is contained in:
Satyajit Sahoo 2017-01-31 13:33:38 -08:00 коммит произвёл Facebook Github Bot
Родитель 1beb6274b8
Коммит 31099aa233
3 изменённых файлов: 40 добавлений и 17 удалений

Просмотреть файл

@ -147,15 +147,12 @@ var examples = [
{ {
title: 'Switches are controlled components', title: 'Switches are controlled components',
render(): React.Element<any> { return <Switch />; } render(): React.Element<any> { return <Switch />; }
} },
]; {
if (Platform.OS === 'ios') {
examples.push({
title: 'Custom colors can be provided', title: 'Custom colors can be provided',
render(): React.Element<any> { return <ColorSwitchExample />; } render(): React.Element<any> { return <ColorSwitchExample />; }
});
} }
];
exports.title = '<Switch>'; exports.title = '<Switch>';
exports.displayName = 'SwitchExample'; exports.displayName = 'SwitchExample';

Просмотреть файл

@ -20,6 +20,8 @@ var View = require('View');
var requireNativeComponent = require('requireNativeComponent'); var requireNativeComponent = require('requireNativeComponent');
var { PropTypes } = React;
type DefaultProps = { type DefaultProps = {
value: boolean, value: boolean,
disabled: boolean, disabled: boolean,
@ -43,34 +45,31 @@ var Switch = React.createClass({
* The value of the switch. If true the switch will be turned on. * The value of the switch. If true the switch will be turned on.
* Default value is false. * Default value is false.
*/ */
value: React.PropTypes.bool, value: PropTypes.bool,
/** /**
* If true the user won't be able to toggle the switch. * If true the user won't be able to toggle the switch.
* Default value is false. * Default value is false.
*/ */
disabled: React.PropTypes.bool, disabled: PropTypes.bool,
/** /**
* Invoked with the new value when the value changes. * Invoked with the new value when the value changes.
*/ */
onValueChange: React.PropTypes.func, onValueChange: PropTypes.func,
/** /**
* Used to locate this view in end-to-end tests. * Used to locate this view in end-to-end tests.
*/ */
testID: React.PropTypes.string, testID: PropTypes.string,
/** /**
* Border color when the switch is turned off. * Border color on iOS and background color on Android when the switch is turned off.
* @platform ios
*/ */
tintColor: ColorPropType, tintColor: ColorPropType,
/** /**
* Background color when the switch is turned on. * Background color when the switch is turned on.
* @platform ios
*/ */
onTintColor: ColorPropType, onTintColor: ColorPropType,
/** /**
* Color of the foreground switch grip. * Color of the foreground switch grip.
* @platform ios
*/ */
thumbTintColor: ColorPropType, thumbTintColor: ColorPropType,
}, },
@ -104,6 +103,7 @@ var Switch = React.createClass({
props.enabled = !this.props.disabled; props.enabled = !this.props.disabled;
props.on = this.props.value; props.on = this.props.value;
props.style = this.props.style; props.style = this.props.style;
props.trackTintColor = this.props.value ? this.props.onTintColor : this.props.tintColor;
} else if (Platform.OS === 'ios') { } else if (Platform.OS === 'ios') {
props.style = [styles.rctSwitchIOS, this.props.style]; props.style = [styles.rctSwitchIOS, this.props.style];
} }
@ -126,11 +126,18 @@ var styles = StyleSheet.create({
if (Platform.OS === 'android') { if (Platform.OS === 'android') {
var RCTSwitch = requireNativeComponent('AndroidSwitch', Switch, { var RCTSwitch = requireNativeComponent('AndroidSwitch', Switch, {
nativeOnly: { onChange: true, on: true, enabled: true } nativeOnly: {
onChange: true,
on: true,
enabled: true,
trackTintColor: true,
}
}); });
} else { } else {
var RCTSwitch = requireNativeComponent('RCTSwitch', Switch, { var RCTSwitch = requireNativeComponent('RCTSwitch', Switch, {
nativeOnly: { onChange: true } nativeOnly: {
onChange: true
}
}); });
} }

Просмотреть файл

@ -10,6 +10,7 @@
// switchview because switch is a keyword // switchview because switch is a keyword
package com.facebook.react.views.switchview; package com.facebook.react.views.switchview;
import android.graphics.PorterDuff;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.CompoundButton; import android.widget.CompoundButton;
@ -117,6 +118,24 @@ public class ReactSwitchManager extends SimpleViewManager<ReactSwitch> {
view.setOnCheckedChangeListener(ON_CHECKED_CHANGE_LISTENER); view.setOnCheckedChangeListener(ON_CHECKED_CHANGE_LISTENER);
} }
@ReactProp(name = "thumbTintColor", customType = "Color")
public void setThumbTintColor(ReactSwitch view, Integer color) {
if (color == null) {
view.getThumbDrawable().clearColorFilter();
} else {
view.getThumbDrawable().setColorFilter(color, PorterDuff.Mode.MULTIPLY);
}
}
@ReactProp(name = "trackTintColor", customType = "Color")
public void setTrackTintColor(ReactSwitch view, Integer color) {
if (color == null) {
view.getTrackDrawable().clearColorFilter();
} else {
view.getTrackDrawable().setColorFilter(color, PorterDuff.Mode.MULTIPLY);
}
}
@Override @Override
protected void addEventEmitters(final ThemedReactContext reactContext, final ReactSwitch view) { protected void addEventEmitters(final ThemedReactContext reactContext, final ReactSwitch view) {
view.setOnCheckedChangeListener(ON_CHECKED_CHANGE_LISTENER); view.setOnCheckedChangeListener(ON_CHECKED_CHANGE_LISTENER);