react-native版知乎日报APP(四) 页面功能实现

本节主要说明 部分页面的逻辑功能实现 .

Home (首页)

首页包含的功能点有 : 弹出菜单 , 轮播图 , 上拉与下拉加载 , 主题切换 , 日期选择器 .

Home是整个应用相对复杂的页面 , 从上到下可以分为三个部分 : 导航栏 , 轮播图 , 日报列表 . 这三个部分中还结合一些小功能 , 导致代码量较多 , 这里分部说明各功能的实现.

组件划分
  • 导航栏

    导航栏由react-navigation提供 , 这里没有选择手动实现 . 在navigationOptions属性中配置标题,背景色通过Mobx动态获取 . 并通过react-native-elements增加左右的按钮和图标 . 需要注意的 , navigationOptions中无法通过this访问组件内的状态和函数 , 列如: this.state.xxx或者this.xxx() 都是不行的, 只能 通过this.props.navigation.setParams传参的方式 , 有时通过保存this引用为that也阔以解决.

  • 轮播图

    轮播图是相对独立的部分与其他组件没有复杂的交互 , 这里我将其独立为单独的文件 . 一开始我使用react-native-swiper实现 , 结合react-native-linear-gradient实现背景渐变的效果 . 文字悬浮在背景层上这里是通过样式的绝对定位和zIndex实现的 , 在不使用样式时,通过<ImageBackground> 组件应该也可以实现 . 但后期react-native-swiper似乎停止维护了 (Github上的吐槽) , 于是在简化分支上我通过react-native-snap-carousel重写了一遍 .

    注 : 目前(2019/08)该库好像换了管理者 , 有人维护了.

  • 日报列表

    日报列表是应用中复用较多的部分 , 这里将其抽离成组件 . 同时也将ScrollView抽离成组件 , 这样仅需要为日报列表绑定数据源和点击事件并为下拉和上拉加载绑定对应方法 , 而不必关注其内部实现 .
    列表项外轮廓是有阴影 , react-native 提供了阴影属性 但仅支持ios 单端 , 所以列表项阴影借助 react-native-cardview 来实现统一效果 .

  • 其他功能

    • 主题切换

      这里主要涉及Mobx的使用 , 在组件头部顶部引入主题Store , @observer标记组件为可观察状态 , 在点击切换按钮时 , 触发action行为事件即可实现切换主题效果.

         @inject('theme')
         @observer
      

注 : react-native 默认不支持装饰器语法 需要手动增加支持
首先 安装依赖 执行:
yarn add @babel/plugin-proposal-decorators
然后在项目根目录下 创建名为 .babelrc的文件 并增加以下内容 保存即可

{
 "presets": ["module:metro-react-native-babel-preset"],
 "plugins": [
   ["@babel/plugin-proposal-decorators", { "legacy": true }],
   ["@babel/transform-runtime", {
     "helpers": true,
     "regenerator": false
   }]
 ]
}

  • 时间标题随着列表滚动切换

    首先每天日报都有一个时间标题 , 需要实现当滚动到日报区域时 , 对应导航条标题切换到该日报的时间标题. 实现原理 : <View>组件有一个onLayout方法 ,当View高度宽度发生变化时 可以触发并返回新的高宽度 . 通过记录高度区间为一个数组, 每次滚动时判断当前在哪个高度区间 , 既可得出当前日报区域的日期.

    效果演示

    • 日报数据缓存

通过结合 react-native-storage 为日报列表增加缓存 , 当数据不过期时 , 优先调用缓存数据 . 这里需要注意 , 当数据过期时 react-native-storage 会返回过期的数据 , 然后再查找对应的Sync 异步方法更新数据 , 但更新后并不会再次返回 , 下次调用时才返回新的数据. 这就导致有网络且数据过期时,react-native-storage 返回的是过期的数据 , 而不是最新的. 这里通过判断网络状态 , 当链接网络时 , 不调用缓存只等待最新数据返回 , 当离线状态下 , 调用缓存.

效果演示
  • 其他

包括日期选择, 弹出层组件 , 只是一些组件的基本使用 , 不在赘述.

Details (详情页)

详情页主要涉及 WebView和动画的使用

  • 导航栏

    导航栏的分享 , 收藏 , 点赞功能中仅有分享是实际有效的 , 其他只有交互效果. 这里为收藏和点赞增加了交互动画 , 主要涉及了react-native-animatable的基础使用 .

  • WebvView

    这里使用react-native-autoheight-webview替代自带的WebvView , 主要是想解决当WebvView嵌套在ScrollView下时 , 由于两者都存在滚动条 , 互相产生冲突 , WebView的高度会塌陷丢失. react-native-autoheight-webview可以解决这个问题.
    这里还通过 customScript 注入JS到webview中 , 增加点击图片显示大图和处理WebView超链接点击的功能.

  • 滚动动画

    当页面下滑时存在导航条渐隐, 背景图缓慢上移 , 内容上移视差滚动动画.

开发过程 :

最初我通过CSS绝对定位, 控制MarginTop,translateY属性切换来实现动画 , 但发现安卓快速滚动时存在性能问题 , 动画跟不上滚动速度. 安卓可以通过 useNativeDriver: true原生本机驱动的形式优化动画性能 , 但该属性支持的动画属性十分有限 , 仅支持opacity, translate transform 下属性 , 不支持像MarginTop这种布局属性 , transform 也不像 Web端 CSS 支持修改动画基点 . 后来发现 react-native-parallax-scroll-view 可以解决部分 , 它能解决页面布局的问题 , 不需要CSS绝对定位就可以实现类似布局, 仅需要实现导航条渐隐背景图上移动画即可 , 最终成功实现预期效果 .

为了提高用户体验 , 还为详情页增加了 , 左滑右滑上下翻页的功能 . 背后的原理 其实就是一个轮播图 , 每页日报铺满视口 , 通过传入的ID数组 , 左右滑动时切换不同的数据 .

性能问题 :

在测试时发现 react-native-parallax-scroll-view带来的副作用 , react-native-parallax- scroll-view 和 react-native-webview 两者结合时 , 在 初次 打开页面会占用大量性能 , 导致在低性能的老机型上导航过渡动画完全丢失 ,在开发调试模式下比较明显 ,目前还没有太好的解决方案。

  • 其他

    • 大字体功能

      通过控制 CSS 增加 <html>标签字号百分比实现

    • 日报夜间主题

      WebView引用的CSS文件中有关于夜间主题的样式 , 通过给<body>标签追加样式即可 .

扩展资料

  1. React Native动画入门
  2. React Native WebView指南
  3. 自定义标题动画
  4. React Native中的动画标题
  5. 使用Native驱动程序进行动画处理
  6. react-native 性能优化

ImgView (图片查看页)

涉及图像的查看与下载保存功能

当点击详情页的图片 , 会进入图片查看页面 , 该功能支持手势缩放与图像保存到本地 . 其中 react-native-image-viewer 负责图像查阅功能 , rn-fetch-blob 负责处理图像文件下载到本地指定文件夹的功能 .

Comment (评论页)

涉及<Modal>遮罩层 <FlatList> 二维列表

主要涉及Modal遮罩层 和 二维数组列表 , 业务代码居多 .

扩展资料

  1. 缓动动画的基础知识

Drawer (侧边栏抽屉)

涉及登录状态读取 , 头像选取拍摄

  • 登录身份验证流程

    登录流程仅 , 在应用中并没有线上功能 , 只是一个流程模拟 .

    关于登录验证 在react-navigation的文档中已提供示例 , 示例中的关键点在于通过 createSwitchNavigator 创建导航 . 但SwitchNavigator导航并不适用本应用 , 问题点在于SwitchNavigator没有提供切换过渡动画 , 影响使用体验 . 本应用中将登录相关的页面 , 注册在 堆栈导航器中(StackNavigator) , 登录成功后通过跳转的方式返回首页. 开发中发现 , 由于首页已存在导航栈中 , 登录成功跳转回首页并不会重新触发侧边栏的componentDidMount生命周期行为 , 导致侧边栏无法重新获取本地存储中的登录状态 . react-navigation 也没有提供回调方法 判断侧边栏的打开状态 , 最终通过在 App.js注册自定义事件 , 在侧边栏中监听全局自定义事件才解决这个问题.

  • 头像选取

    头像选取功能是我结合几个组件封装成一个组件 , 在Android上测试可以 , IOS还没有测试过 .

    注 : 关于图像拍摄功能 , 如果需要自定义相机UI界面 请使用底层库react-native-camera

剩余其他页面 , 包含 设置 , 栏目 , 了解我们 , 意见反馈 , 登录注册等页面 . 代码较少 , 功能也很简单 , 属于一看就懂那种 , 不在赘述 , 有问题请在Github中向我反馈 .

推荐阅读更多精彩内容