loading...

Making sliding tabs in React Native

debadeepsen profile image debadeepsen Updated on ・3 min read

Sliding tab bars are used in the Facebook app, so I was thinking, why not try to do the same in React Native, especially considering that is what they used to build the Facebook app? I quickly realized that I could achieve this using a View that was hidden partially, off-screen, and then using animation to translate it along the X-direction, to move the other parts of the view into place as and when needed. For this, I used the Animated library, and the translateX property of transform. What we're doing is, binding that property to the value of slideAnim, which changes when we press the tab buttons. I'm not covering the basics of Animated here, you can find that in the official docs - https://reactnative.dev/docs/animated . In fact, this example below has been made by slightly modifying the code in the docs. Without further ado, here's the full code.

import React, {useRef} from 'react';

import {
  Animated,
  Text,
  View,
  StyleSheet,
  TouchableOpacity,
  Dimensions,
} from 'react-native';

const windowWidth = Dimensions.get('window').width;
const windowHeight = Dimensions.get('window').height;

const TestPage = () => {
  const slideAnim = useRef(new Animated.Value(0)).current;

  const selectTab = (tabIndex) => {
    Animated.timing(slideAnim, {
      toValue: -windowWidth * tabIndex,
      duration: 300,
      useNativeDriver: true,
    }).start();
  };

  return (
    <>
      <View>
        <Animated.View
          style={{flexDirection: 'row', transform: [{translateX: slideAnim}]}}>
          <FirstTab />
          <SecondTab />
          <ThirdTab />
        </Animated.View>
      </View>

      <View style={styles.buttonRow}>
        <TouchableOpacity
          style={styles.tabButton}
          onPress={() => {
            selectTab(0);
          }}>
          <Text>One</Text>
        </TouchableOpacity>
        <TouchableOpacity
          style={styles.tabButton}
          onPress={() => {
            selectTab(1);
          }}>
          <Text>Two</Text>
        </TouchableOpacity>
        <TouchableOpacity
          style={styles.tabButton}
          onPress={() => {
            selectTab(2);
          }}>
          <Text>Three</Text>
        </TouchableOpacity>
      </View>
    </>
  );
};

const FirstTab = () => (
  <View style={styles.tabBox}>
    <Text style={styles.caption}>First Tab</Text>
    <Text style={styles.text}>
      Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed dignissim
      nulla ac mauris condimentum volutpat. In at tincidunt dolor. Pellentesque
      eu congue turpis. Integer viverra quam neque, id imperdiet dui laoreet id.
      Vestibulum dapibus velit non tortor congue scelerisque. Aliquam sed tempor
      nibh. Nam id eros in ex commodo pulvinar nec in erat. Fusce sodales eget
      felis accumsan fermentum. Aliquam a arcu mattis, consequat dui in, rhoncus
      arcu. Aenean sollicitudin semper diam eu aliquet. Donec dignissim
      fermentum feugiat. Curabitur commodo viverra elit, ut elementum nisl
      gravida vitae. Morbi lobortis luctus dictum. Fusce ornare luctus arcu sit
      amet ultrices. Donec nec ipsum in quam condimentum tempor aliquam id
      tortor. In pharetra orci non eros hendrerit dapibus. Aliquam erat
      volutpat. Nunc blandit dui id augue consequat eleifend. Phasellus et
      molestie felis, vitae accumsan mauris. Vivamus diam ligula, malesuada vel
      eros et, sodales scelerisque purus. Aenean at mi eget lectus mollis
      facilisis a vel lacus. Sed facilisis mauris nec facilisis lobortis. Donec
      augue erat, volutpat a diam a, dictum mattis eros.
    </Text>
  </View>
);

const SecondTab = () => (
  <View style={styles.tabBox}>
    <Text style={styles.caption}>Second Tab</Text>
    <Text style={styles.text}>
      Lorem Ipsum is simply dummy text of the printing and typesetting industry.
      Lorem Ipsum has been the industry's standard dummy text ever since the
      1500s, when an unknown printer took a galley of type and scrambled it to
      make a type specimen book. It has survived not only five centuries, but
      also the leap into electronic typesetting, remaining essentially
      unchanged. It was popularised in the 1960s with the release of Letraset
      sheets containing Lorem Ipsum passages, and more recently with desktop
      publishing software like Aldus PageMaker including versions of Lorem
      Ipsum.
    </Text>
  </View>
);

const ThirdTab = () => (
  <View style={styles.tabBox}>
    <Text style={styles.caption}>Third Tab</Text>
    <Text style={styles.text}>
      At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis
      praesentium voluptatum deleniti atque corrupti quos dolores et quas
      molestias excepturi sint occaecati cupiditate non provident, similique
      sunt in culpa qui officia deserunt mollitia animi, id est laborum et
      dolorum fuga. Et harum quidem rerum facilis est et expedita distinctio.
      Nam libero tempore, cum soluta nobis est eligendi optio cumque nihil
      impedit quo minus id quod maxime placeat facere possimus, omnis voluptas
      assumenda est, omnis dolor repellendus. Temporibus autem quibusdam et aut
      officiis debitis aut rerum necessitatibus saepe eveniet ut et voluptates
      repudiandae sint et molestiae non recusandae. Itaque earum rerum hic
      tenetur a sapiente delectus, ut aut reiciendis voluptatibus maiores alias
      consequatur aut perferendis doloribus asperiores repellat.
    </Text>
  </View>
);

const styles = StyleSheet.create({
  tabBox: {
    padding: 10,
    backgroundColor: '#ffe8',
    height: windowHeight,
  },
  caption: {
    fontSize: 28,
    textAlign: 'center',
    margin: 10,
  },
  buttonRow: {
    flexDirection: 'row',
    position: 'absolute',
    bottom: 0,
  },
  tabButton: {
    padding: 15,
    backgroundColor: '#fff',
    flex: 1,
    margin: 1,
    width: 100,
    justifyContent: 'center',
    alignItems: 'center',
  },
  text: {
    textAlign: 'justify',
  },
});

export default TestPage;

See it on Snack here - https://snack.expo.io/pi0WJYfSN

The great thing is, because we're translating by a value of windowWidth * tabIndex every time, it's completely dynamic. So you could have as many or as few tabs here as possible, and everything will still work.

Posted on by:

debadeepsen profile

debadeepsen

@debadeepsen

Full-stack software engineer, experienced in .NET, PHP, Node JS, Angular, Vue, React, and React Native. Master's Degree in Computer Science with focus on HCI. Lover of coffee, videogames, and cats.

Discussion

pic
Editor guide