Search code examples
reactjsreact-nativereact-animated

How can we make an animated strike through on react native text?


I have a todo list, each list item has a check box. When I check the box, an animated strike-through effect should show from left to right. How to do that?


Solution

  • Unfortunately, you can't animate strike directly but I used some tricks to achieve the same effect.

    import React from 'react';
    import { Animated, Easing, Text, View, StyleSheet } from 'react-native';
    
    export default function App() {
      const ref = React.useRef(View.prototype);
      const animatedValue = React.useRef(new Animated.Value(0)).current;
    
      const [textWidth, setTextWidth] = React.useState(0);
      const [textHeight, setTextHeight] = React.useState(0);
    
      React.useEffect(() => {
        ref.current.measure((x, y, w, h) => {
          setTextWidth(w);
          setTextHeight(h);
          animateStrike();
        });
      }, []);
    
      const animateStrike = () => {
        Animated.timing(animatedValue, {
          toValue: 1,
          duration: 2000,
          easing: Easing.linear,
          useNativeDriver: false,
        }).start();
      };
    
      const strikeWidth = animatedValue.interpolate({
        inputRange: [0, 1],
        outputRange: [0, textWidth],
        extrapolate: 'clamp',
      });
    
      return (
        <View style={styles.container}>
          <View>
            <Text style={styles.text} ref={ref}>
              Some Dummy Text
            </Text>
            <Animated.View
              style={[
                styles.strike,
                { width: strikeWidth, top: textHeight / 2 + 1 },
              ]}
            />
          </View>
        </View>
      );
    }
    
    const styles = StyleSheet.create({
      container: {
        flex: 1,
        justifyContent: 'center',
        alignItems: 'center',
      },
      text: {
        fontSize: 20,
        fontWeight: '400',
      },
      strike: {
        position: 'absolute',
        height: 2,
        backgroundColor: 'red',
      },
    });
    

    You can check the demo here.