我们可以在react-native中设置组件的内容优先级吗?

时间:2016-01-25 16:54:48

标签: ios flexbox react-native

在AutoLayout中,我们可以根据约束排列多个视图,例如,如果我将UILabel和UIImageView放在一行中,我可以这样做:

UILable *label = [UILabel new];
UIImageView *imageView = [UIImageView new];
[self.view addSubview:label];
[self.view addSubview:imageView];

[label mas_makeConstraints:^(MASConstraintMaker *make) {
    make.left.bottom.top.equalTo(self.view);
    make.right.equalTo(imageView.mas_left);
}];

[imageView mas_makeConstraints:^(MASConstraintMaker *make) {
    make.right.bottom.top.equalTo(self.view);
}];

现在,如果我想保持label的内容不被压缩,传统的AutoLayout方式是将label的contentCompressionResistancePriority设置得更高,那么布局系统将保留label的内容不要压缩,如果水平轴上的剩余空间不够,imageView的宽度将被压缩。所有这些都基于content sizeintrinsicContentSize

继续前进,我将重新实现JS中的本地自定义视图,该视图使用intrinsicContentSize属性来计算是否应该完全显示其内容。自定义视图的目标是水平并排显示多个标签,在我的本机实现中,我将检查layoutSubviews方法中每个子视图的边界是否超出其超级视图:

-(void)layoutSubviews {
    [super layoutSubviews];
    CGFloat width = 0;    
    bool update = NO;

    for(UIView * subview in self.subviews) {
        if(subview.frame.origin.x + subview.width > self.width) {
            subview.hidden = YES;
            update = YES;
        } else {
            subview.hidden = NO;
            width = subview.origin.x + subview.width;
        }
    }

    if(update) {
        self.fitSize = CGSizeMake(width, self.fitSize.height);
        [self invalidateIntrinsicContentSize];    //in intrinsicContentSize method, return self.fitSize
    }
}

现在,AutoLayout知道视图的实际大小,它将基于布局的真实大小。我也想使用react native来实现这一点,但我发现我不能设置两个组件之间的关系,比如我使用基于约束的AutoLayout,也不能覆盖intrinsicContentSize方法来计算我希望它的视图的实际大小,这个用例有什么解决方案吗?

1 个答案:

答案 0 :(得分:0)

React Native使用the CSS Flexbox来布局它的视图。这与UIStackView非常相似;换句话说,您在问题中要求的所有内容与布置React Native视图真的相关!

描述这一点的最佳方式是将其与iOS 9的UIStackView进行比较。如果您对此不熟悉,我强烈建议您check out this tutorial,因为一旦您熟悉UIStackView,将这些知识与Flexbox联系起来将是小菜一碟。 。

在React Native中,您使用a StyleSheet来定义视图的布局。请考虑以下样式:

const styles = React.StyleSheet.create({
  container: {
    flexDirection: "vertical",
    flex: 1,
  }
})

container样式实际上定义了UIStackView,其中的项目是垂直对齐的。

StackView Attributes Screenshot

flex值的存在表示容器中的元素将引用自己的弹性值来确定内容拥抱优先级

这是。就像你提到的那样,React Native的布局可以通过操纵它如何解释每个视图的内在内容大小来完全操纵。

考虑以下布局:

storyboard layout example

让我们关注底部标签栏。假设标签栏本身具有上述container样式(带flexDirection: "horizontal")的样式。

要在React Native中实现此布局,您需要为所有子元素指定flex值。 flex值越高,与其兄弟姐妹相比, 内容拥抱优先级。换句话说,1兄弟的flex值越高,对flex值越低的所有其他兄弟姐妹强制执行更高的内容拥抱优先级。

因此,StyleSheet布局可能如下所示:

const styles = React.StyleSheet.create({
  //flex box containing the child elements
  container: {
    flexDirection: "horizontal",
    flex: 1
  },

  //the three child elements nested inside the container
  plusButton: {
    flex: 1
  },
  chooseSourcePlaylistButton: {
    flex: 2
  },
  settingsButton: {
    flex: 1
  },
})

因为您希望中间视图展开并将其他元素推到边缘,所以您希望它通过赋予更大的flex值来支配弹性框。