maxi hraschan
maxi hraschan

Reputation: 300

Expo - Nested horizontal Flatlist dynamic height

I'm currently developing a list with exercises. A new feature should be that a certain exercise can have replacements.

All exercises are displayed in a flatList vertically.

The replacements of an exercise should be displayed horizontal. That works fine.

Issue:

Each exercise can have a different amount of sets that are listed. As you can see below. When the user is scrolling horizontally the height of the nested FlatList doesn't change accordingly.

Working vertical list

Not working horizontal list

WorkoutExerciseList (Vertical scroll flatlist)

  const renderItem = useCallback(
    ({
      item,
      drag,
      isActive,
    }: RenderItemParams<WorkoutExercise | WorkoutExercise[]>) => {
      if (Array.isArray(item) && item.length >= 2) {
        return (
          <ReplacementExercisesList
            items={item}
            drag={drag}
            displaySetFinishedHeaderIcon={displaySetFinishedHeaderIcon}
          />
        );
      } else if (Array.isArray(item)) {
        return (
          <WorkoutExercisesListItem
            {...item[0]}
            drag={drag}
            displaySetFinishedHeaderIcon={displaySetFinishedHeaderIcon}
          />
        );
      } else {
        return (
          <WorkoutExercisesListItem
            {...item}
            drag={drag}
            displaySetFinishedHeaderIcon={displaySetFinishedHeaderIcon}
          />
        );
      }
    },
    []
  );

 <DraggableFlatList
      contentContainerStyle={{
        // flexGrow: 1,
        // flex: 1,
        paddingBottom: 160,
      }}
      keyboardShouldPersistTaps="handled"
      // style={{ flex: 1 }}
      data={workoutExercises}
      onDragEnd={onDragEnd}
      renderItem={renderItem}
      keyExtractor={(item) => {
        if (Array.isArray(item)) {
          return item[0].id;
        } else {
          return item.id;
        }
      }}
    />

ReplacementExerciseList - Horizontal scroll

 <Animated.FlatList
        data={items}
        ref={ref}
        // contentContainerStyle={{ flexGrow: 1 }}
        renderItem={({ item, index }) => (
          <WorkoutExercisesListItem
            drag={drag}
            {...item}
            index={index}
            displaySetFinishedHeaderIcon={displaySetFinishedHeaderIcon}
            isReplacementExercise={true}
            computeHeight={computeListHeight}
          />
        )}
        scrollEnabled={false}
        // onViewableItemsChanged={handleVieweableItemsChanged}
        scrollEventThrottle={32}
        keyExtractor={(item) => item.id}
        horizontal={true}
        initialScrollIndex={activeIndex}
        showsHorizontalScrollIndicator={false}
        bounces={false}
        pagingEnabled={true}
      />

I tried to calculate the height of each item in the ReplacementExerciseList (Horizontal) and set a dynamic height for the list, whenever the active horizontal index changes. But this ends up in an Error: enter image description here

Upvotes: 0

Views: 276

Answers (2)

maxi hraschan
maxi hraschan

Reputation: 300

I removed the second horizontal flatList. Instead i render only ONE list item. When the user is switching to another item i will set a new index. The item always renders the data of the selected index:

  const onSelectReplacementExercise = useCallback((itemIndex: any) => {
    console.log("itemIndex", itemIndex);
    LayoutAnimation.easeInEaseOut();
    setActiveIndex(itemIndex);
  }, []);

 <WorkoutExercisesListItem
        {...items[activeIndex]}
        displaySetFinishedHeaderIcon={displaySetFinishedHeaderIcon}
        isReplacementExercise={true}
      />

onSelectReplacementExercise is called by my switch menu.

Upvotes: 0

Waheed Akhtar
Waheed Akhtar

Reputation: 3187

You can use minHeight and flexGrow: 0 (here you can find) to handle dynamic height but I would recommend using RecyclerView as this have better options for dynamic height plus better performance with dynamic sizings.

Upvotes: 1

Related Questions