理解 React Native 的 FlexBox 排版模型

这两天尝试用 React Native 写了一个 APP,总体感觉是个好东西。目前没有 macOS 环境,没法测试 iOS 上的表现,但是安卓上是不错的。

在设计界面的过程中,如何正确排版、正确使用 FlexBox 模型就成了一个关键问题。其实这里的 FlexBox 跟 CSS3 中新加的那个 FlexBox (Flexible Box) 基本上是一样的,所以通过 MDN 上的这篇文章可以了解 FlexBox 的基础知识,例如主轴和侧轴、每个轴的元素排列等。另外,SegmentFault 上有一篇关于 React Native 布局的文章也不错,介绍了 FlexBox 排列元素时,遇到多个 flex 元素或有固定大小的(不 flex 的)元素,会怎样安排他们的大小。

假定读者阅读了上面两篇文章,明白了基础知识。接下来我结合 APP 中的实例来讲一下使用 FlexBox 过程中遇到的问题、解决方法和对 FlexBox 模型的理解。

考虑如图所示的 UI,上面是一个固定高度的标题栏,其中包含左右各一个固定大小的按钮,中间的文字填满剩余空间;下面是很长的内容,可以上下滚动,滚动时标题栏一直在最上面不动。

首先整个界面的顶层 <View> 标签,其 style 应该包括: {flex: 1, flexDirection: 'column',} ,这样内部元素就会上下排布。标题栏我额外定义了一个 Header 类( class Header extends Component {} ),因此 <View> 的第一个子元素就是 <Header style={...}>(标题栏子元素)</Header> 。这里要注意的是,给 Header 定义 style 本身没有任何效果,应该在 Header 类的 render() 方法中,将其实际顶级元素的 style 附加上 this.props.style,即  <View style={[header_styles.basic, this.props.style]}>...</View>

然后看 <Header> 对应的 <View> 的 style。由于 <Header> 本身是固定高度的,因此可以肯定它不是 {flex: 1} 的。但是我们又想使用 FlexBox 中的排版功能,对标题栏中的元素横向排版,所以在顶层 <View> 中再嵌套一层 <View>,它的 style 应该是这样的:

接下来看内层 <View> 的子元素。首先是左上角、右上角的图标,这里我用的是 react-native-vector-icons,就是两个 <Icon> 元素,它们都是固定大小的(其实就是一个特殊字符),因此我们需要中间的标题 <Text style={{flex: 1}}> 以填满剩余空间。这里就看出来,{flex: 1} 的意思就是这个元素的长宽可以任意放大(或缩小),以适应排版的需要。

这样 <Header> 部分就搞定了,接下来看正文的滚动部分,这里用的是 React Native 的 <ScrollView> 元素。通过文档中看出,ScrollView 是由一个外层短元素包含一个内层长容器,外层短元素可以是固定高度(height)的或 flex 填满剩余高度的,但内层容器应该是内容的实际高度,而不应该是 flex 的。这里文档写的很迷茫(“把 flex 从视图栈向下传递”,并没有看明白哪里是栈、哪里是下……),我是踩了很多坑才搞明白这是什么意思。主要代码如下:

这个 <ScrollView> 在顶层 flex <View> 中,将其设为 {flex: 1} 即可填满除 <Header> 以外的剩余屏幕高度。但是 contentContainerStyle 控制的内层样式绝不应该有 {flex: 1},否则会被缩小到与外层元素一样高,裁剪掉多余的内容,因此无法实现滚动。这里与 <Header> 中类似,内部长内容可能还有更复杂的排版(比如进一步上下/左右分割),所以可以在 <View> 子元素的 style 上下功夫,比如设为  {flex: 1, flexDirection: 'row',} 即可将内部元素再左右排列。

下面提供一些我的 APP 中实现上述布局的代码(省略了逻辑和内容,只保留排版相关的代码,最终效果类似于 Material Design),供读者参考:

 

第二次自己做字幕,这次是脱口秀

Wow,离第一次做美剧字幕已经过去接近五年了,简直是时间飞逝……

Update: 后来又做了几集不同的视频字幕,也把链接放在这里:

  • Last Week Tonight S03E13 – AcFun, BiliBili(需登陆)
  • 柯南秀:明星填问卷 2016.06.16 – BiliBili
  • 鸡毛秀街头采访:川普粉丝有多死心塌地? – BiliBili
  • 赛金花深夜秀:近距离观察 – 川普接受党内提名 – BiliBili

更多视频可以参见我的 AB 站个人主页:

我已经加入阿尔法小分队字幕组,主要做 Last Week Tonight 的字幕。小分队主页:http://space.bilibili.com/60058


前两天又找到一个空闲时间,于是做了一集美国脱口秀的字幕,剧集是 Last Week Tonight with John Oliver(上周今夜秀)的 S03E13。这次只做了中文字幕,因为实在懒得把英文都打出来。把30分钟脱口秀的中文字幕输入到编辑器里,花了大概10个小时,之后做轴和压制大概各1小时。

这次没有传别的地方,只传了AB站。下面是B站的Flash播放器外链,也可以点击这里去B站看。(外链请进入全文查看) 继续阅读“第二次自己做字幕,这次是脱口秀”

Compiling kernel modules for Atheros AR5B22 (AR9462) on Jetson TK1

I recently got a Atheros AR5B22 chip for my Jetson TK1 board, in order to make it support WiFi and Bluetooth. The system provided by NVIDIA (Linux4Tegra 21.4) doesn’t have Atheros driver built-in, so I have to compile it to make use of the device.

AR5B22 installed on Jetson TK1

This is what the chip looks like when installed on TK1. AR5B22 is the Mini PCIe reference design for AR9462, which features both 2.4GHz and 5GHz WiFi and Bluetooth 4.0, according to WikiDevi.

Since it belongs to 9xxx series, Linux kernel has the well-supported driver ath9k for it. Unlike other WiFi-Bluetooth-combo chips from Atheros, this one doesn’t specify which Bluetooth chip it uses (judging by BT 4.0 support, it should be AR3012), but nevertheless you still need ath3k driver and firmware for Bluetooth support. This has bugged me for quite a while, but I figured it out anyway (with hints from this Ubuntu bug report).

If you are familiar with how to compile Linux kernel modules for Jetson TK1, above is all you need to continue. The rest of this article are detailed steps for those who don’t know about this.

Note: The following steps are to compile directly on TK1, and features some hack-y steps for installing them. Also, I am NOT responsible for bricking your device.

  1. First make sure you have the latest Linux4Tegra (L4T) 21.4 installed on your Jetson TK1, which features basic bluetooth support. You can use Jetpack to flash it.
  2. The following steps are all carried out with a shell on TK1. It could be either over SSH (ssh [email protected]), or GNOME Terminal (Ctrl-Alt-T) from GUI if you have a monitor plugged in.
  3. Install the firmware (for ath3k) and dependency (for kernel config menu) packages on your TK1.
  4. Download and extract L4T kernel sources into your home directory.
  5. Copy existent kernel config as a start.
  6. Enter kernel config menu, and change the following settings.

    • From “General setup” set “Local version” to “-gdacac96” (check with uname -a), otherwise your compiled module will report “Unknown symbol in module” and “ath9k: version magic … should be …” errors when you insert them.
    • Use “Exit” to go back to the top, then from “Device Drivers – Network device support – Wireless LAN”, press M on “Atheros Wireless Cards” to compile it as a module; then enter it, press M on “Atheros 802.11n wireless cards support”, and press Y on “Atheros bluetooth coexistence support” and “Atheros ath9k PCI/PCIe bus support”.
    • Again, “Exit” to the top, then from “Networking support – Bluetooth subsystem support (should already be M in 21.4 kernel) – Bluetooth device drivers”, press M on “Atheros firmware download driver”.
    • Use “Save” to save your work (default “.config” name is fine), and “Exit” until you are back to the shell.
  7. Use the following command to start the compilation. It usually needs ~5 minutes to finish.
  8. Here comes the hack-y part: Officially you need sudo make modules_install to install the modules, but I just want to install the newly compiled ones into a separate folder, so I will use the following commands instead:
  9. In order to use WiFi and Bluetooth together, you need to enable “Bluetooth coexistence” in ath9k module.
  10. Finally, insert both modules into the kernel.

You should now have both WiFi and Bluetooth working. You can check with the following commands:

Just to be clear, I used the above steps with the following hardware, but I suppose you can use the same drivers for any Atheros WiFi AR9xxx series and BT AR3xxx series chip (combo or separate), as long as the 3.10 kernel and ath9k & ath3k modules support them.

配置路由器使用联通 PPPoE IPv6

博主所在的济南联通,很早以前说已经开通了公众 IPv6 网络,但是从 2015 年底才开始陆续有人报告可以获取到 IPv6 地址了。这里面具体怎么回事我就不追究了,今天我也终于成功的在电脑和路由器上配置好了 IPv6 网络。

更新:经过测试,使用 OpenWrt 官方最新的 15.05.1 版本,默认安装无需配置即可获取 IPv6 地址,而且软件库中有更多软件包可用,因此建议直接使用新版,而不要使用 PandoraBox 等版本旧、不开源的分支。小米路由器 Mini其它路由器都可以在官网查询支持情况。

联通在我这里使用的是 PPPoE 拨号上网,在 Windows 系统上无需配置就可以直接获取到 IPv6 地址,所以这篇文章主要说一下 OpenWrt 系统路由器的配置。

1. 第一步当然是准备一个支持 OpenWrt 系统(版本最少是 Attitude Adjustment 12.09.1,建议是 Barrier Breaker 14.07 或更高)的路由器。博主用的是小米路由器 Mini (R1CM),其本身虽然是定制的 OpenWrt 系统,但是界面没法像原版系统一样方便的修改参数,而且没有可用的 opkg 包管理软件(类似于 apt-get),最好还是刷成原始的 OpenWrt 系统。

还是以我手中的小米路由器为例,首先要将系统刷成开发版固件,然后去官网开放 SSH 权限,再接下来就是去下载 PandoraBox(一个国产的 OpenWrt 分支,适配很多国产路由器)并刷机。我使用的刷机命令是:

2. 刷好机并进入后台后,请先确认左侧“系统”-“软件包”中有“odhcp6c”这个软件。如果没有的话,建议先“刷新列表”,然后在“可用软件包”中安装它。这个软件是用于通过 DHCP 协议自动获取 IPv6 地址的,因此对本教程至关重要。在 12.09.1 系统中可能不提供这个软件,那么建议下载类似的软件包(通常名字中含有 dhcp 和 6)。

3. 接下来,可以转到左侧“网络”-“接口”,默认内置了三个选项:LAN、WAN 和 WAN6。如果你的系统没有 WAN6,可以在接口中新建一个接口,并将“协议”设置为“DHCPv6 client”并点击“切换协议”。

接下来,在 WAN6 接口中按照如下配置:(括号内是 /etc/config/network 中对应的配置项,都在 config ‘interface’ ‘wan6’ 这一段中)

  • 基本设置:
    • Request IPv6-address:Disabled(option reqaddress ‘none’)
    • Request IPv6-prefix of length:自动(option reqprefix ‘auto’)
  • 物理设置:
    • 接口:自定义接口,[email protected](option ifname ‘@wan’)

这样完成了 DHCP 获取 IPv6 地址的配置,可以先“保存”(不必现在应用)。接下来配置一下 PPPoE 上网信息,在左侧找到“接口”-“WAN”,并进行如下配置:(括号同上,属于 config ‘interface’ ‘wan’ 这一段)

  • 基本设置:
    • 协议:选择 PPPoE,但是如果你是其它网络,可以按自己的情况选择“静态地址”、“DHCP 客户端”等。(option proto ‘pppoe’)
    • PAP/CHAP 用户名、密码:输入宽带拨号的用户名和密码即可。(option username ‘xxx’ / option password ‘xxx’)
  • 高级设置:
    • 在 PPP 链路上启用 IPv6 协商:打勾(option ipv6 ‘1’)

这样也完成了上外网配置,还是先“保存”。最后进行一下“接口”-“LAN”中的配置:(属于 config ‘interface’ ‘lan’ 这一段)

  • 上部分“基本设置”:
    • IPv6 assignment length:64(option ip6assign ’64’)
  • 下部分“IPv6 Settings”:
    • Always announce default router:打勾(option ra_default ‘1’)

全部搞定,此时选择“保存&应用”,然后等待大概一分钟(PPPoE 拨号、获取 IPv6 地址的时间),路由器和所连接设备应当都能获得 IPv6 地址了。

路由器配置成功后,可以从以下两处看到效果:

(1) “状态”-“总览”-“网络”:

(2) “网络”-“接口”:

大概解释一下其中的意思:2408:802a::ee3a/64 这个地址,是路由器 WAN 口本身获得的 IPv6 地址,在路由器上使用 ping6 等命令,就是通过这个 IP 向外访问。而2408:802a::0:1/64 这个 IPv6 网段,是路由器从网络中申请到的专用子网段,用于分配给连接到路由器的设备。

回忆今天的华为上机考试题

今天下午参加了华为在济南的上机考试(据说上午也有一批,题不一样)。回忆一下考的题目,总体还是很水,但是最后一题还是可耻的 WA 了……

  1. 初级题(100分,6个点):送分,输入a和b,输出[a,b]之间的素数,没有时间、空间限制,而且题干用中文把算法都给描述出来了,考验你是否会打开VS或Eclipse、编译、运行……
  2. 中级题(200分,4个点):输入一串逗号分隔(脑残)的数,不超过1000且无重复,输出这串数中可以被其它数整除的数,要求按输入顺序。基本也是送分,除了输入比较恶心(一般都是输入n,然后输入n个数;这个我只能用字符串一位一位处理了)。
    样例:输入”3,4,2,6″,输出”4 6″。
  3. 高级题(300分,4个点):有N个岛,给出岛间距离,全部连通最少需要多少距离的桥?输入n(3<=n<=1000),再输入n*n的邻接矩阵表示距离(没有给出距离的范围……都没说是不是整数……),输出最短桥距离。
    明显是MST,写完贪心(Kruskal,只记得这一种,也不让上网搜)交上去WA 2/4,而且只能提交五次,改了4种版本之后依然稳定的2/4,最后就只拿到一半分。交完最后一次才想到,是不是距离可能有浮点数……
    样例输入(自己编的):
    3
    0 123 456
    123 0 789
    456 789 0
    输出:579

总之是很水的题目,而且要吐槽的是做完之后不能走(15分钟做完前两题、45分钟败完5次提交,剩下一小时就瞪着监考老师),还要做职业测试(精神病测试),做完一遍因为做的太水又被迫做了第二遍……呵呵哒。

PS: 考场上有个孩子,可怜兮兮的给监考老师说,老师我没用过VS,我只会用Code::Blocks,这个VS简单的程序也报错,blah blah……当时我就傻了,还真有只用过Code::Blocks的大神orz……

PSS: 蒋震机房的XP+VS2005真是亮瞎了朕的氪金狗眼,新建工程Debug报缺少DLL,必须先修改一个“FAT32什么什么”的选项才能用……