skip to Main Content

Inverted Flatlist that contains absolute positioned elements doesn’t seem to allow the absolute positioned elements to overlay previous components / items. Instead, they’re forced underneath the previous component. I would like for the absolute positioned elements to render on top of the previous components.

Reproducible code samples:

List Container:

const MessageList = () => {
  const messages = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
  const renderItem = ({ item, index }) => {
    return (
      <Message isLast={index === 0} />
    )
  }

  return (
    <FlatList
      data={messages}
      inverted
      style={{ flex: 1, paddingHorizontal: 16, paddingBottom: 16 }}
      renderItem={renderItem}
      ItemSeparatorComponent={() => <View style={{ marginVertical: 6 }} />}
    />
  )
}

export default MessageList

Message:

const Message = ({ ... }) => {
  return (
    <View>
      <Text style={{ backgroundColor: 'green', padding: 20 }}>Message here</Text>
      {
        isLast
          ? (
              <View style={{ backgroundColor: 'orange', position: 'absolute', bottom: 40, left: 0, right: 0, top: -20, zIndex: 20 }}>
                <Text>Absolute Positioned</Text>
              </View>

            )
          : null
      }
    </View>
  )
}

Result attached as image:
Incorrectly overlayed element

2

Answers


  1. Chosen as BEST ANSWER

    I was able to solve this by making use of the CellRendererComponent prop. I was left with the following:

    const MessageList = () => {
      const messages = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
      const renderItem = ({ item, index }) => {
        return (
          <Message isLast={index === 0} />
        )
      }
    
      const renderCell = (props, index) => {
        return (
          <View style={[props.style, { zIndex: messages.length - props.index }]}>
            {props.children}
          </View>
        )
      }
    
      return (
        <FlatList
          data={messages}
          inverted
          style={{ flex: 1, paddingHorizontal: 16, paddingBottom: 16 }}
          renderItem={renderItem}
          ItemSeparatorComponent={() => <View style={{ marginVertical: 6 }} />}
          CellRendererComponent={renderCell}
        />
      )
    }
    

    which resulted in the following image: Results


  2. Old Answer:

    You have to change the z-index of the containing <View> element, not the child one. You also need to set the containing element to have position: relative so that z-index will work.

    New Answer:

    Okay, I made a code sandbox at https://codesandbox.io/s/frosty-lederberg-4wlw8p?file=/src/App.js and figured out that the FlatList is creating a wrapper around each individual list item, so you need to affect the style of those wrappers. This is the code I changed:

      return (
        <div className={"my-container"} style={{ overflow: "scroll" }}>
          <FlatList
            data={messages}
            inverted
            style={{ flex: 1, paddingHorizontal: 16, paddingBottom: 16 }}
            renderItem={renderItem}
            ItemSeparatorComponent={() => <View style={{ marginVertical: 6 }} />}
          />
        </div>
      );
    

    and you’ll need this css

      .my-container > * > * > *:first-child {
        z-index: 20;
      }
    

    Final result: Absolute positioned FlatList item

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search