模拟器设置成中文
在开发过程中发现,两个模拟器都不能输入中文,所以需要配置一下。
先说一下安卓,在弹出的输入框中查看设置,设置一下对应的languages
即可:
在苹果模拟器中,跟苹果手机一样,打开设置,然后打开通用,同样设置语言:
路由搭建
我在这里走了弯路,去了另一个库…,路由文档入口在这:链接
sudo npm install @react-navigation/native
# 兼容expo
sudo npx expo install react-native-screens react-native-safe-area-context
# 路由跳转的本质是堆栈
sudo npm install @react-navigation/native-stack
# 我们项目中会使用到底部导航栏跳转
sudo npm install @react-navigation/bottom-tabs
我要做的东西如下:
大概也能猜出哪些路由了,这里说一下路由中tab页面和普通页面的搭建,关于抽屉页面,后续使用了再补上:
// router/index.js
import react from 'react';
import { createNativeStackNavigator } from '@react-navigation/native-stack';
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
import { Feather } from '@expo/vector-icons';
import { MaterialCommunityIcons } from '@expo/vector-icons';import HabitHome from '../views/habit/home/index';
import HabitDetail from '../views/habit/detail/index';
import HabitSet from '../views/habit/set';
import DateHome from '../views/date/home/index';
import DateSet from '../views/date/set/index';// 这里声明了底部tab页面有哪些,还配置了顶部导航栏的一些自定义按钮
const Tab = createBottomTabNavigator();function TabStack(){return (<Tab.Navigator screenOptions={{ headerShown: true,tabBarInactiveTintColor: '#333',tabBarActiveTintColor: '#6528F7',tabBarShowLabel: true,}}><Tab.Screen name="HabitHome" component={HabitHome}options={{title: '',tabBarLabel: '打卡',tabBarIcon: ({ color, size }) => (<Feather name="target" color={color} size={size} />),}} /><Tab.Screen name="DateHome" component={DateHome}options={{title: '',tabBarLabel: '纪念日',tabBarIcon: ({ color, size }) => (<MaterialCommunityIcons name="calendar-heart" color={color} size={size} />),}} /></Tab.Navigator>)
}// 将底部导航栏和非底部导航栏的页面都写在这里:
const Stack = createNativeStackNavigator();function PageStack(){return (<Stack.Navigator><Stack.Screenname="TabStack"component={TabStack}options={{ headerShown: false }}/><Stack.Screen name="HabitDetail" component={HabitDetail} options={{ title: '习惯详情' }} /><Stack.Screen name="HabitSet" component={HabitSet}options={{title: '添加一个习惯'}} /><Stack.Screen name="DateSet" component={DateSet} options={{ title: '设置纪念日' }} /></Stack.Navigator>)
}export default PageStack;
接下来就是在App.js
中使用了:
import * as React from 'react';
import { NavigationContainer } from '@react-navigation/native';
import { Provider } from 'react-redux'
import store from './store/index'
import PageStack from './router/index'function App() {return (<Provider store={store}><NavigationContainer><PageStack /></NavigationContainer></Provider>);
}export default App;
用的状态管理器,还是redux
,像以前在普通react项目中那样使用就行(官网地址)
开发技巧
ScrollView
适合用来显示数量不多的滚动元素。放置在ScrollView
中的所有组件都会被渲染(还没滑动到下一屏幕,也是会被渲染出来),FlatList
更适于长列表数据,且元素个数可以增删,和ScrollView
不同的是,FlatList
并不立即渲染所有元素,而是优先渲染屏幕上可见的元素。综上,如果列表太长的情况下,可以优先使用FlatList
。View
组件类似Div
组件,但是没有点击事件;- 所有文字必须包含在
Text
组件中; Button
组件在两端的机器上显示的不一样,所以为了确保样式一致性,我会使用View
按钮来制作按钮;- 由于
View
上没有点击事件,所以我借助了TouchableOpacity
,而安卓机上还有一个特有的组件:TouchableNativeFeedback
,做了如下封装:
import { TouchableOpacity, TouchableNativeFeedback, Platform } from 'react-native';function CommonButton (props){const { onPress, children } = props;if(Platform.OS === 'android') {return (<TouchableNativeFeedback background={TouchableNativeFeedback.Ripple('rgba(215, 187, 245, 0.5)', false)}onPress={onPress}>{ children }</TouchableNativeFeedback>)}else {return (<TouchableOpacity onPress={onPress}>{ children }</TouchableOpacity>)}
}export default CommonButton;
- 从上面的例子可知
Platform
可以用来判断端的类型,如果你觉得一个文件编写两套代码麻烦,可以改成下面的方式:
- common-button.ios.js
- common-button.android.js
在引入文件的时候还是直接写:
import CommonButton from 'xxx/xxx/common-button'
-
React Native
中的flex
跟平常的还是有些区别的; -
由于样式的局限性,所以在项目中我想借助
float
来写瀑布流样式是不支持的,后来实现的方法是采用了拆分成了两列: -
生成随机数有很多种
npm
包供使用,比如nanoid
,但是它不兼容React Native
,这里采用了uuid
:
npm i uuid react-native-get-random-values
// store/modules/habitimport { createSlice } from '@reduxjs/toolkit';
import 'react-native-get-random-values';
import { v4 as uuidv4 } from 'uuid';const defaultList = [{id: uuidv4(10),name: '打卡',count: 0,},
]// ...
expo
包内置了图标,文档地址:@expo/vector-icons;- 路由跳转,在页面的
props
中可以获取navigation
对象:
function HabitHome(props) {const { navigation } = props;// ...// 新增打卡const goSetPage = () => {navigation.navigate('HabitSet')}// ...
}
- 当用户在输入某些内容,会弹出键盘,键盘有时候会挡住页面,可以借助
KeyboardAvoidingView
组件,本组件可以自动根据键盘的高度,调整自身的 height 或底部的 padding,以避免被遮挡; - 另外键盘弹出之后,我们希望可以在点击其他地方的时候自动收回键盘,那么可以借助
TouchableWithoutFeedback
,最终代码如下:
function HabitSet(props) {// ...// 收起键盘const onPress = () => {Keyboard.dismiss();}return (<TouchableWithoutFeedback onPress={onPress}><KeyboardAvoidingView style={styles.container} behavior={Platform.OS == "ios" ? "padding" : "height"}>// ...</KeyboardAvoidingView></TouchableWithoutFeedback>);
}
参考
- expo
- react native
- react-navigation
- 图标
- 配色参考
- react-redux