Search code examples
react-nativereact-native-scrollview

How to slide card when click on button in React Native?


I'm creating a react native app and I need to create a card slider with a button click. When click on the button need to slide to the card image and also when slide the card need to change the button color in order to the correct one. The below screens shows what I need,

Screen1

Screen2

I am able to design the following screen and now I need to know how to do sliding things when clicking on the button and how to change button color when sliding the card. This is what I did,

My code samples

import React, {Component} from 'react';
import {
  View,
  Text,
  TouchableOpacity,
  TextInput,
  Platform,
  StyleSheet,
  StatusBar,
  Alert,
  Image,
  ScrollView,
  Animated,
  Dimensions,
  Modal,
} from 'react-native';
import * as Animatable from 'react-native-animatable';


const {width, height} = Dimensions.get('window');
const CARD_HEIGHT = 260;
const CARD_WIDTH = width * 0.8;
const SPACING_FOR_CARD_INSET = width * 0.1 - 10;

class TestSlider extends Component {

      return (
        <View style={styles.container}>
          <StatusBar backgroundColor="#750056" barStyle="light-content" />
          <View style={styles.header}>
            <Text style={styles.text_header}>Select Your Travel method !</Text>
          </View>
          <Animatable.View animation="fadeInUpBig" style={[styles.footer]}>
            <View style={styles.CardDetail}>
        
                <TouchableOpacity style={styles.CardDetail1} onPress={() => {this.scroll.scrollTo({ x: 0 }); this.SetColor();}}>
                <View style={styles.detailContent}>
                  <Text style={styles.title}>Car</Text>
                </View>
                </TouchableOpacity>
                  
              <TouchableOpacity style={styles.CardDetail1} onPress={() => this.scroll.scrollTo({ x: CARD_WIDTH }) }>
                <View style={styles.detailContent}>
                  <Text style={styles.title}>Bus</Text>
                </View>
                </TouchableOpacity>
              <TouchableOpacity style={styles.CardDetail1} onPress={() => this.scroll.scrollTo({ x: CARD_WIDTH *2 })}>
                <View style={styles.detailContent}>
                  <Text style={styles.title}>Train</Text>
                </View>
                </TouchableOpacity>
            </View>

            <Animated.ScrollView
              ref={(node) => this.scroll = node}
              horizontal
              scrollEventThrottle={1}
              showsHorizontalScrollIndicator={false}
              style={styles.scrollView}
              pagingEnabled
              snapToInterval={CARD_WIDTH + 20}
              snapToAlignment="center">
              <View style={styles.card}>
                <Image
                  source={require('../assets/car.png')}
                  style={styles.cardImage}
                  resizeMode="contain"
                />
                <View style={styles.button}>
                  <TouchableOpacity
                    onPress={() => {
                      this.setModalVisible(true);
                    }}
                    style={[
                      styles.selectNow,
                      {
                        borderColor: '#009387',
                        borderWidth: 1,
                      },
                    ]}>
                    <Text
                      style={[
                        styles.textSelect,
                        {
                          color: '#009387',
                        },
                      ]}>
                      Select Now
                    </Text>
                  </TouchableOpacity>
                </View>
              </View>
              <View style={styles.card}>
                <Image
                  source={require('../assets/bus.jpg')}
                  style={styles.cardImage}
                  resizeMode="stretch"
                />
                <View style={styles.button}>
                  <TouchableOpacity
                    onPress={() => {}}
                    style={[
                      styles.selectNow,
                      {
                        borderColor: '#009387',
                        borderWidth: 1,
                      },
                    ]}>
                    <Text
                      style={[
                        styles.textSelect,
                        {
                          color: '#009387',
                        },
                      ]}>
                      Select Now
                    </Text>
                  </TouchableOpacity>
                </View>
              </View>
              <View style={styles.card}>
                <Image
                  source={require('../assets/train.png')}
                  style={styles.cardImage}
                  resizeMode="stretch"
                />
                <View style={styles.button}>
                  <TouchableOpacity
                    onPress={() => {}}
                    style={[
                      styles.selectNow,
                      {
                        borderColor: '#009387',
                        borderWidth: 1,
                      },
                    ]}>
                    <Text
                      style={[
                        styles.textSelect,
                        {
                          color: '#009387',
                        },
                      ]}>
                      Select Now
                    </Text>
                  </TouchableOpacity>
                </View>
              </View>
            </Animated.ScrollView>
          </Animatable.View>
        </View>
      );
    }
  
}

export default TestSlider;

const styles = StyleSheet.create({
  container1: {
    flex: 1,
    backgroundColor: '#fff',
    alignItems: 'center',
    justifyContent: 'center',
  },
  container: {
    flex: 1,
    backgroundColor: '#750056',
  },
  cardContainer: {
    backgroundColor: '#fff',
    marginTop: 60,
  },
  header: {
    flex: 1,
    justifyContent: 'flex-end',
    paddingHorizontal: 20,
    paddingBottom: 30,
  },
  text_header: {
    color: '#fff',
    fontWeight: 'bold',
    fontSize: 28,
  },
  footer: {
    flex: 1,
    backgroundColor: '#fff',
    borderTopLeftRadius: 30,
    borderTopRightRadius: 30,
    paddingHorizontal: 20,
    paddingVertical: 30,
  },
  scrollView: {
    // position: "absolute",
    top: 60,
    // bottom: 0,
    left: 0,
    right: 0,
    paddingVertical: 10,
  },
  card: {
    // padding: 10,
    elevation: 3,
    backgroundColor: '#FFF',
    borderTopLeftRadius: 10,
    borderBottomRightRadius: 10,
    marginHorizontal: 10,
    shadowColor: '#000',
    shadowRadius: 15,
    shadowOpacity: 0.3,
    shadowOffset: {x: 2, y: -2},
    height: CARD_HEIGHT,
    width: CARD_WIDTH,
    overflow: 'hidden',
  },
  cardImage: {
    flex: 3,
    width: '100%',
    height: '100%',
    alignSelf: 'center',
  },
  button: {
    alignItems: 'center',
    marginTop: 5,
    marginBottom: 5,
  },
  selectNow: {
    width: '80%',
    padding: 5,
    justifyContent: 'center',
    alignItems: 'center',
    borderRadius: 3,
  },
  textSelect: {
    fontSize: 16,
    fontWeight: 'bold',
  },
  CardDetail: {
    alignSelf: 'center',
    marginTop: 20,
    alignItems: 'center',
    flexDirection: 'row',
    position: 'absolute',
    // backgroundColor: "#009387",
  },
  CardDetail1: {
    // alignSelf: 'center',
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#009387',
    borderRadius: 20,
    marginHorizontal: 5,
    width: '30%',
  },
  detailContent: {
    margin: 10,
    alignItems: 'center',
  },
  title:{
    fontSize:14,
    color: "#fff"
  },
});

This is my design UI

Screen3

In my code sliding things working fine. Now I need to change the button color when clicking on it and scroll into the right card. And when sliding the card it should change the right button color. Please help me to solve this problem.


Solution

  • here is my sample :

    import React, { Component, useRef, useState } from 'react';
    import {
      View,
      Text,
      TouchableOpacity,
      TextInput,
      Platform,
      StyleSheet,
      StatusBar,
      Alert,
      Image,
      ScrollView,
      Animated,
      Dimensions,
      Modal,
    
    } from 'react-native';
    import * as Animatable from 'react-native-animatable';
    
    const { width, height } = Dimensions.get('window');
    const CARD_HEIGHT = 260;
    const CARD_WIDTH = width * 0.8;
    const SPACING_FOR_CARD_INSET = width * 0.1 - 10;
    
    const App: () => React$Node = () => {
      const refScrollview = useRef(ScrollView)
      let y = 0;
      let animated = true;
      const [isCar, setIsCar] = useState(true);
      const [isBus, setIsBus] = useState(false);
      const [isTrain, setIsTrain] = useState(false);
    
      const handleScroll = (event: Object) => {
        if (event.nativeEvent.contentOffset.x < 350) {
          setIsCar(true);
          setIsBus(false);
          setIsTrain(false);
        } else if (event.nativeEvent.contentOffset.x >= 350 && event.nativeEvent.contentOffset.x < 600) {
          setIsCar(false);
          setIsBus(true);
          setIsTrain(false);
        } else if (event.nativeEvent.contentOffset.x >= 600) {
          setIsCar(false);
          setIsBus(false);
          setIsTrain(true);
        }
      }
    
      return (
        <View style={styles.container}>
          <StatusBar backgroundColor="#750056" barStyle="light-content" />
          <View style={styles.header}>
            <Text style={styles.text_header}>Select Your Travel method !</Text>
          </View>
          <Animatable.View animation="fadeInUpBig" style={[styles.footer]}>
            <View style={styles.CardDetail}>
    
              <TouchableOpacity style={[styles.CardDetail1, { backgroundColor: isCar ? '#750056' : '#009387' }]} onPress={() => {
                refScrollview.current.scrollTo({ x: 0, y, animated });
                setIsCar(true);
                setIsBus(false);
                setIsTrain(false);
              }}>
                <View style={styles.detailContent}>
                  <Text style={styles.title}>Car</Text>
                </View>
              </TouchableOpacity>
    
              <TouchableOpacity style={[styles.CardDetail1, { backgroundColor: isBus ? '#750056' : '#009387' }]} onPress={() => {
                refScrollview.current.scrollTo({ x: 350, y, animated }); setIsCar(false);
                setIsBus(true);
                setIsTrain(false);
              }}>
                <View style={styles.detailContent}>
                  <Text style={styles.title}>Bus</Text>
                </View>
              </TouchableOpacity>
              <TouchableOpacity style={[styles.CardDetail1, { backgroundColor: isTrain ? '#750056' : '#009387' }]} onPress={() => {
                refScrollview.current.scrollTo({ x: 600, y, animated });
                setIsCar(false);
                setIsBus(false);
                setIsTrain(true);
              }}>
                <View style={styles.detailContent}>
                  <Text style={styles.title}>Train</Text>
                </View>
              </TouchableOpacity>
            </View>
    
            <Animated.ScrollView
              ref={refScrollview}
              horizontal
              scrollEventThrottle={1}
              showsHorizontalScrollIndicator={false}
              style={styles.scrollView}
              pagingEnabled
              snapToInterval={CARD_WIDTH + 20}
              snapToAlignment="center"
              onScroll={handleScroll}>
              <View style={styles.card}>
                <Image
                  source={require('./assets/bus.jpg')}
                  style={styles.cardImage}
                  resizeMode="contain"
                />
                <View style={styles.button}>
                  <TouchableOpacity
                    onPress={() => {
                      this.setModalVisible(true);
                    }}
                    style={[
                      styles.selectNow,
                      {
                        borderColor: '#009387',
                        borderWidth: 1,
                      },
                    ]}>
                    <Text
                      style={[
                        styles.textSelect,
                        {
                          color: '#009387',
                        },
                      ]}>
                      Select Now
                        </Text>
                  </TouchableOpacity>
                </View>
              </View>
              <View style={styles.card}>
                <Image
                  source={require('./assets/bus.jpg')}
                  style={styles.cardImage}
                  resizeMode="stretch"
                />
                <View style={styles.button}>
                  <TouchableOpacity
                    onPress={() => { }}
                    style={[
                      styles.selectNow,
                      {
                        borderColor: '#009387',
                        borderWidth: 1,
                      },
                    ]}>
                    <Text
                      style={[
                        styles.textSelect,
                        {
                          color: '#009387',
                        },
                      ]}>
                      Select Now
                        </Text>
                  </TouchableOpacity>
                </View>
              </View>
              <View style={styles.card}>
                <Image
                  source={require('./assets/bus.jpg')}
                  style={styles.cardImage}
                  resizeMode="stretch"
                />
                <View style={styles.button}>
                  <TouchableOpacity
                    onPress={() => { }}
                    style={[
                      styles.selectNow,
                      {
                        borderColor: '#009387',
                        borderWidth: 1,
                      },
                    ]}>
                    <Text
                      style={[
                        styles.textSelect,
                        {
                          color: '#009387',
                        },
                      ]}>
                      Select Now
                        </Text>
                  </TouchableOpacity>
                </View>
              </View>
            </Animated.ScrollView>
          </Animatable.View>
        </View>
      );
    };
    
    const styles = StyleSheet.create({
      container1: {
        flex: 1,
        backgroundColor: '#fff',
        alignItems: 'center',
        justifyContent: 'center',
      },
      container: {
        flex: 1,
        backgroundColor: '#750056',
      },
      cardContainer: {
        backgroundColor: '#fff',
        marginTop: 60,
      },
      header: {
        flex: 1,
        justifyContent: 'flex-end',
        paddingHorizontal: 20,
        paddingBottom: 30,
      },
      text_header: {
        color: '#fff',
        fontWeight: 'bold',
        fontSize: 28,
      },
      footer: {
        flex: 1,
        backgroundColor: '#fff',
        borderTopLeftRadius: 30,
        borderTopRightRadius: 30,
        paddingHorizontal: 20,
        paddingVertical: 30,
      },
      scrollView: {
        // position: "absolute",
        top: 60,
        // bottom: 0,
        left: 0,
        right: 0,
        paddingVertical: 10,
      },
      card: {
        // padding: 10,
        elevation: 3,
        backgroundColor: '#FFF',
        borderTopLeftRadius: 10,
        borderBottomRightRadius: 10,
        marginHorizontal: 10,
        shadowColor: '#000',
        shadowRadius: 15,
        shadowOpacity: 0.3,
        shadowOffset: { x: 2, y: -2 },
        height: CARD_HEIGHT,
        width: CARD_WIDTH,
        overflow: 'hidden',
      },
      cardImage: {
        flex: 3,
        width: '100%',
        height: '100%',
        alignSelf: 'center',
      },
      button: {
        alignItems: 'center',
        marginTop: 5,
        marginBottom: 5,
      },
      selectNow: {
        width: '80%',
        padding: 5,
        justifyContent: 'center',
        alignItems: 'center',
        borderRadius: 3,
      },
      textSelect: {
        fontSize: 16,
        fontWeight: 'bold',
      },
      CardDetail: {
        alignSelf: 'center',
        marginTop: 20,
        alignItems: 'center',
        flexDirection: 'row',
        position: 'absolute',
        // backgroundColor: "#009387",
      },
      CardDetail1: {
        // alignSelf: 'center',
        justifyContent: 'center',
        alignItems: 'center',
        backgroundColor: '#009387',
        borderRadius: 20,
        marginHorizontal: 5,
        width: '30%',
      },
      detailContent: {
        margin: 10,
        alignItems: 'center',
      },
      title: {
        fontSize: 14,
        color: "#fff"
      },
    });
    
    export default App;