【前言】
(二)中 我们一起学习了属性和布局,现在,我们开始往layout内增加一些组件。
目录标题
三 组件和api
简介 RN 中的核心组件
RN 中的核心组件,是对原生组件的封装
- 原生组件: Android或ios内的组件
- 核心组件:RN中最常用的,来在 react-native 的组件
开发 React Native 应用程序时,通常会使用以下核心组件:
View(视图):View 是 React Native 中最基本的组件之一,用于创建布局结构。它类似于 web 开发中的
Text(文本):Text 组件用于显示文本内容,类似于 HTML 中的 或
元素。你可以在 Text 组件中显示静态文本或动态生成的文本。
TouchableOpacity(触摸透明度):TouchableOpacity 是一个用于处理用户触摸操作的组件。当用户触摸组件时,TouchableOpacity 会在视觉上降低其透明度,以提供触摸的视觉反馈。
Dimensions(尺寸):Dimensions 组件用于获取设备屏幕的尺寸信息,包括屏幕宽度和高度。这在创建响应式布局时非常有用。
StyleSheet(样式表):StyleSheet 是用于创建和管理样式的工具,类似于 CSS 样式表。你可以使用 StyleSheet 来定义组件的样式,并将其应用于对应的组件。
StatusBar(状态栏):StatusBar 组件用于控制应用程序的状态栏的样式和行为。你可以使用 StatusBar 来设置状态栏的背景颜色、文字颜色等属性。
Image(图片):Image 组件用于在应用程序中显示图片。你可以使用 Image 组件加载网络图片或本地图片,并根据需要对其进行调整和处理。
ImageBackground(背景图片):ImageBackground 组件允许你在其内部放置一个图片,并将其作为容器的背景。这在创建具有背景图片的复杂布局时非常有用。
1 alert
User
createTwoButtonAlert = () => {
Alert.alert('警告标题', '警告内容', [
{text: '取消', onPress: () => console.log('Cancel'), style: 'cancel'},
{text: '确定', onPress: () => console.log('Ok'), style: 'default'},
]);
};
createThreeButtonAlert = () => {
Alert.alert('更新提示', '发现新版本是否现在更新?', [
{text: '取消', onPress: () => console.log('Cancel'), style: 'cancel'},
{text: '确定', onPress: () => console.log('Ok'), style: 'default'},
{text: '稍后再试', onPress: () => console.log('稍后提醒我')},
]);
};
import {View, Alert, Button, StyleSheet} from 'react-native';
import React, {Component} from 'react';
export default class index extends Component {
// 创建一个包含两个按钮的警告框
createTwoButtonAlert = () => {
// 调用 Alert.alert() 方法显示警告框
Alert.alert(
// 警告框标题
'警告标题',
// 警告框内容
'警告内容',
// 按钮配置数组
[
// 第一个按钮配置对象
{
// 按钮显示的文本
text: '取消',
// 按下按钮时触发的回调函数
onPress: () => {
// 在控制台输出 'Cancel',表示用户按下了取消按钮
console.log('Cancel');
},
// 按钮样式(取消按钮)
style: 'cancel'
},
// 第二个按钮配置对象
{
// 按钮显示的文本
text: '确定',
// 按下按钮时触发的回调函数
onPress: () => {
// 在控制台输出 'Ok',表示用户按下了确定按钮
console.log('Ok');
},
// 按钮样式(默认按钮)
style: 'default'
},
]
);
};
// 创建一个包含三个按钮的警告框
createThreeButtonAlert = () => {
// 调用 Alert.alert() 方法显示警告框
Alert.alert(
// 警告框标题
'更新提示',
// 警告框内容
'发现新版本是否现在更新?',
// 按钮配置数组
[
// 第一个按钮配置对象
{
// 按钮显示的文本
text: '取消',
// 按下按钮时触发的回调函数
onPress: () => {
// 在控制台输出 'Cancel',表示用户按下了取消按钮
console.log('Cancel');
},
// 按钮样式(取消按钮)
style: 'cancel'
},
// 第二个按钮配置对象
{
// 按钮显示的文本
text: '确定',
// 按下按钮时触发的回调函数
onPress: () => {
// 在控制台输出 'Ok',表示用户按下了确定按钮
console.log('Ok');
},
// 按钮样式(默认按钮)
style: 'default'
},
// 第三个按钮配置对象
{
// 按钮显示的文本
text: '稍后再试',
// 按下按钮时触发的回调函数
onPress: () => {
// 在控制台输出 '稍后提醒我',表示用户按下了稍后再试按钮
console.log('稍后提醒我');
}
},
]
);
};
//注意:Button里面不能写style
render() {
return (
<View styles={[styles.container]}>
<Button
title="Alert"
onPress={() => {
alert('我是一个按钮');
}}
/>
<Button
title="Alert.alert"
onPress={() => {
Alert.alert('我是一个按钮');
}}
color={'red'}
/>
<Button
title="两个按钮"
onPress={this.createTwoButtonAlert}
color={'blue'}
/>
<Button
title="三个按钮"
onPress={this.createThreeButtonAlert}
color={'tomato'}
/>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'space-around',
alignItems: 'center',
},
});
2 Switch
(1)写一个开关,默认不隐藏状态栏(state 初始化为 不隐藏),并赋值给switch,这样 状态栏通过 this.state.hideStatusBar 联动。
点击swift就会触发 onValueChange={this.toggleStatusBar} 进行一次 state值取反,重新赋值给 StatusBar 并改变状态栏。
import React, { Component } from 'react'
import { Text, StyleSheet, View, StatusBar, Switch } from 'react-native'
// constructor():这是类的构造函数,用于初始化类的实例。
// 在 React 组件中,构造函数主要用于初始化组件的状态(state)和绑定事件处理方法。
// super():这是调用父类(即 React.Component)的构造函数,确保在初始化子类时先调用父类的构造函数,以便继承父类的属性和方法。
// this.state = { hideStatusBar: false }:这是在组件的状态对象中,定义了一个名为 hideStatusBar 的状态属性,并将其初始值设为 false。
// 在 React 组件中,状态对象用于存储组件内部的数据,并且当状态发生变化时,React 会自动重新渲染组件以反映这些变化。
export default class index extends Component {
constructor() {
// 调用父类的构造函数
super();
// 初始化组件的状态
this.state = {
// 属性:hideStatusBar,类型:boolean,初始值为 false
hideStatusBar: false
};
}
// 写成一个箭头函数的形式 在类组件中想要改状态的值的话 只能 在箭头函数中操作
//setState() 是 React 组件类中的一个方法,用于更新组件的状态。
//setState() 方法会将新的状态合并到当前状态中,然后触发组件的重新渲染。这样做是为了保持状态的不变性,以避免直接修改状态可能引起的问题。
toggleStatusBar = () => {
this.setState({
hideStatusBar: !this.state.hideStatusBar //直接取反
})
}
render() {
return (
<View>
<Text>index</Text>
<StatusBar
// hidden={false}
hidden={this.state.hideStatusBar}
//不是直接写死,而是 通过hide StatusBar来控制 状态栏
backgroundColor={"red"}//ios不奏效
barStyle={"dark-content"}
/>
<Switch
trackColor={{ false: '#999', true: '#666' }}
// thumbColor={'blue'} 按钮的前景
thumbColor={this.state.hideStatusBar? "green":"red"}
//下面添加一个具体的事件 先初始化一个值 再探测值是否发生变化
value={this.state.hideStatusBar}
//value 属性被设置为 this.state.hideStatusBar,意味着 Switch 组件的状态取决于 hideStatusBar 的值。当 hideStatusBar 的值发生变化时,Switch 组件也会相应地更新其状态。
//这样做的目的是为了将 Switch 组件的状态与组件类中的状态保持同步,以确保用户操作能够正确地反映到界面上。
onValueChange={this.toggleStatusBar}
// onValueChange是switch内置方法, 探测value值是否发生变化
//this.toggleStatusBar 函数被传递给了 onValueChange,意味着当值发生变化时,将调用 toggleStatusBar 函数,结果将hideStatusBar 拨动。
/>
</View>
)
}
}
3 ActivityIndicator
import {StyleSheet, View, ActivityIndicator, Platform} from 'react-native';
import React from 'react';
//加载图标
export default function index() {
if (Platform.OS === 'android') {
alert('当前平台是安卓');
} else if (Platform.OS === 'ios') {
alert('当前平台是IOS');
}
return (
<View style={[styles.container]}>
<ActivityIndicator color={'blue'} size={'large'} />
<ActivityIndicator color={'green'} size={'small'} />
{/*数字指定大小只在安卓应用有效*/}
<ActivityIndicator color={'#00d0ff'} size={70} />
<ActivityIndicator color={'red'} size={100} />
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'space-around',
alignItems: 'center',
},
});
4 image
import {Text, StyleSheet, View, Image, Dimensions, ScrollView} from 'react-native';
import React, {Component} from 'react';
export default class index extends Component {
render() {
return (
<ScrollView>
<View style={[styles.container]}>
<Image
style={[styles.itemImage]}
source={require('./images/wdmpp.jpg')}
/>
<Image
style={styles.tinyLogo}
source={{
uri: 'https://reactnative.dev/img/tiny_logo.png',
}}
/>
<Image
style={styles.logo}
source={{
uri: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADMAAAAzCAYAAAA6oTAqAAAAEXRFWHRTb2Z0d2FyZQBwbmdjcnVzaEB1SfMAAABQSURBVGje7dSxCQBACARB+2/ab8BEeQNhFi6WSYzYLYudDQYGBgYGBgYGBgYGBgYGBgZmcvDqYGBgmhivGQYGBgYGBgYGBgYGBgYGBgbmQw+P/eMrC5UTVAAAAABJRU5ErkJggg==',
}}
/>
</View>
</ScrollView>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
},
itemImage: {
height: Dimensions.get("window").height,
width: Dimensions.get('window').width,
marginVertical: 20,
},
tinyLogo: {
width: 100,
height: 100,
marginVertical: 20,
},
logo: {
width: 66,
height: 58,
},
});
5 textinput
在React Native中,TextInput组件提供了一系列属性来控制文本输入框的行为和样式。以下是一些常用的TextInput属性及其介绍:
value
: 设置或获取用户往文本输入框中输入的值。onChangeText
: 当文本输入框的值发生变化时,调用的回调函数。placeholder
: 设置文本输入框的占位符文本,当输入框为空时显示“请输入用户名”。placeholderTextColor
: 设置占位符文本的颜色。editable
: 设置文本输入框是否可编辑。multiline
: 设置文本输入框是否支持多行输入。numberOfLines
: 当multiline
为true
时,设置文本输入框的行数。secureTextEntry
: 设置文本输入框是否用于输入密码,当为true
时输入内容会被隐藏。autoCapitalize
: 设置文本输入框的自动大写风格,可选值包括none
、sentences
、words
、characters
。autoCorrect
: 设置文本输入框是否启用自动纠正功能。autoFocus
: 设置文本输入框是否自动获取焦点。keyboardType
: 设置文本输入框对应的键盘类型,如default
、numeric
、email-address
等。returnKeyType
: 设置键盘上返回键的类型,如done
、go
、search
等。onFocus
: 文本输入框获取焦点时调用的回调函数。onBlur
: 文本输入框失去焦点时调用的回调函数。onSubmitEditing
: 当用户提交编辑时调用的回调函数。style
: 设置文本输入框的样式。maxLength
: 设置文本输入框可输入的最大字符数。keyboardAppearance
: 设置键盘的外观,如default
、dark
、light
。clearButtonMode
: 设置清除按钮的显示模式,如never
、while-editing
、unless-editing
、always
。
闲聊回调函数
回调函数就像是一份待办事项清单上的任务。当某个任务完成时,你会去执行它,而不是在开始时就执行。在编程中,这个“任务”就是函数,而“完成”则意味着某个事件发生了或某个操作完成了。
在React Native中,当用户输入文本或点击按钮时,你想要执行的操作可能会有所不同,这就是回调函数的用武之地。你可以告诉React Native:“当用户输入文本时,请执行这个函数”,或者:“当用户点击按钮时,请执行另一个函数”。这些函数就是回调函数,它们会在特定的事件发生时被调用,以执行你预先定义的操作。
/* eslint-disable no-alert */
import { StyleSheet, View, TextInput, Dimensions, Button } from 'react-native';
import React, { Component } from 'react';
export default class index extends Component {
constructor() {
// まず、値を取得するために状態を使用できます.なので、コンストラクタ を書きます
//コンストラクタ中に 状態を初期化します
//状態は set state というメソッドを使用してのみ 変更できます .その値は
super()
this.state = {
username: ''
}
}
doLogin = () => {
// フォーム中のデータを取得(しゅとく)するには、3つ(みっつ)の方法(ほうほう)があります。
// onChangeValueハンドラーでテキスト入力の変更を監視(かんし)し、set.state.valueを使って状態中にのusernameを更新します。
// そして、状態のusername値をdoLoginのusername変数に代入(だいにゅう)し、ポップアップ(popーUP)で表示します。
alert(this.state.username)
}
render() {
return (
<View style={[styles.container]}>
<TextInput
// 入力ファームを作成
style={[styles.input]}
placeholder='请输入狗狗的名字'
value={this.state.username}
onChangeText={
// val パラメーター
(val) => {
this.setState({
username: val
})
}
}
// このコールバック関数は、テキストが変更されるたびに 後続(こうぞく)のイベントがトリガーされることを意味します
// 这个回调函数意味着每当文本发生变化时,后续事件就会被触发。
/>
<View>
{/* // viewタグを作成し、その中にbuttonボタンを配置して、ファームの送信機能を実装します。 */}
{/* // 在react中 写一个view标签 ,view标签中写一个button按钮 ,实现提交表单功能 */}
<Button title='登陆' onPress={this.doLogin} />
{/* 点击按钮的时候,触发onpress这个方法 进行了表单提交
ボタンをクリックした時に、 on Pressメソッドをトリガーして ファームの送信を行います */}
</View>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
},
input: {
width: Dimensions.get('window').width - 20,
margin: 10,
borderWidth: 1,
borderColor: 'red',
paddingHorizontal: 5,
},
btn: {
margin: 10,
// borderWidth: 1,
},
});
6 TouchableHighlight
/* eslint-disable no-alert */
import {
Text,
StyleSheet,
View,
TouchableHighlight,
TouchableOpacity,
TouchableWithoutFeedback,
} from 'react-native';
import React, {Component} from 'react';
export default class index extends Component {
constructor() {
super();
this.state = {
highlightColor: 'black',
};
}
TouchableHighlightPress = () => {
//alert('触碰高亮显示');
this.setState({highlightColor: 'white'});
};
TouchableHighlightPressOut = () => {
//alert('触碰高亮显示PressOut');
this.setState({highlightColor: 'black'});
};
render() {
return (
<View style={[styles.container]}>
<React.Fragment>
<TouchableHighlight
underlayColor="blue"
onFocus={this.TouchableHighlightPress}
onPress={this.TouchableHighlightPress}
onLongPress={this.TouchableHighlightPress}
onHideUnderlay={this.TouchableHighlightPressOut}>
<View style={[styles.Item]}>
<Text style={{color: this.state.highlightColor}}>
触碰高亮显示
</Text>
</View>
</TouchableHighlight>
<TouchableOpacity onPress={() => alert('触碰透明度变化')}>
<View style={[styles.Item]}>
<Text>触碰透明度变化</Text>
</View>
</TouchableOpacity>
<TouchableWithoutFeedback onPress={() => alert('触碰无响应')}>
<View style={[styles.Item]}>
<Text>触触碰无响应</Text>
</View>
</TouchableWithoutFeedback>
</React.Fragment>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
},
Item: {
marginBottom: 20,
padding: 10,
borderWidth: 1,
borderColor: 'red',
},
textColor: {
color: 'black',
},
});
7 ScrollView
/* eslint-disable react-native/no-inline-styles */
import { StyleSheet, Text, View, ScrollView, Platform } from 'react-native';
import React, { Component } from 'react';
export default class index extends Component {
render() {
// showsVerticalScrollIndicator 隐藏垂直方向的滚动条
//showsHorizontalScrollIndicator 隐藏水平方向的滚动条
// SafeAreaView 组件在有刘海屏的手机上能够避开刘海屏显示
return (
<View>
<ScrollView style={{ backgroundColor: '#dfb' }} horizontal={true}>
<Text style={[styles.nav]}>新闻</Text>
<Text style={[styles.nav]}>娱乐</Text>
<Text style={[styles.nav]}>体育</Text>
<Text style={[styles.nav]}>财经</Text>
<Text style={[styles.nav]}>军事</Text>
<Text style={[styles.nav]}>时尚</Text>
<Text style={[styles.nav]}>科技</Text>
</ScrollView>
<ScrollView
style={[styles.scrollView]}
// react-native/no-inline-styles
contentContainerStyle={{ margin: 30 }}
showsHorizontalScrollIndicator={true}
showsVerticalScrollIndicator={true}>
<Text style={[styles.text]}>
《三字经》
人之初,性本善。性相近,习相远。
苟不教,性乃迁。教之道,贵以专。
昔孟母,择邻处。子不学,断机杼。
窦燕山,有义方。教五子,名俱扬。
养不教,父之过。教不严,师之惰。
子不学,非所宜。幼不学,老何为。
玉不琢,不成器。人不学,不知义。
为人子,方少时。亲师友,习礼仪。
香九龄,能温席。孝于亲,所当执。
融四岁,能让梨。弟于长,宜先知。
首孝弟,次见闻。知某数,识某文。
一而十,十而百。百而千,千而万。
</Text>
{/*解决ScrollView在安卓下滚动不到底的问题*/}
{/*// eslint-disable-next-line react-native/no-inline-styles*/}
{/* 以上のように、このコードの目的は、異なる設備でscroll viewの高さを制定し、iOS設備でscroll viewを非表示にすることです */}
<View style={{ height: Platform.OS === 'ios' ? 0 : 200 }} />
</ScrollView>
</View>
);
}
}
const styles = StyleSheet.create({
text: {
fontSize: 30,
},
scrollView: {
backgroundColor: '#ddd',
marginHorizontal: 30,
},
nav: {
margin: 10,
height: 50,
fontSize: 30,
},
});
8 SectionList
sections:必需属性,用于指定列表的数据源,通常是一个包含多个对象的数组,每个对象代表一个分组,包含
data
(该分组的数据) 和可选的title
(该分组的标题)。renderItem:必需属性,用于指定渲染列表项的函数,函数接收一个包含
item
和index
属性的对象作为参数,用于渲染列表中的每一项。renderSectionHeader:可选属性,用于指定渲染分组头部的函数,函数接收一个包含
section
属性的对象作为参数,用于渲染每个分组的头部。ItemSeparatorComponent:可选属性,用于指定列表项之间的分隔组件,通常用于添加分割线或其他样式。
ListEmptyComponent:可选属性,用于指定当列表数据为空时渲染的组件,通常用于显示空列表时的占位内容。
refreshing:可选属性,用于指定列表是否处于刷新状态,通常与
onRefresh
属性一起使用。onRefresh:可选属性,用于指定下拉刷新时触发的函数,通常用于请求最新的数据并更新列表内容。
onEndReachedThreshold:可选属性,用于指定列表滚动到底部时触发加载更多数据的阈值,通常设置为一个小于 1 的值,表示列表滚动到底部还剩余多少比例时触发加载更多。
onEndReached:可选属性,用于指定列表滚动到底部时触发的函数,通常用于请求更多的数据并追加到列表末尾。
ListHeaderComponent:可选属性,用于指定列表头部的组件,通常用于显示额外的信息或操作。
ListFooterComponent:可选属性,用于指定列表尾部的组件,通常用于显示加载更多的提示信息或加载动画。
keyExtractor:可选属性,用于指定用于唯一标识列表项的属性,默认为
key
。
这段代码是一个使用React Native的SectionList组件实现的三国英雄列表展示,包含了下拉刷新和上拉加载更多的功能。
/* eslint-disable react/no-unstable-nested-components */
/* eslint-disable no-alert */
/* eslint-disable react-native/no-inline-styles */
import {Text, StyleSheet, View, SafeAreaView, SectionList} from 'react-native';
import React, {Component} from 'react';
// 数据源
const DATA = [
{
title: '魏国',
data: ['曹操', '司马懿', '张辽'],
},
{
title: '蜀国',
data: ['刘备', '关羽', '张飞'],
},
{
title: '吴国',
data: ['孙权', '周瑜', '黄盖'],
},
];
// 列表项组件
const Item = ({title}) => (
<View style={styles.item}>
<Text style={styles.title}>{title}</Text>
</View>
);
class Index extends Component {
constructor() {
super();
this.state = {
isRefresh: false, // 用于标记是否正在刷新
};
}
// 模拟加载数据的函数
loadData = () => {
// 开启加载动画
this.setState({
isRefresh: true,
});
// 模拟请求数据
setTimeout(() => {
this.setState({
isRefresh: false,
});
}, 2000);
alert('下拉刷新');
};
render() {
return (
<SafeAreaView>
<SectionList
sections={DATA} // 数据源
keyExtractor={(item, index) => item + index} // 为每个列表项生成唯一的key
renderItem={({item}) => <Item title={item} />} // 渲染列表项
renderSectionHeader={({section: {title}}) => (
<Text style={styles.header}>{title}</Text> // 渲染分组头部
)}
ItemSeparatorComponent={() => {
// 声明项目之间的分隔符
return (
<View style={{borderBottomWidth: 1, borderBottomColor: 'red'}} />
);
}}
ListEmptyComponent={() => {
// 当列表数据为空时展示的组件
return <Text style={{fontSize: 30}}>空空如也</Text>;
}}
refreshing={this.state.isRefresh} // 控制下拉刷新状态
onRefresh={() => {
// 下拉刷新触发的函数
this.loadData();
}}
onEndReachedThreshold={0.1} // 设置列表底部触发加载更多的阈值
onEndReached={() => {
// 上拉加载更多触发的函数
alert('到底了');
}}
ListHeaderComponent={() => {
// 列表头部组件
return <Text style={{fontSize: 40}}>三国英雄榜</Text>;
}}
ListFooterComponent={() => {
// 列表尾部组件
return <Text style={{fontSize: 30}}>没有更多了</Text>;
}}
/>
</SafeAreaView>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
marginTop: 50,
marginHorizontal: 16,
},
item: {
backgroundColor: '#f9c2ff',
padding: 20,
marginVertical: 8,
},
header: {
fontSize: 32,
backgroundColor: '#fff',
},
title: {
fontSize: 24,
},
});
export default Index;
9 FlatList
FlatList 组件是 React Native 中用于呈现列表数据的高性能组件,它适用于大型数据集。以下是 FlatList 组件的一些常用属性:
data
:要渲染的列表数据数组。renderItem
:用于渲染列表中每个项目的函数。keyExtractor
:用于从数据中提取唯一标识符的函数。ListHeaderComponent
:列表的头部组件,会在列表头部渲染。ListFooterComponent
:列表的尾部组件,会在列表尾部渲染。ItemSeparatorComponent
:用于渲染在列表项之间的分隔符的组件。horizontal
:指定列表是否水平滚动。numColumns
:指定在多列布局中每行的列数。initialNumToRender
:指定初始渲染的项目数量。onEndReached
:滚动到列表底部时调用的函数。onEndReachedThreshold
:触发onEndReached
事件的阈值,即距离列表底部多远时触发。refreshing
:指定列表是否处于刷新状态。onRefresh
:下拉刷新时调用的函数。refreshControl
:自定义刷新指示器的组件。
/* eslint-disable react-native/no-inline-styles */
/* eslint-disable react/no-unstable-nested-components */
/* eslint-disable no-alert */
import {
Text,
StyleSheet,
View,
SafeAreaView,
FlatList,
TouchableOpacity,
} from 'react-native';
import React, { Component } from 'react';
export default class Index extends Component {
constructor() {
super();
this.state = {
isLoading: false,
selectedId: null,
list: [
{
id: '1',
title: '麻辣贝贝火锅'
},
{
id: '2',
title: '孜然烤贝贝串'
},
{
id: '3',
title: '红烧贝贝面'
},
{
id: '4',
title: '酱爆贝贝丝'
},
{
id: '5',
title: '水煮贝贝'
},
{
id: '6',
title: '蒜蓉炒贝贝'
},
{
id: '7',
title: '黑椒贝贝粒'
},
{
id: '8',
title: '酸辣贝贝汤'
},
{
id: '9',
title: '梅菜扣贝贝'
},
{
id: '10',
title: '椒盐贝贝块'
},
{
id: '11',
title: '川味贝贝炒年糕'
},
{
id: '12',
title: '香菇贝贝炖饭'
},
{
id: '13',
title: '柠檬贝贝片'
},
{
id: '14',
title: '肉夹馍(夹贝贝)'
},
{
id: '15',
title: '葱爆贝贝'
},
{
id: '16',
title: '鱼香茄子煲贝贝'
},
{
id: '17',
title: '干锅贝贝'
},
{
id: '18',
title: '糖醋贝贝'
},
{
id: '19',
title: '红烧贝贝丸子'
},
{
id: '20',
title: '酸菜贝贝面'
}
]
,
};
}
renderItem = ({ index, item }) => {
console.log(item);
const backgroundColor =
item.id === this.state.selectedId ? '#dfb' : '#f9c2ff';
return (
<TouchableOpacity
style={[styles.item, { backgroundColor }]}
onPress={() => {
this.setState({ selectedId: item.id });
}}>
<Text style={[styles.title]}>{item.title}</Text>
</TouchableOpacity>
);
};
loadData = () => {
this.setState({
isLoading: true,
});
setTimeout(() => {
//模拟请求数据
alert('刷新请求数据');
this.setState({ isLoading: false });
}, 2000);
};
render() {
return (
<View>
<Text></Text>
<Text></Text>
<Text style = { { fontSize:40}} >可爱玉林狗</Text>
<SafeAreaView>
<FlatList
data={this.state.list}
renderItem={this.renderItem}
keyExtractor={item => item.id}
horizontal={false} //是否水平布局模式
initialScrollIndex={0} //初始化时滚动的索引位置
initialNumToRender={20} // 指定初始渲染数据的数量,一般数量要填满一屏幕
numColumns={2} // 设置展示多少列 数据项必须等高,无法支持瀑布流
inverted={false} //反转列表
extraData={this.state.selectedId}
ItemSeparatorComponent={() => {
//声明项目之间的分割符
return <View style={[styles.itemSeparator]} />;
}}
ListEmptyComponent={() => {
//列表数据为空时展示组件
return <Text style={{ fontSize: 30 }}>空空如也</Text>;
}}
//下拉刷新
refreshing={this.state.isLoading}
onRefresh={this.loadData}
// 上拉加载
// onEndReachedThreshold设置列表触底还剩多少刷新0.1表示列表还剩10%的时候刷新
onEndReachedThreshold={0.1}
onEndReached={() => {
//此处为上拉加载的具体逻辑代码
// alert('到底了');
}}
ListHeaderComponent={() => {
//声明列表的头部组件
return <Text style={[styles.header]}>列表头部</Text>;
}}
ListFooterComponent={() => {
//声明列表的头部组件
return <Text style={[styles.footer]}>没有更多了</Text>;
}}
/>
</SafeAreaView>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
marginTop: 50,
marginHorizontal: 16,
},
item: {
backgroundColor: '#f9c2ff',
height: 100,
width: '50%',
//fontSize: 55,
textAlign: 'cenleftter',
verticalAlign: 'middle',
justifyContent: 'center',
alignItems: 'left',
marginVertical: 8,
marginHorizontal: 8,
},
header: {
fontSize: 10,
backgroundColor: '#fff',
},
title: {
fontSize: 24,
},
itemSeparator: {
borderBottomWidth: 1,
borderBottomColor: 'red',
},
footer: { fontSize: 30, textAlign: 'center' },
});
10 Animated
在 React Native 中,Animated
是一个内置的动画库,它提供了一组组件和函数,用于创建各种动画效果。
特点:
高性能:
Animated
使用原生动画驱动来执行动画,因此具有良好的性能。易于使用:提供了简单易用的 API,使得创建和控制动画变得简单。
支持多种动画效果:可以实现平移、缩放、旋转、透明度变化等各种动画效果。
适用性广泛:适用于各种组件和场景,包括 View、Text、Image 等。
通过 Animated
,开发者可以轻松地为 React Native 应用添加动画效果,提升用户体验,增强应用的吸引力和交互性。
React Native 中的动画组件
在 React Native 中,有几个直接可用的动画组件,它们包括:
Animated.View:用于创建一个可以进行动画操作的视图组件。可以通过
Animated.View
实现平移、缩放、旋转、透明度等动画效果。Animated.Text:类似于普通的文本组件,但可以通过 Animated API 来实现文本的动画效果,如透明度变化、颜色变化等。
Animated.ScrollView:基于 ScrollView 组件,但可以使用 Animated API 来创建滚动动画效果,包括滚动到指定位置、滚动速度控制等。
Animated.Image:类似于普通的图片组件,但可以通过 Animated API 来实现图片的动画效果,如透明度变化、位置移动等。
Animated.FlatList:与普通的 FlatList 类似,但可以使用 Animated API 来创建列表项的动画效果,如渐变、平移等。
Animated.SectionList:类似于 FlatList,但专门用于显示分组数据。可以通过 Animated API 实现分组列表项的动画效果。
Animated.TouchableOpacity:与 TouchableOpacity 类似,但可以使用 Animated API 实现按钮的动画效果,如缩放、颜色变化等。
Animated.TextInput:与 TextInput 类似,但可以使用 Animated API 实现输入框的动画效果,如聚焦时的放大效果、边框颜色变化等。
/* eslint-disable no-alert */
import {
Animated,
Text,
StyleSheet,
View,
SafeAreaView,
Button,
Image,
} from 'react-native';
import React, { Component } from 'react';
export default class Index extends Component {
// fadeAnim 将透明度设置为0
state = {
fadeAnim: new Animated.Value(0),
moveAnim: new Animated.Value(0),
};
fadeIn = () => {
Animated.timing(this.state.fadeAnim, {
toValue: 1, //目标值
useNativeDriver: true, //启用原生方式,渲染动画(执行效率会更高)
duration: 1, // 动画执行时间
}).start(() => {
// 动画执行结束后的回调函数
alert('请吃贝贝');
});
};
fadeOut = () => {
// Will change fadeAnim value to 0 in 3 seconds
Animated.timing(this.state.fadeAnim, {
toValue: 0,
duration: 2,
useNativeDriver: true,
}).start(() => {
// 动画执行结束后的回调函数
alert('我藏起来了');
});
};
componentDidMount() {
//组件加载后触发动画
this.scanMove();
}
scanMove = () => {
// 将moveAnim的初始值设置为0
this.state.moveAnim.setValue(0);
Animated.timing(this.state.moveAnim, {
toValue: 200,
duration: 1000,
useNativeDriver: true,
}).start(() => {
this.scanMove();
});
};
render() {
return (
<SafeAreaView style={styles.container}>
<Animated.View
style={[
styles.fadingContainer,
{
// Bind opacity to animated value
opacity: this.state.fadeAnim,
},
]}>
<Text style={styles.fadingText}> 做好了</Text>
<Image
source={require('../src_13_Animated/eatbb.jpg')}
style={[styles.backgroundImage, { width: 100, height: 100 }]} // 修改宽高为100x100
/>
</Animated.View>
<View style={styles.buttonRow}>
<Button title="做成菜" onPress={this.fadeIn} />
<Button title="送去玉林" onPress={this.fadeOut} />
</View>
<View style={[styles.scanContainer]}>
<Animated.View
style={[
styles.border,
{
transform: [
{
translateY: this.state.moveAnim,
},
],
},
]}
/>
<Image
source={require('../src_13_Animated/bb.jpg')} // 背景图片路径
style={styles.backgroundImage}
/>
</View>
</SafeAreaView>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
},
fadingContainer: {
padding: 20,
backgroundColor: 'powderblue',
},
fadingText: {
fontSize: 15,
backgroundColor:'yellow'
},
buttonRow: {
flexBasis: 100,
justifyContent: 'space-evenly',
marginVertical: 16,
},
// scanContainer: {
// height: 200,
// width: 200,
// borderWidth: 1,
// borderColor: 'green',
// },
border: {
borderWidth: 1,
borderColor: 'red',
},
// ----------
scanContainer: {
position: 'relative', // 确保容器视图相对定位
height: 200,
width: 200,
borderWidth: 1,
borderColor: 'green',
},
// backgroundImage: {
// position: 'absolute', // 确保背景图片绝对定位
// top: 0,
// left: 0,
// width: '70%', // 图片宽度与容器宽度相同
// height: '100%', // 图片高度与容器高度相同
// resizeMode: 'cover', // 图片裁剪方式
// zIndex: -1, // 将背景图片放置在视图的底层
// },
backgroundImage: {
position: 'absolute',
top: 0,
left: 0,
width: '100%',
height: '100%',
resizeMode: 'contain', // 修改为contain
zIndex: -1,
},
});
下一节,我们会接着介绍其他常用组件