Макет Flex с ScrollView

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

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

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

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

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

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

3
0
2 567
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

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

      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

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

Обратите внимание, что я уже заявлял, что изменение гибкости верхнего и нижнего колонтитула на десятичные дроби работает, но я хотел предотвратить это, потому что это очень утомительно. Было бы хорошо узнать, почему он так себя ведет с ScrollView.

Franch 31.07.2018 22:10

@Franch Теперь я понимаю ваш вопрос ... Это потому, что ScrollView не может самостоятельно определять свой размер (это особенность ScrollView, всегда имеет flex: 1). Он должен дождаться, пока другие компоненты выберут свой захват (1, 3, 0,33 ...), а затем scrollView сделает все остальное!

Mr L 31.07.2018 23:52
Ответ принят как подходящий

Обновление 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 в обычном режиме (то есть с использованием целочисленных значений гибкости, как предполагалось в первую очередь) с помощью упаковка ScrollView внутри представления с flex: 1.

Обратной стороной является то, что если я установил для раздела «Прокручиваемый» (контент) достаточно высокое значение гибкости, чтобы его больше нельзя было прокручивать, контент не отображается по центру. Даже если применяется justifyContent: 'center'.

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

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