javascriptcssreactjsreact-native

React Native - TouchableOpacity not working on container with position: absolute


I have a animated SafeAreaView with 2 buttons inside it, the view have position: absolute. When I click the button it pass through it, and hits the elements behind de button. I'm currently using zIndex and elevation, and tried a lot of solutions found here on Stack Overflow, such as:

If I use position: relative in the parent container, the button works.

Here is my code, the Button component is the styled TouchableOpacity, I also tried removing the wrappers, changing the main container to TouchableOpacity instead of SafeAreaView, but nothing...

return (
    <Wrapper
      isAndroid={Platform.OS === 'android'}
      style={{
        transform: [
          {
            translateY: translateValue.interpolate({
              inputRange: [0, 1],
              outputRange: [500, 0]
            })
          }
        ]
      }}>
      <ButtonsWrapper>
        <ActionButton
          inverted
          secondary
          onPress={() => {
            console.log('teste');
          }}
          accessible
          accessibilityLabel="Continuar com Facebook">
          <Icon name="edit" secondary size={20} />
          <BtnText bold noPadding secondary>
            Editar
          </BtnText>
        </ActionButton>
        <ActionButton
          inverted
          primary
          onPress={() => {
            console.log('teste');
          }}
          accessible
          accessibilityLabel="Continuar com Facebook">
          <Icon name="x-circle" primary size={20} />
          <BtnText bold noPadding primary>
            Encerrar
          </BtnText>
        </ActionButton>
      </ButtonsWrapper>
    </Wrapper>
  );
});

const Wrapper = Animated.createAnimatedComponent(styled.SafeAreaView`
  width: 100%;
  border-top-width: 1px;
  border-top-color: ${({ theme: { border } }) => border};
  background: ${({ theme: { background } }) => background};
  z-index: 1;
  position: absolute;
  flex-direction: row;
  justify-content: space-between;
  align-items: center;
  bottom: 0;
  left: 0;
  ${({ isAndroid }) => isAndroid && 'elevation: 1'}
  height: 150px;
`);

const ButtonsWrapper = styled.View`
  flex: 1;
  align-items: center;
  justify-content: center;
  padding: 10px;
`;

const ActionButton = styled(Button)``;

const BtnText = styled(Text)`
  padding-right: 20px;
  flex: 1;
  text-align: center;

  ${({ noPadding }) =>
    noPadding &&
    `
      padding: 0px;
  `}
`;


Solution

  • I just found the problem, in my App.js I just changed the order of the components. The Alert component was placed before de NavigationContainer, placing after the NavigationContainer it worked as expected.

    Before:

    export const App = () => (
      <>
        <StatusBar backgroundColor={theme.background} barStyle="dark-content" />
        <ThemeProvider theme={theme}>
          <Provider store={store}>
            <PersistGate loading={null} persistor={persistor}>
              <Alert />
              <Socket>
                <NavigationContainer>
                  {...}
                </NavigationContainer>            
              </Socket>
            </PersistGate>
          </Provider>
        </ThemeProvider>
      </>
    );

    After:

    export const App = () => (
      <>
        <StatusBar backgroundColor={theme.background} barStyle="dark-content" />
        <ThemeProvider theme={theme}>
          <Provider store={store}>
            <PersistGate loading={null} persistor={persistor}>          
              <Socket>
                <NavigationContainer>
                  {...}
                </NavigationContainer>            
                <Alert />
              </Socket>
            </PersistGate>
          </Provider>
        </ThemeProvider>
      </>
    );

    That was it :)