React Native跨平台开发学习笔记

App的分类(按开发方式)

大致可以分为这3种:

  • native app(原生app:ios或安卓)原生应用程序
    原生应用程序外观和运行起来(性能)是最佳的。可以访问本地资源,开法成本高。发布审核周期长。
  • web app/ H5 app (APIclound)H5应用程序
    整体量级轻,开发成本低,基于浏览器,可以跨平台使用。资源都在远程服务器。网速受到限制时,交互效果也会受到限制,页面跳转费力,不稳定感更强。无法操作很多手机原生设备,摄像头,麦克风,不支持多点触控等。
  • hybrid app(混合app)混合应用程序
    集原生应用程序和HTML5应用程序的优点(及缺点)于一体。速度快,跨平台。

ReactNative简介

React Native使你只使用JavaScript也能编写原生移动应用。它在设计原理上和React一致,通过声明式的组件机制来搭建丰富多彩的用户界面。

React Native最终产品很贴近移动应用,从使用感受上和用Objective-C或Java编写的应用相比几乎是无法区分的。React Native所使用的基础UI组件和原生应用完全一致。你要做的就是把这些基础组件使用JavaScript和React的方式组合起来。所以有React基础,那么学习RN会非常轻松。

ReactNative中文官网: https://reactnative.cn/

ReactNative学习

搭建环境

  1. 创建项目
    npx react-native init LifeServices --version 0.55.4
    LifeServices为项目名称
  2. 打包并运行项目
    yarn react-native run-android

自定义组件

代码笔记:

index.js:

import { AppRegistry } from 'react-native';
import App from './components/App1';

AppRegistry.registerComponent('AwesomeProject', () => App);

app.js:

// 1、自定义组件

// 1) 引入核心模块
import React, { Component } from "react"
import { View, Text, StyleSheet } from "react-native"

// 2) 创建并导出组件
export default class App1 extends Component {
  render() {
    return (
      <View style={styles.container}>
        <Text style={styles.txt1}>nihoa</Text>
      </View>
    )
  }
}

// 3) 样式代码
const styles = StyleSheet.create({
  txt1: {
    color: "red"
  },
  container: {
    backgroundColor: "#ccc"
  }
})

React Native跨平台开发学习笔记
实现效果:
React Native跨平台开发学习笔记

View组件 - 初步认识ScrollView组件

代码笔记:

app.js:

// 2、 View组件 初步认识ScrollView组件
// 1) 引入核心模块
import React, { Component } from "react"
import { View, Text, StyleSheet, ScrollView } from "react-native"

// 2) 创建并导出组件
export default class App2 extends Component {
  render() {
    return (
      <View style={styles.container}>
        {/* View组件默认情况下超出的内容不可见 */}
        {/* 把ScrollView加载需要出现滚动条的盒子内部,默认出现的是竖向滚动条  如果要横向添加horizontal属性 <ScrollView horizontal> */}
        <ScrollView>
          <Text style={styles.txt1}>易烊千玺!!!易烊千玺!!!易烊千玺!!!易烊千玺!!!易烊千玺!!!易烊千玺!!!易烊千玺!!!易烊千玺!!!易烊千玺!!!易烊千玺!!!文字超出不显示!!要用到ScrollView组件!!!</Text>
        </ScrollView>
      </View>
    )
  }
}

// 3) 样式代码
const styles = StyleSheet.create({
  txt1: {
    color: "red"
  },
  container: {
    width: 100,
    height: 100,
    backgroundColor: "pink"
  }
})

实现效果:
React Native跨平台开发学习笔记

获取屏幕的宽高和像素比

代码笔记:

app.js:

// 2、 View组件 初步认识ScrollView组件
import React, { Component } from "react"
import { View, Text, Dimensions } from "react-native"

const { width, height, scale } = Dimensions.get('window')

export default class App3 extends Component {
  render() {
    return (
      <View>
        {/* 获取的是可用范围的宽高 */}
        <Text>屏幕的宽度是:{width}</Text>
        <Text>屏幕的高度是:{height}</Text>
        <Text>屏幕的像素比是:{scale}</Text>
      </View>
    )
  }
}

实现效果:
React Native跨平台开发学习笔记

练习题

书写一个满屏的盒子 && 书写一条最细的线

代码笔记:

app.js:

// 4、练习题
// 1) 书写一个满屏的盒子
// 2) 书写一条最细的线(高度最小)
import React, { Component } from "react"
import { View, Text, Dimensions, StyleSheet } from "react-native"

const { width, height, scale } = Dimensions.get('window')

export default class App3 extends Component {
  render() {
    return (
      <View style={styles.container}>
        {/* 获取的是可用范围的宽高 */}
        <Text>屏幕的宽度是:{width}</Text>
        <Text>屏幕的高度是:{height}</Text>
        <Text>屏幕的像素比是:{scale}</Text>
        <View style={styles.line}></View>
      </View>
    )
  }
}
const styles = StyleSheet.create({
  container: {
    // width,
    // height,
    // width: "100%",
    // height: "100%",
    flex: 1,
    backgroundColor: "pink"
  },
  line: {
  	// 高 / 像素比
    height: 1 / scale,
    backgroundColor: "#000"
  }
})

实现效果:
React Native跨平台开发学习笔记

Flex布局

与CSS中的Flex布局类似:https://blog.csdn.net/qq_53472371/article/details/120919930

但是React Native要用 flexDirction\ alignItem\ justifyContent
React Native跨平台开发学习笔记
代码笔记:

// 5、flex布局
import React, { Component } from "react"
import { View, Text, StyleSheet } from "react-native"

export default class App5 extends Component {
  render() {
    return (
      <View style={styles.container}>
        <View style={styles.box1}><Text style={{ fontSize: 20 }}>1</Text></View>
        <View style={styles.box2}><Text style={{ fontSize: 40 }}>2</Text></View>
        <View style={styles.box3}><Text style={{ fontSize: 30 }}>3</Text></View>
      </View>
    )
  }
}

const styles = StyleSheet.create({
  container: {
    display: "flex",
    flex: 1,
    // 确定哪个是主轴
    // flexDirection的4个值:'row', 'row-reverse', 'column', 'column-reverse'
    flexDirection: "row",

    // 控制主轴对齐方式
    // justifyContent的4个值:'flex-start', 'flex-end', 'center', 'space-between', 'space-around'
    // justifyContent: "space-between"
    justifyContent: 'center',

    // 控制侧轴方向的对齐方式
    // alignItems的4个值:'flex-start', 'flex-end', 'center', 'stretch', 'baseline'
    // 'stretch' 设置侧轴方向上的拉伸,高度没有设置值,才能看到效果(要去掉高度属性)
    // 'baseline' 设置基线对齐,设置以文字底部来对齐
    // alignItems: 'baseline'
    alignItems: 'center'
  },
  box1: {
    width: 100,
    height: 100,
    backgroundColor: "#ccc"
  },
  box2: {
    width: 100,
    height: 100,
    backgroundColor: "#fcf"
  },
  box3: {
    width: 100,
    height: 100,
    backgroundColor: "#ffc"
  },
})

Flex布局练习

代码笔记:

// 6、Flex布局练习
import React, { Component } from "react"
import { View, Text, StyleSheet, Dimensions } from "react-native"

const { width, height, scale } = Dimensions.get('window')

// 抽组件
class Row extends Component {
  render() {
    return (
      <View style={styles.row}>
        <View style={styles.box1}><Text>1</Text></View>
        <View style={styles.box2}><Text>2</Text></View>
        <View style={styles.box3}><Text>3</Text></View>
      </View>
    )
  }
}

export default class App6 extends Component {
  render() {
    return (
      <View style={styles.container}>
        <Text style={{ fontSize: 18 }}>Flex布局练习</Text>
        <View style={styles.boxs}>
          <Row />
          <Row />
          <Row />
        </View>
      </View>
    )
  }
}

const styles = StyleSheet.create({
  container: {
    flexDirection: 'column',
    alignItems: 'center',
    paddingTop: 80
  },
  boxs: {
    width: width * 0.9,    // 0.9倍的屏幕宽度
    height: 200,
    backgroundColor: "#ccc",
    marginTop: 10
  },
  row: {
    flex: 1,
    borderWidth: 1,
    borderColor: "#000",
    // 设置主轴方向为水平
    flexDirection: "row"
  },
  box1: {
    flex: 1.5,
    borderWidth: 1,
    borderColor: "#f00",
  },
  box2: {
    flex: 1,
    borderWidth: 1,
    borderColor: "#f00",
  },
  box3: {
    flex: 2,
    borderWidth: 1,
    borderColor: "#f00",
  }
})

实现效果:
React Native跨平台开发学习笔记

Button按钮组件

代码笔记:

app.js:

// Button按钮组件
import React, { Component } from "react"
import { View, Text, StyleSheet, Button } from "react-native"


export default class App7 extends Component {

  constructor(props) {
    super(props)

    this.state = {
      num: 20
    }

    // this的指向问题
    this.handlePress = this.handlePress.bind(this)
  }

  handlePress() {
    // alert(123);
    this.setState({
      num: this.state.num + 1
    })
  }

  render() {
    return (
      <View>
        <Text>{this.state.num}</Text>
        <Button title="按钮中的文本" color="skyblue" onPress={this.handlePress} style={styles.btn}></Button>
      </View>
    )
  }
}

// Button按钮组件不能修改样式!!!
const styles = StyleSheet.create({
  btn: {
    width: 150,
    height: 100
  }
})

自定义按钮组件TouchableOpacity

因为Button样式本身有局限性TouchableOpacity组件可以*定义组件样式。

代码笔记:

app.js:

// Button按钮组件
import React, { Component } from "react"
import { View, Text, StyleSheet, Button, TouchableOpacity } from "react-native"


export default class App7 extends Component {

  constructor(props) {
    super(props)

    this.state = {
      num: 20
    }

    // this的指向问题
    this.handlePress = this.handlePress.bind(this)
  }

  handlePress() {
    // alert(123);
    this.setState({
      num: this.state.num + 1
    })
  }

  render() {
    return (
      <View>
        <Text>{this.state.num}</Text>
        <Button title="按钮中的文本" color="skyblue" onPress={this.handlePress} style={styles.btn}></Button>

        <TouchableOpacity onPress={this.handlePress} style={styles.btn}><Text>点击自增</Text></TouchableOpacity>

      </View>
    )
  }
}

// Button按钮组件不能修改样式
const styles = StyleSheet.create({
  btn: {
    width: 100,
    height: 100,
    backgroundColor: "pink",
    borderRadius: 50,
    justifyContent: "center",
    alignItems: "center"
  }
})

实现效果:
React Native跨平台开发学习笔记

Image组件

引入方式:
React Native跨平台开发学习笔记
代码笔记:

// 8、Image组件
import React, { Component } from "react"
import { View, Text, Image, StyleSheet } from "react-native"

import Img from "../res/logo.png"

export default class App5 extends Component {
  render() {
    return (
      <View>

        <Text>方式1:</Text>
        <Image source={Img} />

        <Text>方式2:</Text>
        <Image source={require("../res/logo.png")} />

        <Text>方式3:</Text>
        <Image source={{ uri: "https://img-home.csdnimg.cn/images/20201124032511.png" }} style={styles.img} />

      </View>
    )
  }
}
const styles = StyleSheet.create({
  img: {
    width: 300,
    height: 100
  }
})

实现效果:
React Native跨平台开发学习笔记

WebView组件

WebView组件相当于在app内部内嵌一个浏览器,可以通过它的source属性中的uri,写入对应的网页地址,从而展示一个页面。

代码笔记:

// 9、WebView组件
import React, { Component } from "react"
import { WebView } from "react-native"


export default class App9 extends Component {
  render() {
    return (

      <WebView source={{ uri: "https://m.jd.com/" }}></WebView>

    )
  }
}

图片的另一种引入方式

React Native跨平台开发学习笔记

代码笔记:

// 图片的另一种引入方式
import React, { Component } from "react"
import { View, Image, Text, StyleSheet } from "react-native"


export default class App5 extends Component {
  render() {
    return (
      <View>
        <Text>图片的另一种引入方式</Text>
        {/* avatar:图片名称 */}
        <Image source={{ uri: "avatar" }} style={{ width: 300, height: 100 }} />
      </View>
    )
  }
}

实现效果:
React Native跨平台开发学习笔记

FlatList组件的使用

代码笔记:

// FlatList组件的使用
import React, { Component } from "react"
import { View, FlatList, Text } from "react-native"

const arr_data = [
  {
    id: 1,
    data: 10
  },
  {
    id: 2,
    data: 20
  },
  {
    id: 3,
    data: 30
  },
  {
    id: 4,
    data: 40
  },
]

export default class App11 extends Component {
  constructor(props) {
    super(props)
    this.state = {
      arr_data
    }
  }
  renderData({ item }) {   // 这个函数决定了每一项的展示方式    item就是每一项数据
    return (
      <Text>{item.id}、{item.data}</Text>
    )
  }
  render() {
    return (
      <View>
        <FlatList
          numColumns={1}  // 每行显示的个数
          data={this.state.arr_data}  // 数据源
          renderItem={this.renderData}// 渲染函数

        />
      </View>
    )
  }
}

图片展示的练习

代码示例:


import React, { Component } from "react"
import { View, Text, Image, FlatList, StyleSheet } from "react-native"

const img_data = [
  {
    name: "p01",
    des: "111"
  },
  {
    name: "p02",
    des: "222"
  },
  {
    name: "p03",
    des: "333"
  },
  {
    name: "p04",
    des: "444"
  },
  {
    name: "p05",
    des: "555"
  },
  {
    name: "p06",
    des: "666"
  },
]

export default class App5 extends Component {
  constructor(props) {
    super(props)
    this.state = {
      img_data
    }
  }

  renderData({ item }) {
    return (
      <View>
        <Image source={{ uri: item.name }} style={styles.imgContent} />
        <Text style={styles.txtContent} >{item.des}</Text>
      </View>
    )
  }

  render() {
    return (
      <View style={styles.container}>

        <Image source={require("../res/tit_50x16.png")} style={styles.imgTitle} />

        <FlatList
          numColumns={3}  // 每行显示的个数
          data={this.state.img_data}  // 数据源
          renderItem={this.renderData}// 渲染函数

        />

      </View>
    )
  }
}
const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: "#ccc",
    paddingLeft: 10,
    paddingRight: 10,
  },
  imgTitle: {
    width: 50,
    height: 16,
    marginTop: 10,
    marginBottom: 10
  },
  imgContent: {
    width: 100,
    height: 100,
    marginRight: 20
  },
  txtContent: {
    width: 100,
    height: 18,
    marginBottom: 10
  }
})

实现效果:
React Native跨平台开发学习笔记

TextInput组件

代码笔记:

// TextInput组件
import React, { Component } from "react"
import { View, Text, TextInput, StyleSheet } from "react-native"


export default class App5 extends Component {
  render() {
    return (
      <View>
        <TextInput style={styles.txtInput}
          placeholder="请输入..."   // 占位符设置(提示文本)
          placeholderTextColor="#ccc"   // 占位符颜色设置
          maxLength={6}   // 可以输入的最大长度
          underlineColorAndroid="transparent"   // 底线设置透明
        // secureTextEntry={true}    // 安卓下的密码设置
        />
      </View>
    )
  }
}
const styles = StyleSheet.create({
  txtInput: {
    borderWidth: 1,
    borderColor: "#000",
    marginTop: 50,
    // 有自带padding 可以去掉padding
    padding: 0,
    height: 40
  }
})

登录界面的实现

代码示例:

import React, { Component } from "react"
import { View, Text, StyleSheet, Dimensions, Image, TextInput, TouchableOpacity } from "react-native"

const { width, height, scale } = Dimensions.get('window')

export default class App14 extends Component {
  render() {
    return (
      <View style={styles.container}>
        <View style={styles.wrap}>

          {/* 头像 */}
          <Image source={require("../res/avatar.jpg")} style={styles.avatar} />

          {/* 用户名 */}
          {/* 具备多个样式的写法格式:style={[styles.txtInput, styles.username]} */}
          <TextInput style={[styles.txtInput, styles.username]}
            placeholder="请输入用户名"
            placeholderTextColor="#ddd"
            underlineColorAndroid="transparent"
          />

          {/* 密码 */}
          <TextInput style={styles.txtInput}
            placeholder="请输入密码"
            placeholderTextColor="#ddd"
            underlineColorAndroid="transparent"
          />

          {/* 登录按钮 */}
          <TouchableOpacity style={styles.loginBtn} activeOpacity={0.7}>
            {/* 和文字相关的属性,都加在Text组件上(无继承效果) */}
            <Text style={styles.loginTxt}>登 录</Text>
          </TouchableOpacity>

          {/* 忘记密码&&注册新用户 */}
          <View style={styles.btns}>
            <TouchableOpacity activeOpacity={0.9}>
              <Text>忘记密码</Text>
            </TouchableOpacity>
            <TouchableOpacity activeOpacity={0.9}>
              <Text>注册新用户</Text>
            </TouchableOpacity>

          </View>

          {/* 其他方式登录 */}
          <View style={styles.bottomBox}>
            <View style={styles.line}></View>
            <Text style={styles.bottomTxt}>其他方式登录</Text>
            <View style={styles.bottomImages}>
              <TouchableOpacity activeOpacity={0.9}>
                <Image source={require("../res/icon1.png")} style={styles.bottomImage} />
              </TouchableOpacity>
              <TouchableOpacity activeOpacity={0.9}>
                <Image source={require("../res/icon2.png")} style={[styles.bottomImage, styles.bottomImageSnd]} />
              </TouchableOpacity>
              <TouchableOpacity activeOpacity={0.9}>
                <Image source={require("../res/icon3.png")} style={styles.bottomImage} />
              </TouchableOpacity>
            </View>
          </View>


        </View>
      </View>
    )
  }
}
const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: "#eee",
    alignItems: "center"
  },
  wrap: {
    width: 320,
    height,
    // backgroundColor: "#ccc",
    alignItems: "center"
  },
  avatar: {
    width: 60,
    height: 60,
    borderRadius: 30,
    borderWidth: 1,
    borderColor: "#fff",
    marginTop: 50,
    marginBottom: 30
  },
  txtInput: {
    width: 320,
    height: 40,
    backgroundColor: "#fff"
  },
  username: {
    marginBottom: 5
  },
  loginBtn: {
    width: 320,
    height: 30,
    alignItems: "center",
    justifyContent: "center",
    backgroundColor: "skyblue",
    marginTop: 20,
    borderRadius: 4
  },
  loginTxt: {
    color: "#fff"
  },
  btns: {
    width: "100%",
    flexDirection: "row",
    justifyContent: "space-between",
    marginTop: 10
  },
  line: {
    width: "100%",
    height: 1 / scale,
    backgroundColor: "#999"
  },
  bottomBox: {
    width: "100%",
    position: "absolute",
    bottom: 40,
    alignItems: "center"
  },
  bottomTxt: {
    width: 100,
    marginTop: -8,
    backgroundColor: "#eee",
    textAlign: "center",
    fontSize: 12
  },
  bottomImages: {
    flexDirection: "row",
    // justifyContent: "center",
    marginTop: 10
  },
  bottomImage: {
    width: 40,
    height: 40,
    borderRadius: 20
  },
  bottomImageSnd: {
    marginLeft: 15,
    marginRight: 15
  }
})

实现效果:
React Native跨平台开发学习笔记

ScrollView组件的使用

使用ScrollView组件实现横向多屏:

代码示例:

// ScrollView组件的使用
import React, { Component } from "react"
import { View, Text, StyleSheet, Dimensions, ScrollView } from "react-native"

export default class App5 extends Component {
  render() {
    return (
      <View>
        <ScrollView
          horizontal={true}   // 水平排列
          pagingEnabled={true}    // 滚动条倍数滚动
          showsHorizontalScrollIndicator={false}    // 不显示横向滚动条(用小圆点代替)
        >
          <View style={styles.box}><Text>1</Text></View>
          <View style={[styles.box, styles.box2]}><Text>2</Text></View>
        </ScrollView>
      </View>
    )
  }
}
const styles = StyleSheet.create({
  box: {
    width: 411,
    height: 200,
    backgroundColor: "#ccc"
  },
  box2: {
    backgroundColor: "#fcf"
  }
})

图片和文字的展示案例

代码示例:

// 图片和文字的展示案例
import React, { Component } from "react"
import { View, Text, StyleSheet, Dimensions, ScrollView, Image } from "react-native"

export default class App5 extends Component {
  render() {
    return (
      <View>
        <ScrollView
          horizontal={true}   // 水平排列
          pagingEnabled={true}    // 滚动条倍数滚动
          showsHorizontalScrollIndicator={false}    // 不显示横向滚动条(用小圆点代替)
        >
          <View style={styles.box}>
            <Image source={require("../res/banner1.png")} style={styles.img} />
            <Text style={styles.title}>啦啦啦1</Text>
          </View>
          <View style={styles.box}>
            <Image source={require("../res/banner2.png")} style={styles.img} />
            <Text style={styles.title}>啦啦啦2</Text>
          </View>
          <View style={styles.box}>
            <Image source={require("../res/banner3.png")} style={styles.img} />
            <Text style={styles.title}>啦啦啦3</Text>
          </View>
        </ScrollView>
      </View>
    )
  }
}
const styles = StyleSheet.create({
  box: {
    width: 411,
    height: 220
  },
  img: {
    width: 411,
    height: 220
  },
  title: {
    width: 411,
    height: 30,
    lineHeight: 30,
    backgroundColor: "rgba(0, 0, 0, 0.5)",
    position: "absolute",
    bottom: 0,
    color: "#fff",
    paddingLeft: 10
  }
})

实现效果:(可滑动)
React Native跨平台开发学习笔记

自动轮播&&无缝滚动效果的实现

代码笔记:

// 自动轮播&&无缝滚动效果
// 原理:当看到第4张图片的时候,瞬间切换到第1张
import React, { Component } from "react"
import { View, Text, StyleSheet, Dimensions, ScrollView, Image } from "react-native"
const { width } = Dimensions.get("window")

export default class App1 extends Component {

  componentDidMount() {
    let scrollview = this.refs.scrollview   // 获取ScrollView组件对象
    let num = 0

    // 每隔几秒滑动1次
    setInterval(() => {
      num++;
      if (num === 4) {    // 多补的这张图片需要被看见,所以num可以等于3
        num = 1

        // 瞬间切换到第1张(不要带动画效果)
        scrollview.scrollTo({ x: 0, y: 0, animated: false })

      }
      // 在上面判断中已经是第一张,即下一张是第二张,第二张num就应该为1
      scrollview.scrollTo({ x: num * width, y: 0, animated: true })
    }, 2000);

  }

  render() {
    return (
      <View>
        <ScrollView
          ref="scrollview"
          horizontal={true}   // 水平排列
          pagingEnabled={true}    // 滚动条倍数滚动
          showsHorizontalScrollIndicator={false}    // 不显示横向滚动条(用小圆点代替)
        >
          <View style={styles.box}>
            <Image source={require("../res/banner1.png")} style={styles.img} />
            <Text style={styles.title}>啦啦啦1</Text>
          </View>
          <View style={styles.box}>
            <Image source={require("../res/banner2.png")} style={styles.img} />
            <Text style={styles.title}>啦啦啦2</Text>
          </View>
          <View style={styles.box}>
            <Image source={require("../res/banner3.png")} style={styles.img} />
            <Text style={styles.title}>啦啦啦3</Text>
          </View>
          <View style={styles.box}>
            <Image source={require("../res/banner1.png")} style={styles.img} />
            <Text style={styles.title}>啦啦啦1</Text>
          </View>
        </ScrollView>
      </View>
    )
  }
}
const styles = StyleSheet.create({
  box: {
    width: 411,
    height: 220
  },
  img: {
    width: 411,
    height: 220
  },
  title: {
    width: 411,
    height: 30,
    lineHeight: 30,
    backgroundColor: "rgba(0, 0, 0, 0.5)",
    position: "absolute",
    bottom: 0,
    color: "#fff",
    paddingLeft: 10
  }
})

使用react-native-swiper实现轮播图

基本使用

react-native-swiper:是专门用来实现轮播图的模块

  • 安装:npm i react-native-swiper --save
  • 查看:npm view react-native-swiper
  • 删除:npm rm react-native-swiper --save

React Native跨平台开发学习笔记
React Native跨平台开发学习笔记
React Native跨平台开发学习笔记
代码笔记:

// 使用react-native-swiper实现轮播图
import React, { Component } from "react"
import { View, Text, StyleSheet, Dimensions } from "react-native"

import Swiper from "react-native-swiper"

const { width, height, scale } = Dimensions.get('window')

export default class App3 extends Component {
  render() {
    return (
      <View style={styles.container}>

        <Swiper style={styles.wrapper} horizontal={true} autoplay autoplayTimeout={2} showsButtons={true} showsPagination={false}>
          <View style={styles.slide1}>
            <Text style={styles.text}>hhh</Text>
          </View>
          <View style={styles.slide2}>
            <Text style={styles.text}>lll</Text>
          </View>
          <View style={styles.slide3}>
            <Text style={styles.text}>yyy</Text>
          </View>
        </Swiper>

      </View>
    )
  }
}
const styles = StyleSheet.create({
  container: {
    height: 200,
  },
  wrapper: {

  },
  slide: {
    flex: 1,
    justifyContent: "center",
    backgroundColor: "transparent"
  },
  slide1: {
    flex: 1,
    justifyContent: "center",
    alignItems: "center",
    backgroundColor: "#9DD6EB"
  },
  slide2: {
    flex: 1,
    justifyContent: "center",
    alignItems: "center",
    backgroundColor: "#fcc"
  },
  slide3: {
    flex: 1,
    justifyContent: "center",
    alignItems: "center",
    backgroundColor: "#cff"
  },
  text: {
    color: "#fff",
    fontSize: 30,
    fontWeight: "bold"
  }
})

实现效果:
React Native跨平台开发学习笔记

实现轮播图

代码示例:

// 使用react-native-swiper实现完整的轮播图(加入图片)
import React, { Component } from "react"
import { View, Text, StyleSheet, Image } from "react-native"

import Swiper from "react-native-swiper"


export default class App4 extends Component {
  render() {
    return (
      <View style={styles.container}>

        <Swiper style={styles.wrapper}
          horizontal={true}
          autoplay
          autoplayTimeout={2}
          // showsButtons={true}
          // showsPagination={false}
          dot={<View style={{ backgroundColor: "#ccc", width: 8, height: 8, borderRadius: 4, marginLeft: 3, marginRight: 3, marginTop: 3, marginBottom: 3 }} />}
          activeDot={<View style={{ backgroundColor: "yellow", width: 8, height: 8, borderRadius: 4, marginLeft: 3, marginRight: 3, marginTop: 3, marginBottom: 3 }} />}
          paginationStyle={{
            bottom: 5, left: null, right: 10
          }}
        >
          <View style={styles.slide1}>
            <Image source={require("../res/banner1.png")} style={styles.img} />
            <Text style={styles.title}>啦啦啦1</Text>
          </View>
          <View style={styles.slide2}>
            <Image source={require("../res/banner2.png")} style={styles.img} />
            <Text style={styles.title}>啦啦啦1</Text>
          </View>
          <View style={styles.slide3}>
            <Image source={require("../res/banner3.png")} style={styles.img} />
            <Text style={styles.title}>啦啦啦1</Text>
          </View>
        </Swiper>

      </View >
    )
  }
}
const styles = StyleSheet.create({
  container: {
    height: 200,
  },
  wrapper: {

  },
  slide: {
    flex: 1,
    justifyContent: "center",
    backgroundColor: "transparent"
  },
  slide1: {
    flex: 1,
    justifyContent: "center",
    alignItems: "center",
    backgroundColor: "#9DD6EB"
  },
  slide2: {
    flex: 1,
    justifyContent: "center",
    alignItems: "center",
    backgroundColor: "#fcc"
  },
  slide3: {
    flex: 1,
    justifyContent: "center",
    alignItems: "center",
    backgroundColor: "#cff"
  },
  img: {
    width: 411,
    height: 220
  },
  title: {
    width: 411,
    height: 30,
    lineHeight: 30,
    backgroundColor: "rgba(0, 0, 0, 0.5)",
    position: "absolute",
    bottom: 0,
    color: "#fff",
    paddingLeft: 10
  }
})

实现效果:
React Native跨平台开发学习笔记

适配其他分辨率的做法

每种机型的Dimensions宽度、高度、像素比是有可能不一样的。
React Native跨平台开发学习笔记
React Native跨平台开发学习笔记

关闭所有黄色警告的代码

index.js:

import { AppRegistry } from 'react-native';
import App from './components/App16';

// 关闭全部黄色警告
console.ignoredYellowBox = ['Warning: BackAndroid is deprecated. Please use BackHandler instead.', 'source.uri should not be an empty string', 'Invalid props.style key'];

console.disableYellowBox = true

AppRegistry.registerComponent('AwesomeProject', () => App);

stackNavigator组件

stackNavigator的基本使用

代码笔记:

Page1.js:


import React, { Component } from "react"
import { View, Text, StyleSheet } from "react-native"


export default class Page1 extends Component {
  render() {
    return (
      <View>
        <Text>page1</Text>
      </View>
    )
  }
}

App.js:

import React, { Component } from "react"
import { View, Text, StyleSheet, Button } from "react-native"

import { StackNavigator } from "react-navigation"
import Page1 from "./pages/Page1"

class Home extends Component {
  render() {
    return (
      <View>
        <Button title="点击跳转到Page1" onPress={() => this.props.navigation.navigate("Page1")} />
      </View>
    )
  }
}

export default StackNavigator({
  Home: {
    screen: Home,    // 对应组件
  },
  Page1: {
    screen: Page1,    // 对应组件

  }
}, {
  headerMode: "none"   // 隐藏顶部的导航栏

})

stackNavigator的传参使用和返回

React Native跨平台开发学习笔记
代码笔记:

App.js:


import React, { Component } from "react"
import { View, Text, StyleSheet, Button } from "react-native"

import { StackNavigator } from "react-navigation"
import Page2 from "./pages/Page2"

class Home extends Component {
  render() {
    return (
      <View>
        {/* <Button title="点击跳转到Page2" onPress={() => this.props.navigation.navigate("Page2")} /> */}
        <Text>这是Home页面</Text>
        <Text onPress={() => this.props.navigation.navigate("Page2", { name: "yyqx" })}>点击跳转到Page2</Text>
      </View>
    )
  }
}

export default StackNavigator({
  Home: {
    screen: Home,    // 对应组件
  },
  Page2: {
    path: "page2/:name",
    screen: Page2,    // 对应组件

  }
}, {
  headerMode: "none"   // 隐藏顶部的导航栏

})

Page2.js:

import React, { Component } from "react"
import { View, Text, StyleSheet, Button } from "react-native"


export default class Page2 extends Component {
  render() {
    const { navigation } = this.props
    return (
      <View>
        <Text>Page2</Text>
        <Text>接收到的参数为:{navigation.state.params.name}</Text>
        <Button title="返回Home页面" onPress={() => { navigation.goBack() }} />
      </View>
    )
  }
}

stackNavigator的一些样式配置

代码笔记:

// stackNavigator配置项
import React, { Component } from "react"
import { View, Text, StyleSheet, Button } from "react-native"

import { StackNavigator } from "react-navigation"
import Page1 from "./pages/Page1"

class Home extends Component {
  render() {
    return (
      <View>
        <Button title="点击跳转到Page1" onPress={() => this.props.navigation.navigate("Page1")} />
      </View>
    )
  }
}

export default StackNavigator({
  Home: {
    screen: Home,    // 对应组件
    navigationOptions: {
      title: "Home首页"
    }
  },
  Page1: {
    screen: Page1,    // 对应组件
    navigationOptions: {
      // header: null
      headerStyle: {
        backgroundColor: "#fcf",
        height: 40
      },
      headerTitleStyle: {
        color: "#333"
      }
    }
  }
}, {
  // 全局的配置
  navigationOptions: {
    title: "默认界面标题",
    headerStyle: {
      backgroundColor: "#f40",
      height: 40
    },
    headerTitleStyle: {
      color: "#fff"
    }
  }
})

实现效果:
React Native跨平台开发学习笔记

DrawerNavigator组件

DrawerNavigator的基本使用(打开抽屉)

DrawerNavigator组件可以用来制作抽屉类型的导航,也可以用来制作自定义内容的抽屉

点击函数中通过:this.props.navigation.openDrawer() 打开抽屉。

代码笔记:

App.js:

// DrawerNavigator的基本使用
import React, { Component } from 'react'
import { Button, View } from 'react-native'

import { DrawerNavigator } from "react-navigation"

class Home extends Component {
  render() {
    return (
      <View>
        {/* this.props.navigation.openDrawer() 打开抽屉 */}
        <Button title="点击打开抽屉" onPress={() => { this.props.navigation.openDrawer() }} />
      </View>
    )
  }
}
export default DrawerNavigator({
  Home: {
    screen: Home
  }
})

实现效果:
React Native跨平台开发学习笔记
React Native跨平台开发学习笔记

DrawerNavigator的核心使用

代码笔记:

// DrawerNavigator的核心使用
import React, { Component } from 'react'
import { Button, View, Text } from 'react-native'

import { DrawerNavigator } from "react-navigation"

class Home extends Component {
  render() {
    return (
      <View>
        {/* this.props.navigation.openDrawer() 打开抽屉 */}
        <Button title="点击打开抽屉" onPress={() => { this.props.navigation.openDrawer() }} />
      </View>
    )
  }
}

class Page1 extends Component {
  render() {
    return (
      <View>
        <Text>这里是Page1</Text>
        <Button title="点击返回" onPress={() => { this.props.navigation.goBack() }} />
      </View>
    )
  }
}

class Page2 extends Component {
  render() {
    return (
      <View>
        <Text>这里是Page2</Text>
        <Button title="点击返回" onPress={() => { this.props.navigation.goBack() }} />
      </View>
    )
  }
}

export default DrawerNavigator({
  Home: {
    screen: Home
  },
  Page1: {
    screen: Page1
  },
  Page2: {
    screen: Page2
  },
})

实现效果:
React Native跨平台开发学习笔记
React Native跨平台开发学习笔记
React Native跨平台开发学习笔记

DrawerNavigator的一些配置,以及自定义抽屉内容

代码笔记:

// DrawerNavigator的一些配置,以及自定义抽屉内容
import React, { Component } from 'react'
import { Button, View, Text, ScrollView } from 'react-native'

import { DrawerItems, DrawerNavigator, SafeAreaView } from "react-navigation"

class Home extends Component {
  render() {
    return (
      <View>
        {/* this.props.navigation.openDrawer() 打开抽屉 */}
        <Button title="点击打开抽屉" onPress={() => { this.props.navigation.openDrawer() }} />
      </View>
    )
  }
}

class Page1 extends Component {
  render() {
    return (
      <View>
        <Text>这里是Page1</Text>
        <Button title="点击返回" onPress={() => { this.props.navigation.goBack() }} />
      </View>
    )
  }
}


export default DrawerNavigator({
  Home: {
    screen: Home
  },
  Page1: {
    screen: Page1
  }
}, {
  drawerWidth: 200,
  drawerPosition: "right",
  // 自定义
  contentComponent: (props) => (
    <ScrollView style={{ backgroundColor: "#ccc", flex: 1 }}>
      {/* <SafeAreaView forceInset={{ top: "always", horizontal: "never" }}>
        <DrawerItems {...props} />
      </SafeAreaView> */}
      <Text>设置其他组件</Text>
    </ScrollView>
  )
})

实现效果:
React Native跨平台开发学习笔记

从自定义抽屉中传递参数到页面

代码笔记:

// DrawerNavigator 从自定义抽屉向页面传递参数
import React, { Component } from 'react'
import { Button, View, Text, ScrollView } from 'react-native'

import { DrawerItems, DrawerNavigator, SafeAreaView } from "react-navigation"

class Home extends Component {
  render() {
    return (
      <View>
        {/* this.props.navigation.openDrawer() 打开抽屉 */}
        <Button title="点击打开抽屉" onPress={() => { this.props.navigation.openDrawer() }} />
      </View>
    )
  }
}

class Page1 extends Component {
  render() {
    const { navigation } = this.props
    return (
      <View>
        <Text>这里是Page1</Text>
        <Button title="点击返回" onPress={() => { this.props.navigation.goBack() }} />
        <Text>收到的参数为:{navigation.state.params.name}</Text>
      </View>
    )
  }
}


export default DrawerNavigator({
  Home: {
    screen: Home
  },
  Page1: {
    screen: Page1
  }
}, {
  drawerWidth: 200,
  drawerPosition: "right",
  // 自定义
  contentComponent: (props) => (
    <ScrollView style={{ backgroundColor: "#ccc", flex: 1 }}>
      {/* <SafeAreaView forceInset={{ top: "always", horizontal: "never" }}>
        <DrawerItems {...props} />
      </SafeAreaView> */}
      <Button
        title="点击跳转到Page1"
        onPress={() => props.navigation.navigate("Page1", { name: "yyqx" })}
      />
    </ScrollView>
  )
})

实现效果:
React Native跨平台开发学习笔记
React Native跨平台开发学习笔记

使用FlatList组件实现下拉刷新

》》》要学会思路!!!

代码笔记:

// 使用FlatList组件实现下拉刷新
import React, { Component } from 'react'
import { FlatList, View, Text, StyleSheet } from 'react-native'

const CITY_NAMES = ["北京市", "上海市", "深圳市", "广州市", "成都", "杭州"]

export default class App extends Component {

  constructor(props) {
    super(props)
    this.state = {
      isLoading: false,
      dataArr: CITY_NAMES
    }
  }

  renderData({ item }) {
    return (
      <View style={styles.itemBox}>
        <Text style={styles.itemTxt}>{item}</Text>
      </View>
    )
  }

  loadData() {
    // 1、修改isLoading的值为true
    this.setState({
      isLoading: true
    })

    // 2、模拟异步请求
    setTimeout(() => {
      let newData = CITY_NAMES.reverse()   // 把数组反转,模拟新的数据的获取
      this.setState({
        dataArr: newData,
        isLoading: false
      })
    }, 1000);
  }

  render() {
    return (
      <View>
        <FlatList
          // numColumns=
          data={this.state.dataArr}
          renderItem={this.renderData}

          refreshing={this.state.isLoading}   // 设置是否正在加载数据
          onRefresh={this.loadData.bind(this)}    // 设置刷新的时候执行的代码

        />
      </View>
    )
  }
}
const styles = StyleSheet.create(
  {
    itemBox: {
      width: 360,
      height: 200,
      backgroundColor: "#ccc",
      marginLeft: 20,
      marginBottom: 15
    },
    itemTxt: {
      textAlign: "center",
      lineHeight: 200
    }
  }
)

实现效果:
React Native跨平台开发学习笔记

使用FlatList组件实现滑动到底部加载更多(上拉加载更多)

React Native跨平台开发学习笔记
代码笔记:

// 使用FlatList组件实现下拉刷新
import React, { Component } from 'react'
import { FlatList, View, Text, StyleSheet, ActivityIndicator } from 'react-native'

const CITY_NAMES = ["北京市", "上海市", "深圳市", "广州市"]

export default class App extends Component {

  constructor(props) {
    super(props)
    this.state = {
      isLoading: false,
      dataArr: CITY_NAMES
    }
  }

  renderData({ item }) {
    return (
      <View style={styles.itemBox}>
        <Text style={styles.itemTxt}>{item}</Text>
      </View>
    )
  }

  loadData() {
    // 1、修改isLoading的值为true
    this.setState({
      isLoading: true
    })

    // 2、模拟异步请求
    setTimeout(() => {
      let newData = this.state.dataArr.concat(CITY_NAMES)   // 合并,数据变长
      this.setState({
        dataArr: newData,
        isLoading: false
      })
    }, 1000);
  }

  genIndicator() {    // 加载符号的制作
    return (
      <View>
        <ActivityIndicator
          size="large"
          animating={true}
          color="#ccc"
        />
        <Text style={{ textAlign: "center", flex: 1, marginBottom: 10 }}>正在加载数据...</Text>
      </View>
    )
  }

  render() {
    return (
      <View>
        <FlatList
          // numColumns=
          data={this.state.dataArr}
          renderItem={this.renderData}

          ListFooterComponent={this.genIndicator}   // 确定加载的符号
          onEndReached={this.loadData.bind(this)}
        />
      </View>
    )
  }
}
const styles = StyleSheet.create(
  {
    itemBox: {
      width: 360,
      height: 200,
      backgroundColor: "#ccc",
      marginLeft: 20,
      marginBottom: 15
    },
    itemTxt: {
      textAlign: "center",
      lineHeight: 200
    }
  }
)

实现效果:
React Native跨平台开发学习笔记

AsyncStorage的使用

React Native跨平台开发学习笔记
代码笔记:

// AsyncStorage存储
import React, { Component } from 'react'
import { AsyncStorage, Button, TextInput, View } from 'react-native'

export default class App14 extends Component {
  constructor(props) {
    super(props)
    this.state = {
      val: ""
    }
  }

  handleChange(text) {
    this.setState({
      val: text
    })
  }

  // handPress() {
  //   alert(this.state.val)
  // }

  save() {
    AsyncStorage.setItem("key", this.state.val, (error) => {
      if (!error) {
        alert("保存成功")
      } else {
        alert("保存失败")
      }
    })
  }

  get() {
    AsyncStorage.getItem("key", (error, result) => {
      if (!error) {
        alert("获取成功,值为:" + result)
      } else {
        alert("获取失败")
      }
    })
  }

  remove() {
    AsyncStorage.removeItem("key", (error) => {
      if (!error) {
        alert("删除成功")
      } else {
        alert("删除失败")
      }
    })
  }

  render() {
    return (
      <View>
        <TextInput placeholder="请输入..." onChangeText={this.handleChange.bind(this)} />
        {/* <Button title="获取value" onPress={this.handPress.bind(this)} /> */}
        <Button title="保存数据" onPress={this.save.bind(this)} />
        <Button title="获取数据" onPress={this.get} />
        <Button title="删除数据" onPress={this.remove} />
      </View>
    )
  }
}

实现效果:
React Native跨平台开发学习笔记
React Native跨平台开发学习笔记

React Native项目

项目文件夹

React Native跨平台开发学习笔记

导航页面的初步实现(TabNavigator)

React Native跨平台开发学习笔记

在项目中获取周边数据

项目目录下安装axiosyarn add axios@0.18.0

项目完成

上一篇:1.React 组件介绍


下一篇:第二十三篇,数据结构(起始篇)—单向链表。