在本系列中,您将学习如何使用 react Native 创建移动应用程序中常用的页面布局。你创建的布局不会是功能性的——相反,本系列的主要重点是让你在 React Native 应用程序中布局内容。
为了跟随本系列,我挑战您先尝试自己重新创建每个屏幕,然后再阅读本教程中的分步说明。仅仅通过阅读本教程,您不会真正受益于它!在此处查找答案之前先尝试。如果你成功地让它看起来像原始屏幕,将你的实现与我的进行比较。然后自己决定哪个更好!
在本系列的第三篇文章中,您将创建以下照片库页面:
画廊通常用于以仅显示必要信息的方式显示相关内容的集合。大多数情况下,这包括照片、标题和其他相关信息。
以下是在野外使用的此类布局的几个示例:
项目设置
第一步,当然是建立一个新的 React Native 项目:
react-native init react-native-common-screens
设置项目后,打开 文件并将默认代码替换为以下内容:index.android.js
import React, { Component } from 'react'; import { AppRegistry } from 'react-native'; import Gallery from './src/pages/Gallery'; export default class ReactNativeCommonScreens extends Component { render() { return ( <Gallery /> ); } } AppRegistry.registerComponent('ReactNativeCommonScreens', () => ReactNativeCommonScreens);
创建一个 src/pages
文件夹并 Gallery.js
在其中创建一个文件。
你还需要这个 react-native-vector-icons
包。这专门用于页脚中的图标。
npm install --save react-native-vector-icons
打开 android/app/build.gradle
文件并添加对包的引用:
dependencies { //rest of the dependencies are here at the top compile project(':react-native-vector-icons') //add this }
android/settings.gradle
通过在底部添加以下内容对文件执行相同 操作:
include ':react-native-vector-icons' project(':react-native-vector-icons').projectDir = new File(rootProject.projectDir, ' ../node_modules/react-native-vector-icons/android')
打开 android/app/src/main/java/com/react-native-common-screens/MainApplication.java
并导入包:
import java.util.Arrays; import java.util.List; import com.oblador.vectoricons.VectorIconsPackage; //add this
最后,初始化包:
@Override protected List<ReactPackage> getPackages() { return Arrays.<ReactPackage>asList( new MainReactPackage(), new VectorIconsPackage() //add this ); }
创建图库页面
好的,既然您已经尝试自己编写布局代码(没有作弊,对吗?),我将向您展示我是如何构建我的实现的。
与前两个页面不同,图库页面需要一些图像作为其主要内容。您可以去 Google 搜索图片或从 GitHub 存储库下载图片。我使用的所有图像都标记为供其各自所有者重复使用,因此您可以根据需要自由使用它们。获得图像后,将它们保存在 src/images
目录中。由于图像的布局方式,它们都应该具有相同的尺寸。
首先创建文件 ( src/pages/Gallery.js
) 并添加样板代码:
import React, { Component } from 'react'; import { StyleSheet, View, ScrollView, Image, } from 'react-native'; import Icon from 'react-native-vector-icons/fontAwesome'; import Button from '../components/Button'; export default class Gallery extends Component { ... }
此页面需要一个 constructor()
函数,您可以在其中定义要使用的图像的路径。在 React Native 中,引用工作目录中的图像的方式是像使用javascript模块一样需要它们。同样重要的是要注意,您不能动态生成图像路径,因此您必须手动提供实际路径。
constructor(props) { super(props); this.state = { photos: [ { label: 'beach', src: require('../images/beach.jpg') }, { label: 'bridge', src: require('../images/bridge.jpg') }, { label: 'fields', src: require('../images/fields.jpg') }, { label: 'mountains', src: require('../images/mountains.jpg') }, { label: 'sunflower', src: require('../images/sunflower.jpg') }, { label: 'sunset', src: require('../images/sunset.jpg') }, { label: 'lake', src: require('../images/lake.jpg') }, { label: 'nature', src: require('../images/nature.jpg') }, { label: 'pink', src: require('../images/pink.jpg') }, { label: 'rails', src: require('../images/rails.jpg') }, ] }; }
您实际上不需要在状态中定义这些值,因为值不会改变。您实际上可以在单独的文件中定义它们,导入它,将其分配给一个变量,然后直接使用它。但为了简单起见,我决定将所有内容都放在状态中。
在 render()
方法内部,您将打破将所有内容包装在 ScrollView
组件内的趋势,因为屏幕最下方的选项卡组件应该有一个固定的位置。这意味着即使照片超出可用高度,标签仍应保持在原位。为此,请使用 View
组件来包装所有内容,并且仅将照片集合包装在 ScrollView
. 这允许您仅将滚动应用于照片集合的容器:
render() { return ( <View style={styles.container}> <ScrollView style={styles.gallery}> { this.renderGallery() } </ScrollView> <View style={styles.tabs}> </View> ); }
现在您可能会开始在这里看到一种模式。每次需要在 render()
函数中使用 JavaScript 代码时,都应该创建一个单独的函数来保存该代码,而不是将其直接放在 render()
函数中。这使它保持精益和清洁。
现在让我们继续进行造型。尽管 ScrollView
这次没有使用 a 来包装所有内容,但重要的是要注意您仍然必须向 flex: 1
主容器提供内容,以便它消耗整个可用空间。
container: { flex: 1, flexDirection: 'column' }, gallery: { flexDirection: 'column' }, tabs: { flexDirection: 'row', backgroundColor: '#333', padding: 20 }, tab: { flex: 1 }, icon: { textAlign: 'center' },
该 renderGallery()
函数与我们在上一个教程中使用的函数非常相似 renderWeeks()
,我们用于渲染日历页面。如果您想重新了解它的工作原理,请继续阅读日历页面上的上一个教程。您需要知道的是,resizeMode
它适用于 Image
. 在这种情况下,它设置为 cover
,这使得图像占据其容器的整个可用空间,同时仍保持其纵横比。如果原始图像较小,这会导致屏幕较大的设备的图像略微放大。
renderGallery() { var count = 0; var previous_item = ''; var pairs = this.getPairsArray(this.state.photos); return pairs.map((item, index) => { return ( <View style={styles.item} key={index}> <Image resizeMode={Image.resizeMode.cover} style={styles.photo} source={item[0].src} /> <Image resizeMode={Image.resizeMode.cover} style={styles.photo} source={item[1].src} /> </View> ); }); }
这是 getPairsArray()
功能:
getPairsArray(photos) { var pairs_r = []; var pairs = []; var count = 0; photos.forEach((item) => { count += 1; pairs.push(item); if(count == 2){ pairs_r.push(pairs) count = 0; pairs = []; } }); return pairs_r; }
最后,这里是每一行 ( item
) 和照片 ( photo
) 的样式。注意 flex: 1
实际照片上的使用。这样做是因为 Image
组件本身就是它自己的容器。您希望容器本身占据每一行可用空间的一半——这就是 flex
应该分配属性的原因。如果不这样做,只会消耗照片所需的尺寸,而 resizeMode
您之前添加的尺寸甚至不会产生效果。
item: { flex: 1, flexDirection: 'row', }, photo: { flex: 1 }
结论
而已!在本教程中,您学习了如何实现图库页面的布局。在布局 React Native 应用程序时,我们专注于如何处理图像。通常,您必须使用flex
和的组合resizeMode
才能使图像按照您想要的方式流动。我的解决方案与您的解决方案相比如何?