Flex макет с ScrollView

Некоторое время назад я делал макеты для экранов в React Native с Flexbox и не столкнулся с какими-либо проблемами до сегодняшнего дня, когда мне нужно было сделать этот очень простой макет:

  • Раздел заголовка (не NavBar).
  • Раздел содержимого → ScrollView с плоским списком внутри него.
  • Раздел нижнего колонтитула.

Я хочу, чтобы раздел содержимого был в 3 раза больше, чем верхний и нижний колонтитулы, поэтому, естественно, я установил flex на 1 (верхний колонтитул), 3 (контентный), 1 (нижний колонтитул).

Независимо от того, что содержимое остается, как будто оно имеет flex: 1,
Единственный способ, которым я мог управлять макетом так, как я хотел, это оставить контент flex: 1 и установите нижний колонтитул и заголовок в flex: 0.33,

Я подозреваю, что это может быть как-то связано с реквизитом ScrollView's contentContainerStyle, который я установил в flexGrow: 1, flexShrink: 1,

Вот минимальный пример, который воспроизводит это.

2 ответа

Решение

Обновление 2:

Мне было указано, что я не должен использовать ListView, заключенный в ScrollView, поскольку может произойти следующее:

  • Это может привести к некоторым странным поведениям, таким как onEndReached стрельба непрерывно.

  • Обтекание ListView внутри ScrollView заставляет родительское действие прокрутки доминировать над дочерним действием прокрутки, которое приводит только к прокрутке ScrollView.


Хорошо, я не уверен, почему это работает, но нашел решение после нескольких часов попыток:

После шага, упомянутого в обновлении 1, я добавил следующий стиль flexGrow: 0 к FlatList внутри ScrollView, и контент стал центрированным и уменьшал размер контента, пока он не стал прокручиваемым, работает также отлично.

В основном это результирующий код:

render() {
    return (
      <View style={{ flex: 1 }}>
        <View style={{ flex: 1 }}>
          <Text>HEADER</Text>
        </View>
        <View style={{ flex: 6 }}>  // Change this to affect ScrollView size
          <ScrollView contentContainerStyle={{ flexGrow: 1, justifyContent: 'center' }}>
            <FlatList
              data={listItems}
              renderItem={Item}
              keyExtractor={(index, item) => item}
              style={{ flexGrow: 0 }}  // This was the solution to centering
            />
          </ScrollView>
        </View>
        <View style={{ flex: 1 }}>
          <Text>FOOTER</Text>
        </View>
      </View>
    );
  }

Вот окончательное рабочее решение, если вы хотите попробовать его.


Обновление 1:

Управляется размером ScrollView с помощью Flex в обычном режиме (то есть с использованием целочисленных значений flex, как и предполагалось вначале), оборачивая ScrollView внутри View с помощью flex: 1,

Недостатком является то, что если я устанавливаю секцию Scrollable (контент) на достаточно высокое значение flex, чтобы он больше не прокручивался, контент не отображается по центру. Даже если justifyContent: 'center' применены.

Вот пример ОБНОВЛЕНИЕ 1.

С минимальными изменениями это работает для меня, я использовал этот стиль:

      const styles = StyleSheet.create({
    screen: {
      backgroundColor: 'lightgray',
      flex: 1,
    },
    header: {
      flex: 0.33,
      backgroundColor: 'lightblue',
      justifyContent: 'center',
      alignItems: 'center',
    },
    scrollView: {
      flex: 1,
    },
    footer: {
      backgroundColor: 'lightpink',
      flex: 0.33,
      alignItems: 'center',
      justifyContent: 'center',
    },
  });

Полный код >>> https://snack.expo.io/Hk9tbHR4Q

Это результат:

Другие вопросы по тегам