使用 React Native 构建 Facebook Paper 类似的 UI

731 查看

我模仿 Facebook 的 Paper 应用构建了一个开闭卡片的轮播效果作为技术演示.它使用了 React Native 及其动画库.

当人们听到 React Native 后第一反应会觉得它运行缓慢.这是因为一般人会去这样解释 React Native: "它允许你通过 Javascript 构建你的应用程序",而人们会认为浏览器中运行的 JavaScript 性能并不够好.

但事实是,它采用的全部都是原生界面元素.但你通过 React Native 构建界面时, 每次都会实例化 Android 和 iOS 的原生 UI.因此,相比于比较沉重的 DOM 结构它是相当请轻量的.

下面一段介绍:我是如何着手构建类似 Facebook 的 Paper 应用的交互效果的. 我们可以放大和缩小轮播图,在动画进行的时候,我们也可以停止它.

先来看看它是什么样子:


Actual screenshots from the working demo.

Actual screenshots from the working demo.

上面的屏幕截图,是从我所构建的 App 中截出来的. 左边是当前缩小的卡片列表.您可以滑动它们.您也可以把它拉起来,让它们变成全屏. 现在你可以在全屏状态下滑动卡片,一个接一个. 我们来与下面 Facebook Paper应用的交互模型来进行比较.


The zoomed out carousel of cards at the bottom.

点这里查看 Youtube 上的视频

我们以实例化两个状态变量开始.一个用于存储 pan 值,另一个存储动画进度:从0到1.这一进展变量是基于 pan 值进行插值.

let pan = new Animated.ValueXY();
this.state = {
  pan: pan,
  dockAnimation: pan.y.interpolate({
    inputRange: [-300, 0],
    outputRange: [0, 1],
  })
}

现在,我们需要创建一个 panResponder. 这是一个复杂的手势操控的概念,它判断什么时候应该激活手势以及们完成事件的各种方法.在我们的例子中,我们要在手势正在进行和结束对它进行跟踪.

this._panResponder = PanResponder.create({
  onStartShouldSetPanResponder: (evt, gestureState) => true,
  onStartShouldSetPanResponderCapture: (evt, gestureState) => true,
  onMoveShouldSetPanResponder: (evt, gestureState) => true,
  onMoveShouldSetPanResponderCapture: (evt, gestureState) => true,
  onPanResponderGrant: () => {},
  onPanResponderMove: Animated.event([null, {dx: this.state.pan.x, dy: this.state.pan.y}]),
  onPanResponderRelease: (evt, gestureState) => {
    // dragging stopped, animate the item to the correct position
  }
})

在实际代码中可以看到看到 onPanResponderRelease 块的全部实现.它做的很简单:决定用户是否已经拖远远,并切换 state 的值.如果是,绘制这个动画.

transform: [{
  scale: this.state.dockAnimation.interpolate({
    inputRange: [0, 1],
    outputRange: [1, 0.5],
  })
}

多种变换被以 ListView 的 style 的方式应用. 我已经用 scale 变换作为例子展示了,再一次,我们使用插值来控制动画.

<AnimatedListView
  style={this.getListViewStyle()}
  {...this._panResponder.panHandlers}
/>

最后,styles 和 panResponder 的 panResponder 都被绑定到了 ListView. 需要注意的是在我们创建了一个一个组合式的 ListView: AnimatedListView,这样的动画库可以从样式对象解析出动画的值.

这就是我们需要为动画做的所有事情!剩下的就是使用 Flex 布局来构建那些漂亮的卡片.Jason Brown 写了一本有关React Native动画库的好书:http://browniefed.com/react-native-animation-book

我在 Github 上共享了所有的代码,你可以自由修改它!

paramaggarwal/rn-paper-interface

<iframe src="https://player.vimeo.com/video/175727390" width="640" height="1137" frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe>

目前,我只在iOS上运行过.但是你可以尝试在 Android 上运行,并在 github 上打开一个 PR. 我没有用过任何的 iOS 特定的 API, 所以理论上,它应该在 Android 上工作.


作者信息
原文作者:Param Aggarwal
原文链接:http://t.cn/RtnSJwA
翻译自力谱宿云 LeapCloud旗下MaxLeap团队_UX成员:Jason
译者简介:MaxLeap UX 组负责人,负责前端开发,客户端/部分服务端 SDK 开发及开发者用户体验优化相关工作. 持续关注新技术,热爱产品, 热衷全栈/全端开发. 曾供职于搜狐武汉研究院,后投身 MaxLeap致力于为开发者提供快速高效的开发体验.