React Native弹性盒子未使用所有可用空间

18

我有一个布局,希望将其全屏。它现在是这个样子:enter image description here

我想要的是布局占据整个屏幕空间(所以提交按钮应该在底部)。我正在尝试使用 {flex: 1},但它不起作用。以下是代码:

'use strict';

const React = require('react-native');
const {
  StyleSheet,
  Text,
  View,
  BackAndroid,
  TextInput,
  TouchableNativeFeedback,
  ScrollView
} = React;

const ActionButton = require('./action-button');

module.exports = React.createClass({
  handleBackButtonPress () {
    if (this.props.navigator) {
      this.props.navigator.pop();
      return true;
    }

    return false;
  },

  componentWillMount () {
    BackAndroid.addEventListener('hardwareBackPress', this.handleBackButtonPress);
  },

  componentWillUnmount () {
    BackAndroid.removeEventListener('hardwareBackPress', this.handleBackButtonPress);
  },

  onInputFocus (refName) {
    setTimeout(() => {
      let scrollResponder = this.refs.scrollView.getScrollResponder();
      scrollResponder.scrollResponderScrollNativeHandleToKeyboard(
        React.findNodeHandle(this.refs[refName]),
        0,
        true
      );
    }, 50);
  },

  render: function() {
    return (
      <ScrollView ref='scrollView' style={styles.scroller}>
        <View style={styles.container}>
          <View style={styles.header}>
            <Text>New Post</Text>

              <View style={styles.actions}>
                <ActionButton handler={this.handleBackButtonPress} icon={'fontawesome|close'}
                  size={15} width={15} height={15} />
              </View>
          </View>
          <View style={styles.content}>
            <TextInput underlineColorAndroid={'white'}
              placeholder={'Who\'s your professor?'}
              ref='professor'
              onFocus={this.onInputFocus.bind(this, 'professor')}
              style={styles.professor}
              />

            <TextInput multiline={true}
              underlineColorAndroid={'white'}
              placeholder={'What do you think?'}
              ref='post'
              onFocus={this.onInputFocus.bind(this, 'post')}
              style={styles.post}
              />
          </View>
          <View style={styles.footer}>
            <TouchableNativeFeedback
              background={TouchableNativeFeedback.SelectableBackground()}>

              <View style={{width: 50, height: 25, backgroundColor: 'green'}}>
                <Text>Submit</Text>
              </View>
            </TouchableNativeFeedback>
          </View>
        </View>
      </ScrollView>
    );
  }
});

const styles = StyleSheet.create({
  scroller: {
    flex: 1,
    flexDirection: 'column'
  },
  container: {
    flex: 1,
    flexDirection: 'column',
    justifyContent: 'flex-start',
    backgroundColor: 'white',
    padding: 5,
  },
  post: {
    flex: 3
  },
  professor: {
    flex: 1
  },
  actions: {
    flex: 1,
    flexDirection: 'row',
    justifyContent: 'flex-end',
    alignSelf: 'center'
  },
  header: {
    flex: 1,
    padding: 5,
    flexDirection: 'row'
  },
  content: {
    flex: 4
  },
  footer: {
    flex: 1
  }
});

从我所看到的情况来看,我将flex属性设置所有的视图层级,但仍然没有任何效果(在顶层是一个带有{flex: 1}的导航器)。有什么建议吗?


你是否把这个视图放在另一个容器中了? - Aakash Sigdel
3个回答

21

你需要的是ScrollView组件的contentContainerStyle属性。如果你将这段代码替换为:

<ScrollView ref='scrollView' style={styles.scroller}>

和:

<ScrollView ref='scrollView' contentContainerStyle={styles.scroller}>

那将解决你的问题。

文档中所述

这些样式将被应用于滚动视图内容容器,该容器包裹所有子视图。

希望能帮到你!


1
这立刻解决了我的问题。但是,当内容超出视图底部时,它会使ScrollView停止滚动,因此基本上通过将style更改为contentContainerStyle将其转换为<View />。我尝试同时使用两者,但也没有按预期工作。 - agm1984
3
一样。这不适用于RN 0.48/Expo 21.0。编辑,似乎这个可以:contentContainerStyle={{ flexGrow: 1 }} - FMCorz
使用contentContainerStyle={{flexGrow:1}}对我也起到了作用。谢谢! - Thomas P.

1
如果屏幕截图中的颜色准确无误,那么您的滚动视图已经占据了所有垂直空间,但容器并没有(容器背景颜色为白色)。这说明了滚动视图的工作原理。它们充当容器,在其中flex无法真正使子元素适应垂直空间,因为它可能是无限的。相反,子元素以其自然高度呈现。http://devdocs.io/react_native/scrollview 尝试改用占据整个屏幕高度的视图。
<View style={styles.container}>
  ... components here ...
</View>
const styles = StyleSheet.create({
  container: {
    flex: 1,
    flexDirection: 'column',
    justifyContent: 'space-between'
  }
})

0
你需要为最外层容器设置flexDirection: 'row'属性:
scroller: {
  flex:1,
  flexDirection: 'row'
}

我已经设置了你的应用程序的基本版本在这里。其余的代码如下,以获得完整的工作示例:

https://rnplay.org/apps/gjBqgw

'use strict';

var React = require('react-native');
var {
  StyleSheet,
  Text,
  View,
  BackAndroid,
  TextInput,
  TouchableNativeFeedback,
  ScrollView,
  AppRegistry,
  TouchableHighlight
} = React;

var SampleApp = React.createClass({
   render: function() {
    return (
      <ScrollView ref='scrollView' style={styles.scroller}>
        <View style={styles.container}>
          <View style={styles.header}>
            <Text>New Post</Text>

              <View style={styles.actions}>
                <TouchableHighlight handler={this.handleBackButtonPress} icon={'fontawesome|close'}
                  size={15} width={15} height={15}>
                            <Text>Button Text</Text>
                        </TouchableHighlight>
              </View>
          </View>
          <View style={styles.content}>
           <Text>Hello from content</Text>
          </View>
          <View style={styles.footer}>
            <TouchableHighlight>

              <View style={{width: 50, height: 25, backgroundColor: 'green'}}>
                <Text>Submit</Text>
              </View>
            </TouchableHighlight>
          </View>
        </View>
      </ScrollView>
    );

  }
});

const styles = StyleSheet.create({
  scroller: {
    flex:1,
    flexDirection: 'row'
  },
  container: {
    flex: 1,
    backgroundColor: 'white',
    padding: 5,
  },
  post: {
    flex: 3
  },
  professor: {
    flex: 1
  },
  actions: {
    flex: 1,
    flexDirection: 'row',
    alignSelf: 'center'
  },
  header: {
    flex: 1,
    padding: 5,
    flexDirection: 'row'
  },
  content: {
    flex: 4
  },
  footer: {
    flex: 1,
  }
});

AppRegistry.registerComponent('SampleApp', () => SampleApp);

为什么将flex-direction设置为行可以解决问题?这不会使主轴左右排列吗?而使用flex:1会在水平方向上占用整个可用空间吗?@nader-dabit - Aakash Sigdel
我尝试了你的建议,但它只是让内容消失了。 - Hugo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接