Skip to content

Commit 8d6d75c

Browse files
author
yuji
committed
fixes #7 inject state in ScrollResponders @thanks smothers
Now you can get `state` and `context`(ref to swiper's `this`) from params
1 parent ff4e7b2 commit 8d6d75c

File tree

7 files changed

+158
-29
lines changed

7 files changed

+158
-29
lines changed

README.md

Lines changed: 37 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ The best Swiper component for React Native.
3535

3636
- [x] Custom pagination style
3737

38+
- [x] State inject
39+
3840
## Changelogs
3941

4042
- **[v1.2.2]**
@@ -167,7 +169,7 @@ AppRegistry.registerComponent('swiper', () => swiper)
167169

168170
#### Basic
169171

170-
| Prop | Default | Type | Describe |
172+
| Prop | Default | Type | Description |
171173
| :------------ |:---------------:| :---------------:| :-----|
172174
| horizontal | true | `bool` | If `true`, the scroll view's children are arranged horizontally in a row instead of vertically in a column. |
173175
| loop | true | `bool` | Set to `true` to enable continuous loop mode. |
@@ -177,33 +179,33 @@ AppRegistry.registerComponent('swiper', () => swiper)
177179

178180
#### Custom basic style & content
179181

180-
| Prop | Default | Type | Describe |
182+
| Prop | Default | Type | Description |
181183
| :------------ |:---------------:| :---------------:| :-----|
182184
| width | - | `number` | If no specify default enable fullscreen mode by `flex: 1`. |
183185
| height | - | `number` | If no specify default fullscreen mode by `flex: 1`. |
184186
| style | {...} | `style` | See default style in source. |
185187

186188
#### Pagination
187189

188-
| Prop | Default | Type | Describe |
190+
| Prop | Default | Type | Description |
189191
| :------------ |:---------------:| :---------------:| :-----|
190192
| showsPagination | true | `bool` | Set to `true` make pagination visible. |
191193
| paginationStyle | {...} | `style` | Custom styles will merge with the default styles. |
192-
| renderPagination | - | `function` | Complete control how to render pagination with two params (`index`, `total`) ref to `this.state.index` / `this.state.total`, For example: show numbers instead of dots. |
194+
| renderPagination | - | `function` | Complete control how to render pagination with three params (`index`, `total`, `context`) ref to `this.state.index` / `this.state.total` / `this`, For example: show numbers instead of dots. |
193195
| dot | `<View style={{backgroundColor:'rgba(0,0,0,.2)', width: 8, height: 8,borderRadius: 4, marginLeft: 3, marginRight: 3, marginTop: 3, marginBottom: 3,}} />` | `element` | Allow custom the dot element. |
194196
| activeDot | `<View style={{backgroundColor: '#007aff', width: 8, height: 8, borderRadius: 4, marginLeft: 3, marginRight: 3, marginTop: 3, marginBottom: 3,}} />` | `element` | Allow custom the active-dot element. |
195197

196198
#### Autoplay
197199

198-
| Prop | Default | Type | Describe |
200+
| Prop | Default | Type | Description |
199201
| :------------ |:---------------:| :---------------:| :-----|
200202
| autoplay | true | `bool` | Set to `true` enable auto play mode. |
201203
| autoplayTimeout | 2.5 | `number` | Delay between auto play transitions (in second). |
202204
| autoplayDirection | true | `bool` | Cycle direction control. |
203205

204206
#### Control buttons
205207

206-
| Prop | Default | Type | Describe |
208+
| Prop | Default | Type | Description |
207209
| :------------ |:---------------:| :---------------:| :-----|
208210
| showsButtons | true | `bool` | Set to `true` make control buttons visible. |
209211
| buttonWrapperStyle | `{backgroundColor: 'transparent', flexDirection: 'row', position: 'absolute', top: 0, left: 0, flex: 1, paddingHorizontal: 10, paddingVertical: 10, justifyContent: 'space-between', alignItems: 'center'}` | `style` | Custom styles. |
@@ -212,14 +214,14 @@ AppRegistry.registerComponent('swiper', () => swiper)
212214

213215
#### Props of Children
214216

215-
| Prop | Default | Type | Describe |
217+
| Prop | Default | Type | Description |
216218
| :------------ |:---------------:| :---------------:| :-----|
217219
| style | {...} | `style` | Custom styles will merge with the default styles. |
218220
| title | {<Text numberOfLines={1}>...</Text>} | `element` | If this parameter is not specified, will not render the title. |
219221

220222
#### Basic props of `<ScrollView />`
221223

222-
| Prop | Default | Type | Describe |
224+
| Prop | Default | Type | Description |
223225
| :------------ |:---------------:| :---------------:| :-----|
224226
| horizontal | true | `bool` | If `true`, the scroll view's children are arranged horizontally in a row instead of vertically in a column. |
225227
| pagingEnabled | true | `bool` | If true, the scroll view stops on multiples of the scroll view's size when scrolling. This can be used for horizontal pagination. |
@@ -234,16 +236,34 @@ AppRegistry.registerComponent('swiper', () => swiper)
234236
235237
#### Supported ScrollResponder
236238

237-
| Prop | Default | Type | Describe |
239+
| Prop | Params | Type | Description |
238240
| :------------ |:---------------:| :---------------:| :-----|
239-
| onMomentumScrollBegin | - | `function` | When animation begins after letting up |
240-
| onMomentumScrollEnd | - | `function` | Makes no sense why this occurs first during bounce |
241-
| onTouchStartCapture | - | `function` | Immediately after `onMomentumScrollEnd` |
242-
| onTouchStart | - | `function` | Same, but bubble phase |
243-
| onTouchEnd | - | `function` | You could hold the touch start for a long time |
244-
| onResponderRelease | - | `function` | When lifting up - you could pause forever before * lifting |
245-
246-
> @see: https://github.com/facebook/react-native/blob/master/Libraries/Components/ScrollResponder.js
241+
| onMomentumScrollBegin | `e` / `state` / `context` | `function` | When animation begins after letting up |
242+
| onMomentumScrollEnd | `e` / `state` / `context` | `function` | Makes no sense why this occurs first during bounce |
243+
| onTouchStartCapture | `e` / `state` / `context` | `function` | Immediately after `onMomentumScrollEnd` |
244+
| onTouchStart | `e` / `state` / `context` | `function` | Same, but bubble phase |
245+
| onTouchEnd | `e` / `state` / `context` | `function` | You could hold the touch start for a long time |
246+
| onResponderRelease | `e` / `state` / `context` | `function` | When lifting up - you could pause forever before * lifting |
247+
248+
> Note: each ScrollResponder be injected with two params: `state` and `context`, you can get `state` and `this`(ref to swiper's context) from params, for example:
249+
250+
```jsx
251+
var swiper = React.createClass({
252+
_onMomentumScrollEnd: function (e, state, context) {
253+
console.log(state, context.state)
254+
},
255+
render: function() {
256+
return (
257+
<Swiper style={styles.wrapper}
258+
onMomentumScrollEnd ={this._onMomentumScrollEnd}
259+
...
260+
</Swiper>
261+
)
262+
}
263+
})
264+
```
265+
266+
> More ScrollResponder info, see: https://github.com/facebook/react-native/blob/master/Libraries/Components/ScrollResponder.js
247267
248268
### Examples
249269

dist/index.js

Lines changed: 38 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,10 @@ exports['default'] = _React$StyleSheet$Text$View$ScrollView$TouchableOpacity2['d
192192
*/
193193
autoplayTimer: null,
194194

195+
componentWillMount: function componentWillMount() {
196+
this.props = this.injectState(this.props);
197+
},
198+
195199
componentDidMount: function componentDidMount() {
196200
this.autoplay();
197201
},
@@ -227,7 +231,7 @@ exports['default'] = _React$StyleSheet$Text$View$ScrollView$TouchableOpacity2['d
227231
});
228232

229233
this.setTimeout(function () {
230-
_this2.props.onScrollBeginDrag && _this2.props.onScrollBeginDrag.call(_this2, e);
234+
_this2.props.onScrollBeginDrag && _this2.props.onScrollBeginDrag(e, _this2.state, _this2);
231235
});
232236
},
233237

@@ -251,7 +255,7 @@ exports['default'] = _React$StyleSheet$Text$View$ScrollView$TouchableOpacity2['d
251255
_this3.autoplay();
252256

253257
// if `onMomentumScrollEnd` registered will be called here
254-
_this3.props.onMomentumScrollEnd && _this3.props.onMomentumScrollEnd.call(_this3, e);
258+
_this3.props.onMomentumScrollEnd && _this3.props.onMomentumScrollEnd(e, _this3.state, _this3);
255259
});
256260
},
257261

@@ -400,6 +404,37 @@ exports['default'] = _React$StyleSheet$Text$View$ScrollView$TouchableOpacity2['d
400404
);
401405
},
402406

407+
/**
408+
* Inject state to ScrollResponder
409+
* @param {object} props origin props
410+
* @return {object} props injected props
411+
*/
412+
injectState: function injectState(props) {
413+
var _this5 = this;
414+
415+
/* const scrollResponders = [
416+
'onMomentumScrollBegin',
417+
'onTouchStartCapture',
418+
'onTouchStart',
419+
'onTouchEnd',
420+
'onResponderRelease',
421+
]*/
422+
423+
for (var prop in props) {
424+
// if(~scrollResponders.indexOf(prop)
425+
if (typeof props[prop] === 'function' && prop !== 'onMomentumScrollEnd' && prop !== 'renderPagination' && prop !== 'onScrollBeginDrag') {
426+
(function () {
427+
var originResponder = props[prop];
428+
props[prop] = function (e) {
429+
return originResponder(e, _this5.state, _this5);
430+
};
431+
})();
432+
}
433+
}
434+
435+
return props;
436+
},
437+
403438
/**
404439
* Default render
405440
* @return {object} react-dom
@@ -456,7 +491,7 @@ exports['default'] = _React$StyleSheet$Text$View$ScrollView$TouchableOpacity2['d
456491
onMomentumScrollEnd: this.onScrollEnd }),
457492
pages
458493
),
459-
props.showsPagination && (props.renderPagination ? this.props.renderPagination.call(this, state.index, state.total) : this.renderPagination()),
494+
props.showsPagination && (props.renderPagination ? this.props.renderPagination(state.index, state.total, this) : this.renderPagination()),
460495
this.renderTitle(),
461496
this.props.showsButtons && this.renderButtons()
462497
);

examples/examples/basic.js

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,15 @@ var styles = StyleSheet.create({
3535
})
3636

3737
var swiper = React.createClass({
38+
_onMomentumScrollEnd: function (e, state, context) {
39+
// you can get `state` and `this`(ref to swiper's context) from params
40+
console.log(state, context.state)
41+
},
3842
render: function() {
3943
return (
40-
<Swiper style={styles.wrapper} showsButtons={true}>
44+
<Swiper style={styles.wrapper}
45+
onMomentumScrollEnd={this._onMomentumScrollEnd}
46+
showsButtons={true}>
4147
<View style={styles.slide1}>
4248
<Text style={styles.text}>Hello Swiper</Text>
4349
</View>

examples/examples/index.js

Lines changed: 38 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,10 @@ exports['default'] = _React$StyleSheet$Text$View$ScrollView$TouchableOpacity2['d
192192
*/
193193
autoplayTimer: null,
194194

195+
componentWillMount: function componentWillMount() {
196+
this.props = this.injectState(this.props);
197+
},
198+
195199
componentDidMount: function componentDidMount() {
196200
this.autoplay();
197201
},
@@ -227,7 +231,7 @@ exports['default'] = _React$StyleSheet$Text$View$ScrollView$TouchableOpacity2['d
227231
});
228232

229233
this.setTimeout(function () {
230-
_this2.props.onScrollBeginDrag && _this2.props.onScrollBeginDrag.call(_this2, e);
234+
_this2.props.onScrollBeginDrag && _this2.props.onScrollBeginDrag(e, _this2.state, _this2);
231235
});
232236
},
233237

@@ -251,7 +255,7 @@ exports['default'] = _React$StyleSheet$Text$View$ScrollView$TouchableOpacity2['d
251255
_this3.autoplay();
252256

253257
// if `onMomentumScrollEnd` registered will be called here
254-
_this3.props.onMomentumScrollEnd && _this3.props.onMomentumScrollEnd.call(_this3, e);
258+
_this3.props.onMomentumScrollEnd && _this3.props.onMomentumScrollEnd(e, _this3.state, _this3);
255259
});
256260
},
257261

@@ -400,6 +404,37 @@ exports['default'] = _React$StyleSheet$Text$View$ScrollView$TouchableOpacity2['d
400404
);
401405
},
402406

407+
/**
408+
* Inject state to ScrollResponder
409+
* @param {object} props origin props
410+
* @return {object} props injected props
411+
*/
412+
injectState: function injectState(props) {
413+
var _this5 = this;
414+
415+
/* const scrollResponders = [
416+
'onMomentumScrollBegin',
417+
'onTouchStartCapture',
418+
'onTouchStart',
419+
'onTouchEnd',
420+
'onResponderRelease',
421+
]*/
422+
423+
for (var prop in props) {
424+
// if(~scrollResponders.indexOf(prop)
425+
if (typeof props[prop] === 'function' && prop !== 'onMomentumScrollEnd' && prop !== 'renderPagination' && prop !== 'onScrollBeginDrag') {
426+
(function () {
427+
var originResponder = props[prop];
428+
props[prop] = function (e) {
429+
return originResponder(e, _this5.state, _this5);
430+
};
431+
})();
432+
}
433+
}
434+
435+
return props;
436+
},
437+
403438
/**
404439
* Default render
405440
* @return {object} react-dom
@@ -456,7 +491,7 @@ exports['default'] = _React$StyleSheet$Text$View$ScrollView$TouchableOpacity2['d
456491
onMomentumScrollEnd: this.onScrollEnd }),
457492
pages
458493
),
459-
props.showsPagination && (props.renderPagination ? this.props.renderPagination.call(this, state.index, state.total) : this.renderPagination()),
494+
props.showsPagination && (props.renderPagination ? this.props.renderPagination(state.index, state.total, this) : this.renderPagination()),
460495
this.renderTitle(),
461496
this.props.showsButtons && this.renderButtons()
462497
);

examples/examples/swiper.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ var swiper = React.createClass({
6060
</Swiper>
6161

6262
<Swiper style={styles.wrapper} height={240}
63-
onMomentumScrollEnd={function(){console.log('this.state.index:', this.state.index)}}
63+
onMomentumScrollEnd={function(e, state, context){console.log('index:', state.index)}}
6464
dot={<View style={{backgroundColor:'rgba(0,0,0,.2)', width: 5, height: 5,borderRadius: 4, marginLeft: 3, marginRight: 3, marginTop: 3, marginBottom: 3,}} />}
6565
activeDot={<View style={{backgroundColor: '#000', width: 8, height: 8, borderRadius: 4, marginLeft: 3, marginRight: 3, marginTop: 3, marginBottom: 3,}} />}
6666
paginationStyle={{

examples/examples/swiper_number.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ var styles = StyleSheet.create({
2525
}
2626
})
2727

28-
var renderPagination = function (index, total) {
28+
var renderPagination = function (index, total, context) {
2929
return (
3030
<View style={{
3131
position: 'absolute',

src/index.js

Lines changed: 36 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,10 @@ export default React.createClass({
192192
*/
193193
autoplayTimer: null,
194194

195+
componentWillMount() {
196+
this.props = this.injectState(this.props)
197+
},
198+
195199
componentDidMount() {
196200
this.autoplay()
197201
},
@@ -227,7 +231,7 @@ export default React.createClass({
227231
})
228232

229233
this.setTimeout(() => {
230-
this.props.onScrollBeginDrag && this.props.onScrollBeginDrag.call(this, e)
234+
this.props.onScrollBeginDrag && this.props.onScrollBeginDrag(e, this.state, this)
231235
})
232236
},
233237

@@ -250,7 +254,7 @@ export default React.createClass({
250254
this.autoplay()
251255

252256
// if `onMomentumScrollEnd` registered will be called here
253-
this.props.onMomentumScrollEnd && this.props.onMomentumScrollEnd.call(this, e)
257+
this.props.onMomentumScrollEnd && this.props.onMomentumScrollEnd(e, this.state, this)
254258
})
255259
},
256260

@@ -387,6 +391,35 @@ export default React.createClass({
387391
)
388392
},
389393

394+
/**
395+
* Inject state to ScrollResponder
396+
* @param {object} props origin props
397+
* @return {object} props injected props
398+
*/
399+
injectState(props) {
400+
/* const scrollResponders = [
401+
'onMomentumScrollBegin',
402+
'onTouchStartCapture',
403+
'onTouchStart',
404+
'onTouchEnd',
405+
'onResponderRelease',
406+
]*/
407+
408+
for(let prop in props) {
409+
// if(~scrollResponders.indexOf(prop)
410+
if(typeof props[prop] === 'function'
411+
&& prop !== 'onMomentumScrollEnd'
412+
&& prop !== 'renderPagination'
413+
&& prop !== 'onScrollBeginDrag'
414+
) {
415+
let originResponder = props[prop]
416+
props[prop] = (e) => originResponder(e, this.state, this)
417+
}
418+
}
419+
420+
return props
421+
},
422+
390423
/**
391424
* Default render
392425
* @return {object} react-dom
@@ -434,7 +467,7 @@ export default React.createClass({
434467
{pages}
435468
</ScrollView>
436469
{props.showsPagination && (props.renderPagination
437-
? this.props.renderPagination.call(this, state.index, state.total)
470+
? this.props.renderPagination(state.index, state.total, this)
438471
: this.renderPagination())}
439472
{this.renderTitle()}
440473
{this.props.showsButtons && this.renderButtons()}

0 commit comments

Comments
 (0)