场外音:
今天因为写一个用了很多次的布局而加班到10点才回家…

这里我先抛出问题:
Interesting

图中用红框圈出来的部分视图指定高度,而宽度在不设置值的情况下默认是撑满屏幕的( Tips: flexDirection 的 cross 方向在不指定 size 的情况下是 match_parent 的 ),‘用药禁忌’ 是可点区域。
Notice:这部分要求通过传递组件的形式描述布局,因此我们需要的是一个完整单一的组件,这也是为了约束题目。

请给出你所能想到的所有布局方案.

问题分析

首先,可以很轻易看出以下几点:

  • 布局在竖直方向上是垂直居中
  • 两个 Item 是呈左右两端分布,并存在适当边距
  • 右侧的点击区域可大可小

方案一

适用于右侧点击区域比较灵活的

<View style={{flex: 1, alignItems: 'center', flexDirection: 'row'}}>
{leftView}
<View style={{flex: 1}} />
{rightView}
</View>

这种方案比较简单:

  1. 让父布局呈水平布局,且子元素纵向上居中,这样所有子元素不再满高,而是被压缩在中间以自适应的形式存在
  2. leftView、rightView 在不指定宽高的情况下是自适应的子布局的,因此在中间加了辅助元素 flex: 1 后这两个布局会被挤到父布局两侧,接下来就可以直接在这两个布局上控制左右边距即可达到目标。
  3. 然后就可以使用 TouchableXXX 的 hitSlop 属性来扩展点击区域大小

方案二

这是一种较为简单明了的布局思路

这种方案也是我在 react-native-navigationbar 中用到的。

const leftChildrenView = (
// 子布局默认 cross 对齐方式是 auto,也可以对 alignSelf 使用
// flex-start、flex-end、center 等值进行 cross 方向上的调节、
// 再配合 margin 外边距微调即可
)

const rightChildrenView = (
same as leftView
)

...
<View style={{flex: 1, flexDirection: 'row'}}>
<View style={{flex: 1, justifyContent: 'center'}}>
{leftChildrenView}
</View>
<View style={{flex: 4}} />
<View style={{flex: 1, justifyContent: 'center'}}>
{rightChildrenView}
</View>
</View>

解析
整体思路如下:

  1. 最外层水平布局并使用 flex 撑满父容器
  2. 内容使用 flex 值进行等份划分,中间4份,两侧一份。此时布局是垂直撑满屏幕的,别问我为什么,前边有讲
  3. 通过 step 2 你可以得到左右各一份等宽并满高的视图,这样在给左右护法加了 flex 方向的居中后,就可以很轻易得配合 alignSelf 以及 margin 等 style 进行水平方向上的微调
  4. 这种情况下右侧的点击区域是撑满自己的宽高的

so much for this ……

donation