【问题标题】:React Native: Setting flex:1 on a ScrollView contentContainerStyle causes overlapping of componentsReact Native:在 ScrollView contentContainerStyle 上设置 flex:1 会导致组件重叠
【发布时间】:2016-02-13 23:23:52
【问题描述】:

问题:

我有一个带有 2 个子视图的 ScrollView,我希望它们中的第一个(让我们称之为 ViewA)具有 {flex: 1} 以便另一个(ViewB)将粘在屏幕底部 - 但前提是它们的总高度小于屏幕。当然,如果它们高于屏幕,我希望它像往常一样滚动。

案例 1 (GOOD):ViewA 带有长文本,ViewB 随之滚动。 https://rnplay.org/apps/slCivA

案例 2 (BAD):ViewA 带有短文本,ViewB 不粘在底部。 https://rnplay.org/apps/OmQakQ

尝试过的解决方案:

所以我将 ScrollView 的样式和 contentContainerStyle 设置为 flex: 1. I 还将 ViewA 的样式设置为 flex:1。但是当我这样做时,ScrollView 的 contentContainer 视图被固定到屏幕高度,因此在需要时无法滚动,甚至更糟 - ViewB 与 ViewA 重叠。

案例 3 (BAD):ViewB 粘在底部,但整个东西没有滚动。 https://rnplay.org/apps/wZgtWA

如果这是一个错误 - 如何修复/解决它? 如果这是预期的行为 - 我怎样才能实现我所描述的?

谢谢。

【问题讨论】:

  • 你能复制这个问题,或者在rnplay.org 上设置一个例子吗?谢谢。
  • 是的 - 这里是:rnplay.org/apps/wZgtWA。请注意,即使没有 ViewB,一旦在 contentContainerStyle 上设置了flex:1,您就无法滚动页面。

标签: ios flexbox react-native


【解决方案1】:

好的,我已经制作了一个示例here,我想我已经解决了这个问题。我做的主要事情是制作一个包含两个内部视图的主容器视图,然后将内部视图设置为 80% 和 20%(您可以调整以使其看起来像您想要的那样)。

https://rnplay.org/apps/O4UxFA

【讨论】:

  • 感谢您的回答 :) 我想我还不够清楚 - 我希望 viewB 在需要时与 viewA 一起滚动。我只希望它在 ViewA+ViewB 的高度小于屏幕大小时粘住。 ViewB 应该在 ScrollView 里面,但是如果内容比屏幕小,我希望它贴在底部。
  • 要完成我认为您的想法,您可能需要根据视图中发生的各种不同情况进行一些计算,并在滚动时重新渲染。看看github.com/facebook/react-native/blob/master/Libraries/ReactIOS/…。这将让您测量元素。然后您可能需要使用Dimensions 或React Native Device (npmjs.com/package/react-native-device) 等计算视图高度并动态设置样式。
  • 谢谢,我正在这样做,并设法得到一个可以接受的结果。但它太乱了,我想也许这只是一个错误或什么的。
【解决方案2】:

好的,所以我无法通过单独的样式让它工作,但我是这样做的:

  1. 在渲染后测量页脚的高度(使用onLayoutmeasure
  2. measure 回调中,我将高度(如果需要)添加到 ViewA 和 ViewB 之间的间隔视图中,以便将 ViewB 放在底部。
  3. 为了避免向用户显示“跳转”,我隐藏(不透明)ViewB 直到其位置固定。

我的 CJSX 代码(精简版和简化版):

Dimensions = require('Dimensions')
windowSize = Dimensions.get('window')

MyClass = React.createClass
  mixins: [TimerMixin]

  render: ->
    <ScrollView style={styles.container} automaticallyAdjustContentInsets={false}>
      <View style={styles.mainContainer}>
        ... THIS IS VIEW A ...      
      </View>
      {
        if !@state.footerWasFixed
          <View>
            <ActivityIndicatorIOS/>
          </View>
      }
      <View style={[styles.spacer, {height: @state.spacerSize || 0}]}></View>
      <View onLayout={@measureFooterPosition} style={[styles.extras, {opacity: if @state.footerWasFixed then 1 else 0 }]} ref='extras'>
        ... THIS IS VIEW B ...       
      </View>
    </ScrollView>


  measureFooterPosition: ->
    @refs.extras.measure(@fixFooterPosition)

  fixFooterPosition: (ox, oy, width, height) ->
    footerPosition = Math.round(oy + height)
    diff = windowSize.height - footerPosition
    if diff > 0
      @setState(spacerSize: diff)
    if !@state.footerWasFixed
      @setTimeout (=>
        @setState(footerWasFixed: true)
      ), 30

styles = StyleSheet.create(
  container:
    backgroundColor: 'grey'
    flex: 1
  spacer:
    backgroundColor: 'white'
  mainContainer:
    flex: 1
    backgroundColor: 'white'
  extras:
    backgroundColor: 'white')

这是非常简化的代码,(我的观点有比这个更具体的要求......)但我希望它可以帮助任何人。

【讨论】:

  • 与下面的柯林斯回答相比,这非常做作。仅发表评论,以便人们继续滚动。
【解决方案3】:

尝试将 {flexGrow: 1} 输入到 contentContainerStyle 属性

【讨论】:

  • 这应该是答案
  • 这对我有用,但我使用 flex: 1 而不是 flexGrow
  • 谢谢!比flex: 1 更好,因为 ScrollView 变得可滚动
猜你喜欢
  • 1970-01-01
  • 2018-03-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-11-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多