re-rendering 60 times per second with the new progress this.subscription = mediaPlayerTimeProgressEmitter.addListener( 'TimeProgress', (progress: number) => this.setState({ progress, }), ); } componentWillUnmount() { this.subscription.remove(); } render() { const { isPlaying } = this.state; // Calculating the left margin based on the score width, // and total duration of the song
the margin left based on the time progress, // width of the score and duration of the song const scoreLeftMargin = this.calculateLeftMargin(); return ( <View style={{ flex: 1 }}> <Score style={{ marginLeft: scoreLeftMargin }} /> <Playback src={'https://player/song.mp4'} isPlaying /> <Button title={isPlaying ? ‘PAUSE' : 'PLAY'} onPress={() => this.setState({ isPlaying: !isPlaying, })} /> </View> ); } } componentWillUnmount() { this.subscription.remove(); }
new animated value based on the accumulated // distance of the gesture since the touch started, dx. // Duration and score width are constants const nextValue = -(gestureState.dx / (this.state.width / this.props.duration)); this.props.progress.setValue(nextValue + this.progressAccValue); },
We'll update the local state 1 time per second * when the value is controlled by the playback */ componentDidMount() { let prevValue = 0; this._listenerId = this.props.progress.addListener((e: *) => { // Math.round() will always round down to the lesser integer const nextTimeInSeconds = Math.floor(e.value / 1000); if (!this.state.isSliding && prevValue !== nextTimeInSeconds) { this.setState({ value: nextTimeInSeconds }); } prevValue = nextTimeInSeconds; }); }
• Native Modules and Native UI Components are the game changers • Keep the ScrollView in mind as a reference model: Practical hacks for delightful interactions • Think. Research. Plan. Write. Validate. Fail. Modify