'ScrollView clips Touchable Opacity with absolute positioning

I am new to React Native with my first project. Currently I am dealing with a problem that my KeyboardAvoidingScrollView clips TouchableOpacity that is being triggered from a child component. I am doing this to display sort of a backdrop on the items that are note currently opened.

Here's my code also with some visual examples of what my problem looks like:

This is my "App.js" file:

import React from 'react';
import type {Node} from 'react';
import {StyleSheet, SafeAreaView, View} from 'react-native';
import {KeyboardAwareScrollView} from 'react-native-keyboard-aware-scroll-view';
import ToDoItem from './components/ToDoItem';

const App: () => Node = () => {
  return (
    <KeyboardAwareScrollView style={styles.scrollView} removeClippedSubviews>
      <SafeAreaView>
        <ToDoItem />
        <ToDoItem />
        <ToDoItem />
        <ToDoItem />
        <ToDoItem />
        <ToDoItem />
      </SafeAreaView>
    </KeyboardAwareScrollView>
  );
};

// Native styling
const styles = StyleSheet.create({
  container: {
    flex: 1,
  },
  scrollView: {
    flex: 1,
    width: '100%',
    backgroundColor: 'red',
  },
});

export default App;

Here below you can see my ToDoItem.js component:

import React from 'react';
import {useState} from 'react';
import type {Node} from 'react';
import {StyleSheet, TouchableOpacity, TextInput, Pressable} from 'react-native';
import {MotiView, useAnimationState} from 'moti';
import ToDoCheckbox from './ToDoCheckbox.js';

const ToDoItem: () => Node = () => {
  const [label, setLabel] = useState('Useless task');
  const [open, setOpen] = useState(false);
  const [description, setDescription] = useState('');

  // Animation states
  const animateItemContainer = useAnimationState({
    from: {
      minHeight: 56,
      marginTop: 0,
      marginBottom: 0,
      borderRadius: 16,
    },
    to: {
      minHeight: 56,
      marginTop: 0,
      marginBottom: 0,
      borderRadius: 16,
    },
    expanded: {
      minHeight: 200,
      marginTop: 8,
      marginBottom: 8,
      borderRadius: 0,
    },
  });

  const animateMainContainer = useAnimationState({
    from: {
      paddingTop: 6,
      paddingBottom: 6,
      paddingLeft: 16,
      paddingRight: 16,
      zIndex: 0,
    },
    to: {
      paddingTop: 6,
      paddingBottom: 6,
      paddingLeft: 16,
      paddingRight: 16,
      zIndex: 0,
    },
    expanded: {
      paddingLeft: 0,
      paddingRight: 0,
      zIndex: 2,
    },
  });

  // Open handler
  const handleOpen = () => {
    setOpen(true);
    animateItemContainer.transitionTo('expanded');
    animateMainContainer.transitionTo('expanded');
  };

  // Close handler
  const handleClose = () => {
    setOpen(false);
    animateItemContainer.transitionTo('to');
    animateMainContainer.transitionTo('to');
  };

  return (
    <React.Fragment>
      {open && (
        <TouchableOpacity style={styles.backdrop} onPress={handleClose} />
      )}
      <MotiView state={animateMainContainer}>
        <MotiView
          style={styles.itemContainer}
          state={animateItemContainer}
          transition={{
            type: 'spring',
            stiffness: 300,
            damping: 25,
          }}>
          <Pressable onPress={handleOpen} style={styles.labelContainer}>
            <ToDoCheckbox />
            <TextInput
              style={styles.labelInput}
              onChangeText={setLabel}
              onFocus={handleOpen}
              value={label}
              placeholder="Enter to-do label"
            />
          </Pressable>
          {open && (
            <MotiView
              style={styles.descriptionContainer}
              from={{
                top: -25,
                opacity: 0,
              }}
              animate={{
                top: 0,
                opacity: 1,
              }}
              transition={{
                type: 'spring',
                stiffness: 200,
                damping: 25,
              }}>
              <TextInput
                multiline
                style={styles.descriptionInput}
                onChangeText={setDescription}
                value={description}
                placeholder="Enter description"
              />
            </MotiView>
          )}
        </MotiView>
      </MotiView>
    </React.Fragment>
  );
};

// Native styling
const styles = StyleSheet.create({
  backdrop: {
    position: 'absolute',
    top: 0,
    bottom: 0,
    left: 0,
    right: 0,
    backgroundColor: 'rgba(0, 0, 0, 0.15)',
    zIndex: 1,
  },

  itemContainer: {
    overflow: 'hidden',
    width: '100%',
    backgroundColor: '#fff',
  },

  labelContainer: {
    display: 'flex',
    alignItems: 'center',
    flexDirection: 'row',
  },

  labelInput: {
    display: 'flex',
    width: '50%',
    color: 'black',
    fontSize: 16,
    fontWeight: '400',
  },

  descriptionContainer: {
    paddingLeft: 56,
    paddingRight: 24,
    paddingBottom: 24,
  },

  descriptionInput: {
    width: '100%',
    color: 'black',
    fontSize: 16,
    fontWeight: '400',
  },
});

export default ToDoItem;

enter image description here



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source