react native facebook message gradient effect

237 Views Asked by At

I want to developer the bubble with gradient effect like facebook, I tried to set background as linearGradient, then playaround with the bubble background. As the image below: enter image description here

I tried to set a parent of bubble view background color = `white', then bubble background = 'transparent' but not working. Can someone give me some advices?

Here is the exactly what I want to do https://cuong-le.medium.com/recreating-the-facebook-messenger-gradient-effect-52a1b17c0c3f

1

There are 1 best solutions below

1
Harsh Patel On

Try this:

import React from 'react';
import {
  FlatList,
  StatusBar,
  SafeAreaView,
  StyleSheet,
  Text,
  View,
  Dimensions,
  Animated,
} from 'react-native';
import MaskedView from '@react-native-masked-view/masked-view';
import { LinearGradient } from 'expo-linear-gradient';

const { width, height } = Dimensions.get('window');
const AnimatedLinearGradient = Animated.createAnimatedComponent(LinearGradient);

const data = [
  {
    key: 1,
    text: 'Hi',
    isOwnMsg: true,
  },
...
  ];

export default App = () => {
  const [dimension, setDimension] = React.useState({ height });
  const scrollY = React.useRef(new Animated.Value(0)).current;
  return (
    <SafeAreaView>
      <Animated.ScrollView
        style={{ backgroundColor: 'transparent' }}
        onScroll={Animated.event(
          [{ nativeEvent: { contentOffset: { y: scrollY } } }],
          { useNativeDriver: true }
        )}>
        <StatusBar hidden={true} />
        <MaskedView
          maskElement={
            <View
              onLayout={(ev) => setDimension(ev.nativeEvent.layout)}
              style={{ backgroundColor: 'transparent' }}>
              {data.map((item) => (
                <View
                  key={item.key}
                  style={[
                    styles.singleMsg,
                    {
                      backgroundColor: 'red', // Important to apply the gradient effect as a mask
                      alignSelf: item.isOwnMsg ? 'flex-end' : 'flex-start',
                    },
                  ]}>
                  <Text style={{ opacity: 0 }}>{item.text}</Text>
                </View>
              ))}
            </View>
          }>
          <View style={{ height: dimension.height }}>
            <FlatList
              scrollEnabled={false}
              data={data}
              keyExtractor={(item) => item.key}
              style={[StyleSheet.absoluteFillObject, { zIndex: 1 }]}
              removeClippedSubviews={false}
              renderItem={({ item }) => {
                return (
                  <View
                    style={[
                      styles.singleMsg,
                      {
                        zIndex: item.isOwnMsg ? -1 : 1, // only display the other messages above the gradient mask, we want to avoid gradient being applied to the other message other than own.
                        backgroundColor: item.isOwnMsg
                          ? 'transparent'
                          : '#E4E7EB', // remove the background for my messages because we're using the gradient mask
                        alignSelf: item.isOwnMsg ? 'flex-end' : 'flex-start',
                      },
                    ]}>
                    <Text
                      style={{ color: item.isOwnMsg ? 'white' : '#111927' }}>
                      {item.text}
                    </Text>
                  </View>
                );
              }}
            />
            <AnimatedLinearGradient
              style={{
                height,
                transform: [
                  {
                    translateY: scrollY,
                  },
                ],
              }}
              colors={['#feda75', '#fa7e1e', '#d62976', '#962fbf', '#4f5bd5']}
            />
          </View>
        </MaskedView>
      </Animated.ScrollView>
    </SafeAreaView>
  );
};

const styles = StyleSheet.create({
  singleMsg: {
    paddingHorizontal: 20,
    paddingVertical: 12,
    margin: 12,
    marginBottom: 8,
    borderRadius: 12,
    maxWidth: width * 0.65,
  },
});

Explanation:

Animated.ScrollView component is used to scroll the messages.

MaskedView component is used to create a mask for the gradient.

FlatList component is used to render the messages.

AnimatedLinearGradient component is used to create the gradient.

Source: check

Working Code: Expo Demo