react-native init rn --version react-native@0.59.4
react-native run-android
react-native start
// 每次安装新包需要重新编译或Start
yarn add react-native-router-flux
App.js 中导入并配置
import React, { Component } from 'react';
// 导入
import { Router, Stack, Scene, Actions } from 'react-native-router-flux';
React.Component.prototype.Actions = Actions;
import Main from './components/Main';
export default class App extends Component {
render() {
return (
<Router>
{/* 配置 */}
<Stack>
<Scene key="main" component={Main} hideNavBar={true} />
</Stack>
</Router>
);
}
}
yarn add react-native-tab-navigator
import React, { Component } from 'react';
import { View } from 'react-native';
import TabNavigator from 'react-native-tab-navigator';
import Home from './tabs/Home';
import Cart from './tabs/Cart';
import Member from './tabs/Member';
export default class Main extends Component {
constructor() {
super();
this.state = {
selectedTab: 'home'
};
}
render() {
return (
<View style={{ flex: 1 }}>
<TabNavigator>
<TabNavigator.Item
selected={this.state.selectedTab === 'home'}
title="首页"
onPress={() => this.setState({ selectedTab: 'home' })}
>
<Home></Home>
</TabNavigator.Item>
{/* ... */}
</TabNavigator>
</View>
);
}
}
- 安装
yarn add react-native-vector-icons
- link
react-native link
- 打开
android/app/build.gradle
,定位到第81行
,添加如下代码
// 自定义项目用用到的 字体文件
project.ext.vectoricons = [
iconFontNames: ['Ionicons.ttf'] // Name of the font files you want to copy
]
// 应用导入的字体文件
apply from: "../../node_modules/react-native-vector-icons/fonts.gradle"
- 重新编译
react-native run-android
- 使用
import Icon from 'react-native-vector-icons/Ionicons';
<TabNavigator.Item
selected={this.state.selectedTab === 'home'}
title="首页"
onPress={() => this.setState({ selectedTab: 'home' })}
renderIcon={() => <Icon name="md-home" size={22} color="#900" />}
renderSelectedIcon={() => <Icon name="md-home" size={22} color="#0078d7" />}
>
<Home></Home>
</TabNavigator.Item>
yarn add react-native-swiper@nightly
import React, { Component } from 'react';
import { View, Image } from 'react-native';
import Swiper from 'react-native-swiper';
export default class Home extends Component {
constructor() {
super();
this.state = {};
}
render() {
return (
<View>
<View style={{ height: 200 }}>
<Swiper showsButtons={false} autoplay={true}>
{/* resizeMode="contain" */}
<Image source={{
uri: 'http://overwatch.nos.netease.com/2/media/artwork/Roadhog_artwork.jpg'
}} style={{ width: '100%', height: '100%' }} />
<Image source={{
uri: 'http://overwatch.nos.netease.com/2/media/artwork/hanzo-concept.49XGv.jpg'
}} style={{ width: '100%', height: '100%' }} />
<Image source={{
uri: 'http://overwatch.nos.netease.com/2/media/artwork/soldier-76-concept.40OZx.jpg'
}} style={{ width: '100%', height: '100%' }} />
</Swiper>
</View>
</View>
);
}
}
<ScrollView style={{ flex: 1, backgroundColor: '#fff' }}>
{/* 小屏装不下时需要 ScrollView 进行滚动 */}
<View>
<View style={styles.gridList}>
<View style={styles.gridItem}>
{/* 注意引入本地图片直接 require,不再需要 uri 了 */}
<Image style={styles.gridImg} source={require('../../images/calendar.png')} />
<Text>天降正义</Text>
</View>
{/* ... */}
</View>
</View>
</ScrollView>
App.js
<Router>
{/* 配置 */}
<Stack>
<Scene key="main" component={Main} hideNavBar={true} />
<Scene key="in_theaters" component={MovieList} />
</Stack>
</Router>
Home.js
<TouchableOpacity style={styles.gridItem} onPress={() => this.Actions.in_theaters()}>
<View>
<Image style={styles.gridImg} source={require('../../images/files-and-folders.png')} />
<Text>电影列表</Text>
</View>
</TouchableOpacity>
<Router>
{/* 配置 */}
<Stack>
<Scene key="main" component={Main} hideNavBar={true} />
<Tabs
{/* tabBarPosition="top" 有个警告待解决! */}
tabBarPosition="top"
hideNavBar={true}
// 启动Scene的懒加载效果,知道对应的路由被激活时,才会创建对应的组件
lazy={true}
>
<Scene
key="in_theaters"
component={MovieList}
title="正在热映"
hideNavBar={true}
mtype="in_theaters"
/>
<Scene
key="coming_soon"
component={MovieList}
title="即将上映"
hideNavBar={true}
mtype="coming_soon"
/>
<Scene
key="top250"
component={MovieList}
title="Top250"
hideNavBar={true}
mtype="top250"
/>
</Tabs>
</Stack>
</Router>
<FlatList
data={this.state.mlist}
renderItem={({ item, index }) => this.renderMovieItem(item)}
keyExtractor={item => item.id + ''}
ItemSeparatorComponent={() => <View style={{ borderTopColor: '#ccc', borderTopWidth: 1, marginHorizontal: 10 }}></View>}
/>
loadMore = () => {
// 先判断还有更多吗
// nowPage * pageSize >= totalSize 证明没有下一页了
const {nowPage, pageSize, totalSize} = this.state;
if(nowPage * pageSize >= totalSize) {
this.setState({
isOver: true // 数据加载完了把 loading 干掉
});
} else {
this.setState({
nowPage: nowPage + 1
}, () => {
this.getMovieListByType();
});
}
}
App.js 中配置路由
<Scene key="moviedetail" component={MovieDetail} hideNavBar={true} />
- 安装
yarn add react-native-image-picker
- link
react-native link
- 修改
AndroidManifest.xml
android
->app
->src
->main
->AndroidManifest.xml
文件,在第8行添加如下配置:
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
- 修改
MainActivity.java
android
->app
->src
->main
->java
->com
->当前项目名称文件夹
->MainActivity.java
文件,修改配置如下:
package com.native_camera;
import com.facebook.react.ReactActivity;
// 1. 添加以下 2 行:
import com.imagepicker.permissions.OnImagePickerPermissionsCallback;
import com.facebook.react.modules.core.PermissionListener;
public class MainActivity extends ReactActivity {
// 2. 添加如下 1 行:
private PermissionListener listener;
/**
* Returns the name of the main component registered from JavaScript.
* This is used to schedule rendering of the component.
*/
@Override
protected String getMainComponentName() {
return "native_camera";
}
}
- 使用
// 第1步:
import {View, Button, Image} from 'react-native'
import ImagePicker from 'react-native-image-picker'
var photoOptions = {
//底部弹出框选项
title: '请选择',
cancelButtonTitle: '取消',
takePhotoButtonTitle: '拍照',
chooseFromLibraryButtonTitle: '选择相册',
quality: 0.75,
allowsEditing: true,
noData: false,
storageOptions: {
skipBackup: true,
path: 'images'
}
}
// 第2步:
constructor(props) {
super(props);
this.state = {
imgURL: ''
}
}
// 第3步:
<Image source={{ uri: this.state.imgURL }} style={{ width: 200, height: 200 }}></Image>
<Button title="拍照" onPress={this.cameraAction}></Button>
// 第4步:
cameraAction = () => {
ImagePicker.showImagePicker(photoOptions, (response) => {
console.log('response' + response);
if (response.didCancel) {
return
}
this.setState({
imgURL: response.uri
});
})
}
- 重新进行打包部署
// 一次不行退出多试几次!
react-native run-android
- android/app/src/main/res/values/strings.xml`修改应用名称
- android\app\src\main\res\mipmap-xxxxxx`修改图标
-
先保证自己正确配置了所有的 RN 环境
-
在 cmd 命令行中,运行这一句话
keytool -genkey -v -keystore my-release-key.keystore -alias my-key-alias -keyalg RSA -keysize 2048 -validity 10000
- 其中:
my-release-key.keystore
表示你一会儿要生成的那个 签名文件的 名称【很重要,要找个小本本记下来】 -alias
后面的东西,也很重要,需要找个小本本记下来,这个名称可以根据自己的需求改动my-key-alias
- 当运行找个命令的时候,需要输入一系列的参数,找个口令的密码,【一定要找个小本本记下来】
-
当生成了签名之后,这个签名,默认保存到了自己的用户目录下
C:\Users\liulongbin\my-release-key.keystore
-
将你的签名证书copy到 android/app目录下。
-
编辑
android
->gradle.properties
文件,在最后,添加如下代码:
MYAPP_RELEASE_STORE_FILE=your keystore filename
MYAPP_RELEASE_KEY_ALIAS=your keystore alias
MYAPP_RELEASE_STORE_PASSWORD=*****
MYAPP_RELEASE_KEY_PASSWORD=*****
- 编辑 android/app/build.gradle文件添加如下代码:
// ...
android {
// ...
defaultConfig { ... }
+ signingConfigs {
+ release {
+ storeFile file(MYAPP_RELEASE_STORE_FILE)
+ storePassword MYAPP_RELEASE_STORE_PASSWORD
+ keyAlias MYAPP_RELEASE_KEY_ALIAS
+ keyPassword MYAPP_RELEASE_KEY_PASSWORD
+ }
+}
buildTypes {
release {
// ...
+ signingConfig signingConfigs.release
}
}
}
// ...
-
进入项目根目录下的
android
文件夹,打开终端,然后输入./gradlew assembleRelease
开始发布APK的Release版; -
当发行完毕后,进入自己项目的
android\app\build\outputs\apk
目录中,找到app-release.apk
,这就是我们发布完毕之后的完整安装包;就可以上传到各大应用商店供用户使用啦;