Open Kim-Andersen opened 8 years ago
Looks like this is possible with scrollBy()
. I missed it because it isn't listed in the docs. (Note the referenced issue mentions scrollTo
which was renamed to scrollBy
in the 1.4.5 release. So double check your version).
Thank you for your quick answer, leecade.
scrollBy() seems to be the action for buttons moving slides. My idea was, to remove buttons for an easier GUI. Just swiping left or right for moving to dynamic generated views.
I wrote a use short case which only uses native swiper without anything else. It’s working fine on Ios and Android with buttons. But on Android real swiping with the fingers is limited. It's possible only 4 or 5 times. Please try it for yourself.
Thank you for supporting me if you have the time... Benjamin from Munich
import React from 'react'; import ReactNative, { AppRegistry, StyleSheet, Text, View} from 'react-native'; import Swiper from 'react-native-swiper';
var test = React.createClass({ getInitialState: function() { return { items: [{},{},{}], }; }, render: function() { return (
);
} });
const styles = StyleSheet.create({ container: { flex: 1, justifyContent: 'center', backgroundColor: '#F5FCFF', }, welcome: { textAlign: 'center', }, });
AppRegistry.registerComponent('test', () => test);
A snapshot of Ios version
Am 07.06.2016 um 01:53 schrieb lifehackett notifications@github.com:
Looks like this is possible with scrollBy(). I missed it because it isn't listed in the docs. (Note the referenced issue mentions scrollTo which was renamed to scrollBy in the 1.4.5 release. So double check your version).
29 https://github.com/leecade/react-native-swiper/issues/29
— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/leecade/react-native-swiper/issues/163#issuecomment-224123415, or mute the thread https://github.com/notifications/unsubscribe/APMbqoLvDerrJK6FVObKpcin1epp9vDnks5qJLMJgaJpZM4ItXMv.
Here is how I managed to do this. (My use case was to just reset the index back to 0.) I hope this can help others...
I stored the swiper component from ref and storing index after onMomentumScrollEnd. Then on componentWillReceiveProps - I use the scrollBy function to change the index (which is really an offset).
class SuggestionSlider extends Component {
swiper:Object;
currentIndex:number;
componentWillReceiveProps(nextProps) {
if (this.currentIndex > 0) {
this.swiper.scrollBy(this.currentIndex * -1); //offset
}
}
_onMomentumScrollEnd(e, state, context) {
this.currentIndex = state.index;
}
render() {
return (
<Swiper style={styles.swiper} height={180} width={400} ref={component => this.swiper = component} onMomentumScrollEnd = {this._onMomentumScrollEnd.bind(this)} dot={<View style={styles.swiperDot} />} activeDot={<View style={styles.swiperDotActive} />} loop={false}>
...
This is the solution that works for me. Similar to darrenfurr, I grabbed a reference to the swiper and stored it in 'this.swiper': `<Swiper showsButtons={true} style={styles.swiper} showPagination dot={<View style={{backgroundColor: 'rgba(255,255,255,.3)', width: 13, height: 13, borderRadius: 7, marginLeft: 7, marginRight: 7}} />} activeDot={<View style={{backgroundColor: '#fff', width: 13, height: 13, borderRadius: 7, marginLeft: 7, marginRight: 7}} />} paginationStyle={{ bottom: 80 }} ref={component => this.swiper = component}
` Then, I created this method on the parent class:
swipe(targetIndex) {
const currentIndex = this.swiper.state.index;
const offset = targetIndex- incurrentIndex dex;
this.swiper.scrollBy(offset);
}
I'm having a similar issue where I am passing Swiper
an index
prop from a parent component.
When the parent component updates the index, Swiper.componentWillReceiveProps
receives the new index prop value, but it doesn't actually re-render at the new position.
The above workarounds do work, which is great, thank you. But I feel they're less than optimal. The Swiper
component is aware of receiving new props, so I think this is actually a bug.
To give a more complete example, here's what I came up with and it's working beautifully. We have a Redux application and I always like being able to control everything with the state so this solution worked perfectly because it stays in sync with the state but can also be controlled when the state changes:
import React, {
PureComponent,
} from 'react';
import RNSwiper from 'react-native-swiper';
import PropTypes from 'prop-types';
export default class Swiper extends PureComponent {
static propTypes = {
onIndexChanged: PropTypes.func,
index: PropTypes.number,
};
index = 0;
constructor(props) {
super(props);
const { index } = this.props;
this.index = index;
}
ref = (el) => {
this.swiper = el;
};
onIndexChanged = (newIndex) => {
const { onIndexChanged } = this.props;
this.index = newIndex;
if (onIndexChanged) {
onIndexChanged(newIndex);
}
};
componentWillReceiveProps({ index }) {
if (index !== this.index) {
const difference = index - this.index;
this.swiper.scrollBy(difference);
}
}
render() {
return (
<RNSwiper
{...this.props}
ref={el => this.ref(el)}
onIndexChanged={this.onIndexChanged}
/>
);
}
}
@dwilt I tried to use wrapper mentioned above and I have problem with 5 elements. I can jump to 2,3,4 - hovewer when I try to jump to 1st the last one appears. Do You have any idea what i'm doing wrong ?
Typescript implementation of @dwit's solution
// https://github.com/leecade/react-native-swiper/issues/163
import React, {
Component,
} from 'react';
import Swiper from 'react-native-swiper';
type OnIndexChangedMethodType = any;
export interface ControllableSwiperPropsType {
onIndexChanged?: OnIndexChangedMethodType;
index: number;
children: any;
}
export default class ControllableSwiper extends Component<ControllableSwiperPropsType> {
private index: number;
private swiper: Swiper; // stores reference to swiper
// use constructor to define what index we will be in
constructor(props: ControllableSwiperPropsType) {
super(props);
const { index } = this.props;
this.index = index;
}
// on indexChagned
protected onIndexChanged = (newIndex: number) => {
const prevIndex = this.index;
if (prevIndex === newIndex) return; // if they're the same, do nothing and trigger nothing.
this.index = newIndex;
if (this.props.onIndexChanged) this.props.onIndexChanged({ index: newIndex, prevIndex });
}
// if component is getting an index change, we must trigger the scrollBy method - since for some reason the Swiper component does not respect index on rerender
public componentWillReceiveProps({ index }: ControllableSwiperPropsType) {
if (index !== this.index) { // if the index has changed, trigger the scrollby method
const difference = index - this.index;
(this.swiper as any).scrollBy(difference);
}
}
public render() {
return (
<Swiper
index={this.index}
ref={(swiper) => { this.swiper = swiper; }}
onIndexChanged={this.onIndexChanged}>
{this.props.children}
</Swiper>
);
}
}
Hi, Great component.
Is there any way to programmatically update the active index of the swiper? It would be helpful to have a parent component update a prop or call a method on the swiper, to have it animate to an index of choice.
Thanks