From da8a94836b84b9053620087d7f340a14b7e741d2 Mon Sep 17 00:00:00 2001 From: Maarten van Dillen <> Date: Mon, 6 Apr 2020 14:26:29 +0200 Subject: [PATCH 1/7] inactiveIndicator --- scrollview-switch.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scrollview-switch.js b/scrollview-switch.js index 6ec0403..1872b9f 100644 --- a/scrollview-switch.js +++ b/scrollview-switch.js @@ -76,7 +76,7 @@ class ToggleSwitch extends React.Component { render() { const { text: { on = 'ON', off = 'OFF', activeTextColor, inactiveTextColor }, - color: { active, inactive, indicator, activeBorder, inactiveBorder }, + color: { active, inactive, indicator, inactiveIndicator, activeBorder, inactiveBorder }, textStyle = {}, disabled = false } = this.props; @@ -153,7 +153,7 @@ class ToggleSwitch extends React.Component { Date: Mon, 6 Apr 2020 14:48:44 +0200 Subject: [PATCH 2/7] added padding prop --- scrollview-switch.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scrollview-switch.js b/scrollview-switch.js index 1872b9f..7b59c9d 100644 --- a/scrollview-switch.js +++ b/scrollview-switch.js @@ -16,7 +16,7 @@ class ToggleSwitch extends React.Component { isActive: this.props.active || false }; this.borderWidth = 2; - this.universalPadding = 2; + this.universalPadding = this.props.padding || 2; this.viewPortRadius = this.props.radius + this.universalPadding; this.textMargin = 8; this.viewPortWidth = this.props.width + (2 * this.props.radius) + (2 * this.universalPadding) + this.textMargin; @@ -115,7 +115,7 @@ class ToggleSwitch extends React.Component { { opacity: 1, backgroundColor: isActive? active: inactive, - height: this.props.radius * 2 + this.universalPadding * 2 + height: this.props.radius * 2 + this.universalPadding * 2 } ]} > From afcd559b608f098157bfc0d8ed27adfb4a9f4bfb Mon Sep 17 00:00:00 2001 From: Maarten van Dillen <> Date: Tue, 7 Apr 2020 15:17:01 +0200 Subject: [PATCH 3/7] delay rendering of scrollview content until native views layout has been done on Android --- scrollview-switch.js | 35 ++++++++++++++++++++++++----------- 1 file changed, 24 insertions(+), 11 deletions(-) diff --git a/scrollview-switch.js b/scrollview-switch.js index 7b59c9d..10f4f1c 100644 --- a/scrollview-switch.js +++ b/scrollview-switch.js @@ -13,7 +13,8 @@ class ToggleSwitch extends React.Component { constructor(...props) { super(...props); this.state = { - isActive: this.props.active || false + isActive: this.props.active || false, + isLaidOut: Platform.OS === 'ios', }; this.borderWidth = 2; this.universalPadding = this.props.padding || 2; @@ -23,16 +24,23 @@ class ToggleSwitch extends React.Component { this.initailContentOffset = this.props.active ? 0 : this.props.width + this.textMargin; } - async componentDidMount() { - if (!this.props.active && Platform.OS === 'android') { + // async componentDidMount() { + // if (!this.props.active && Platform.OS === 'android') { // Android hack to push scroll view to end at the initial rendering... - this.intervalRef = setInterval(() => { - if (this.scrollRef) { - this.scrollRef.scrollToEnd({ animated: false }); - clearInterval(this.intervalRef); - } - }, 10); + // this.intervalRef = setInterval(() => { + // if (this.scrollRef) { + // this.scrollRef.scrollToEnd({ animated: false }); + // clearInterval(this.intervalRef); + // } + // }, 10); + // } + // } + + onScrollViewContentSizeChange = () => { + if (this.scrollRef && !this.props.active && Platform.OS === 'android') { + this.scrollRef.scrollToEnd({ animated: false }); } + this.setState({ isLaidOut: true }) } setScrollViewRef = (ref) => this.scrollRef = ref @@ -80,7 +88,7 @@ class ToggleSwitch extends React.Component { textStyle = {}, disabled = false } = this.props; - const { isActive } = this.state; + const { isActive, isLaidOut } = this.state; return ( @@ -107,6 +115,8 @@ class ToggleSwitch extends React.Component { scrollEnabled={!disabled} scrollsToTop={false} contentOffset={{x: this.initailContentOffset, y: 0}} + onContentSizeChange={this.onScrollViewContentSizeChange} + style={{ width: this.viewPortWidth }} > Date: Tue, 2 Jun 2020 16:53:11 +0200 Subject: [PATCH 4/7] added textProps prop to customize the Text components --- scrollview-switch.js | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/scrollview-switch.js b/scrollview-switch.js index 10f4f1c..35152ca 100644 --- a/scrollview-switch.js +++ b/scrollview-switch.js @@ -85,6 +85,7 @@ class ToggleSwitch extends React.Component { render() { const { text: { on = 'ON', off = 'OFF', activeTextColor, inactiveTextColor }, color: { active, inactive, indicator, inactiveIndicator, activeBorder, inactiveBorder }, + textProps = {}, textStyle = {}, disabled = false } = this.props; @@ -148,6 +149,7 @@ class ToggleSwitch extends React.Component { }, textStyle ]} + {...textProps} > {on} @@ -186,13 +188,15 @@ class ToggleSwitch extends React.Component { > + { + alignSelf: 'center', + textAlign: 'center', + color: isActive ? activeTextColor : inactiveTextColor + }, + textStyle + ]} + {...textProps} + > {off} From fda6669b455e6abc6e4be3615e4e2cf937b9aa65 Mon Sep 17 00:00:00 2001 From: Maarten van Dillen <> Date: Wed, 3 Jun 2020 11:42:07 +0200 Subject: [PATCH 5/7] fixed potential crash when no onValueChange handler is defined --- scrollview-switch.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scrollview-switch.js b/scrollview-switch.js index 35152ca..d35cc5f 100644 --- a/scrollview-switch.js +++ b/scrollview-switch.js @@ -51,7 +51,7 @@ class ToggleSwitch extends React.Component { this.setState({ isActive: active }, () => { - this.props.onValueChange(active); + this.props.onValueChange && this.props.onValueChange(active); }); } From 2603d1e22371baf05e26f56ca7ff27aa2051a7fd Mon Sep 17 00:00:00 2001 From: Maarten van Dillen <> Date: Wed, 3 Jun 2020 11:46:04 +0200 Subject: [PATCH 6/7] added support for updating the active prop after initial render --- scrollview-switch.js | 80 ++++++++++++++++++++++++-------------------- 1 file changed, 44 insertions(+), 36 deletions(-) diff --git a/scrollview-switch.js b/scrollview-switch.js index d35cc5f..aa47e57 100644 --- a/scrollview-switch.js +++ b/scrollview-switch.js @@ -9,35 +9,44 @@ import { Platform } from 'react-native'; +const textMargin = 8 + class ToggleSwitch extends React.Component { - constructor(...props) { - super(...props); + constructor(props) { + super(props); + + const universalPadding = this.props.padding || 2 + this.state = { isActive: this.props.active || false, isLaidOut: Platform.OS === 'ios', + borderWidth: 2, + universalPadding, + viewPortRadius: this.props.radius + universalPadding, + viewPortWidth: this.props.width + (2 * this.props.radius) + (2 * universalPadding) + textMargin, + contentOffset: this.props.active ? 0 : this.props.width + textMargin }; - this.borderWidth = 2; - this.universalPadding = this.props.padding || 2; - this.viewPortRadius = this.props.radius + this.universalPadding; - this.textMargin = 8; - this.viewPortWidth = this.props.width + (2 * this.props.radius) + (2 * this.universalPadding) + this.textMargin; - this.initailContentOffset = this.props.active ? 0 : this.props.width + this.textMargin; } - // async componentDidMount() { - // if (!this.props.active && Platform.OS === 'android') { - // Android hack to push scroll view to end at the initial rendering... - // this.intervalRef = setInterval(() => { - // if (this.scrollRef) { - // this.scrollRef.scrollToEnd({ animated: false }); - // clearInterval(this.intervalRef); - // } - // }, 10); - // } - // } + componentDidUpdate(prevProps, prevState) { + const { active } = this.props + if (prevProps.active !== active) { + this.setState({ + isActive: active, + contentOffset: active ? 0 : this.props.width + textMargin + }) + //android fix sync scroll view position with state + if (active) { + this.scrollRef.scrollTo({ x: 0, y: 0, animated: false }) + } else { + this.scrollRef.scrollToEnd({ animated: false }); + } + } + } + //android fix sync scroll view position with state onScrollViewContentSizeChange = () => { - if (this.scrollRef && !this.props.active && Platform.OS === 'android') { + if (this.scrollRef && !this.state.isActive && Platform.OS === 'android') { this.scrollRef.scrollToEnd({ animated: false }); } this.setState({ isLaidOut: true }) @@ -68,7 +77,7 @@ class ToggleSwitch extends React.Component { onDragEnd = (e) => { const { contentOffset } = e.nativeEvent; - if(contentOffset.x > (this.props.width ) / 2) { + if (contentOffset.x > (this.props.width ) / 2) { this.scrollRef.scrollToEnd(); this.updateState(false); } else { @@ -89,21 +98,21 @@ class ToggleSwitch extends React.Component { textStyle = {}, disabled = false } = this.props; - const { isActive, isLaidOut } = this.state; + const { isActive, isLaidOut, borderWidth, universalPadding, viewPortRadius, viewPortWidth, contentOffset } = this.state; return ( - + @@ -115,18 +124,17 @@ class ToggleSwitch extends React.Component { onScrollBeginDrag={this.onDragStart} scrollEnabled={!disabled} scrollsToTop={false} - contentOffset={{x: this.initailContentOffset, y: 0}} + contentOffset={{x: contentOffset, y: 0}} onContentSizeChange={this.onScrollViewContentSizeChange} - - style={{ width: this.viewPortWidth }} + style={{ width: viewPortWidth }} > @@ -136,7 +144,7 @@ class ToggleSwitch extends React.Component { { width: this.props.width, opacity: isLaidOut ? 1 : 0, - // marginLeft: this.viewPortRadius + // marginLeft: viewPortRadius } ]} > @@ -160,7 +168,7 @@ class ToggleSwitch extends React.Component { styles.indicatorWrapper, { justifyContent: isActive ? 'flex-end' : 'flex-start', - padding: this.universalPadding, + padding: universalPadding, opacity: isLaidOut ? 1 : 0, } ]}> @@ -182,7 +190,7 @@ class ToggleSwitch extends React.Component { styles.inactiveView, { width: this.props.width, opacity: isLaidOut ? 1 : 0, - // marginRight: this.viewPortRadius + // marginRight: viewPortRadius } ]} > From 936840fb5f0e88fb593a4bdef6a761d2aa158886 Mon Sep 17 00:00:00 2001 From: Maarten van Dillen <> Date: Thu, 10 Sep 2020 13:51:29 +0200 Subject: [PATCH 7/7] fix for missing setOpacityTo function https://github.com/facebook/react-native/issues/29272#issuecomment-653514316 --- scrollview-switch.js | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/scrollview-switch.js b/scrollview-switch.js index aa47e57..08b155d 100644 --- a/scrollview-switch.js +++ b/scrollview-switch.js @@ -84,11 +84,21 @@ class ToggleSwitch extends React.Component { this.scrollRef.scrollTo({x: 0, y: 0, animated: true}) this.updateState(true); } - this.touchableOpacity.setOpacityTo(1, 300); + //fix for https://github.com/facebook/react-native/issues/29272#issuecomment-653514316 + if (this.touchableOpacity.setOpacityTo != undefined) { + this.touchableOpacity.setOpacityTo(1, 300); + } else if (this.touchableOpacity._setOpacityTo != undefined) { + this.touchableOpacity._setOpacityTo(1, 300); + } } onDragStart = (e) => { - this.touchableOpacity.setOpacityTo(0.5, 300); + //fix for https://github.com/facebook/react-native/issues/29272#issuecomment-653514316 + if (this.touchableOpacity.setOpacityTo != undefined) { + this.touchableOpacity.setOpacityTo(0.5, 300); + } else if (this.touchableOpacity._setOpacityTo != undefined) { + this.touchableOpacity._setOpacityTo(0.5, 300); + } } render() {