react_native 项目实战 (4) 自定义分类 使用 CheckBox 以及 数据存储asyncStorage
来源:互联网 发布:仁化县网络问政平台 编辑:程序博客网 时间:2024/06/06 02:04
使用CheckBox
先看下效果图
引入CheckBox 第三方复选框react-native-check-box
npm install react-native-check-box –save //两个横杠
leftText 的Text 大写.又被坑了一次
Checkbox
http://www.searu.org/39207.html
遇到的问题
1, 点击后就隐藏了 解决: 更新react-native-check-box 到最新的 就好了 吐血这个问题
我开始想自己写的 但想着自己写肯定费时费力 不甘心 各种找资料 还是找到了
"react-native-check-box": "^2.0.2",
npm install react-native-check-box –save 用这个命令 别用github上面的那个readmi说的命令
真的坑啊
2, checkbox 没有勾选 解决: 原因isChecked Checked 我的c是小写 ..
其他的难点就是关于算法的问题了 主要是这几个Checkbox如何布局 大致说下把:
- 定义一个views数组 里面装了所有的Checkbox
- 每一行我包裹起来 包裹了两个checkbox 然后用views数组给push进去
- 需要留出最后一样 通过判断奇数偶数 再把最后一行添加进去
具体看代码把
AsyncStorage使用 进行数据存取
引用
import { AppRegistry, StyleSheet, Text, View, Image, TouchableOpacity, AsyncStorage} from 'react-native';
通过 setItem方法保存数据 key- value 形式
AsyncStorage.setItem('custom_key', JSON.stringify(this.state.data)) .then(() => this.refs.toast.show("保存成功"));
获取 getItem 方法获取数据
AsyncStorage.getItem('custom_key') .then(value => { //有用户数据,选中该选中CheckBox if (value !== null) { // console.log(JSON.parse(value)); this.setState({data: JSON.parse(value)}); } else { this.setState({ data: [{name: 'Android', checked: true}, {name: 'IOS', checked: true}, {name: 'React Native', checked: true}, {name: 'Java', checked: true}, {name: 'JS', checked: true}] }); } });
下面上完成的代码
/** * Created by liuml on 2017/9/17. */import React, {Component} from 'react';import { AppRegistry, StyleSheet, Text, View, Image, AsyncStorage, TouchableOpacity} from 'react-native';/** * 自定义分类页面 */import NavigationBar from '../compont/NavigationBar';import CheckBox from 'react-native-check-box';import Toast from "react-native-easy-toast"export default class CustomKeyPage extends Component { // 构造 constructor(props) { super(props); // 初始状态 this.state = { data: [{name: 'android', checked: true}, {name: 'IOS', checked: false}] }; } handleBack = () => { this.props.navigation.goBack(); } getLeftBtn = () => { return <View style={{flexDirection: 'row', alignItems: 'center'}}> <TouchableOpacity activeOpacity={0.7} onPress={this.handleBack}> <Image source={require('../../res/images/ic_arrow_back_white_36pt.png')} style={{width: 24, height: 24}}/> </TouchableOpacity> </View>; } getRightBtn = () => { return <View style={{flexDirection: 'row', alignItems: 'center'}}> <TouchableOpacity onPress={this.handleSave} activeOpacity={0.7}> <View style={{marginRight: 10}}> <Text style={{fontSize: 16, color: '#FFF'}}>保存</Text> </View> </TouchableOpacity> </View>; } //保存 handleSave = () => { //http://lib.csdn.net/article/reactnative/43540 JSON.stringify 字符串转JSON //AsyncStorage是一个简单的、异步的、持久化的Key-Value存储系统 AsyncStorage.setItem('custom_key', JSON.stringify(this.state.data)) .then(() => this.refs.toast.show("保存成功")); // console.log(JSON.stringify(this.state.data)); } //CheckBox 点击 有个疑问为什么在这里设置值就可以不用setState就改变item的checked,因为是这样调用的()=>this.handlerCBClick(item) handleClick = (item) => { // console.log("之前 " + item.checked); item.checked = !item.checked; // console.log("之后 " + item.checked); } //渲染CheckBox 这里item就是一个对象 renderCheckBox = (item) => { // console.log(item); // console.log(item.name + ',' + item.checked); var leftText = item.name; return <CheckBox style={{flex: 1, padding: 10}} onClick={() => this.handleClick(item)} leftText={item.name} isChecked={item.checked} unCheckedImage={<Image source={require('../../res/images/ic_check_box_outline_blank.png')} style={styles.checkbox}/>} checkedImage={<Image source={require('../../res/images/ic_check_box.png')} style={styles.checkbox}/>} /> } renderViews = () => { let len = this.state.data.length; var views = []; //要绘制的所有多选框,装入views数组 for (let i = 0, j = len - 2; i < j; i += 2) { views.push(( <View key={`view_${i}`} style={{flexDirection: 'row'}}> {this.renderCheckBox(this.state.data[i])} {this.renderCheckBox(this.state.data[i + 1])} </View> )); } //偶数个,剩下最后两个多选框 //奇数个,剩下最后一个多选框 views.push( <View key={`view_${len - 1}`} style={{flexDirection: 'row'}}> {len % 2 === 0 ? this.renderCheckBox(this.state.data[len - 2]) : <View style={{flex: 1, padding: 10}}></View>} {this.renderCheckBox(this.state.data[len - 1])} </View> ); return views; } componentDidMount = () => { this.loadData(); } loadData = () => { //加载本地数据 AsyncStorage.getItem('custom_key') .then(value => { //有用户数据,选中该选中CheckBox if (value !== null) { // console.log(JSON.parse(value)); this.setState({data: JSON.parse(value)}); } else { this.setState({ data: [{name: 'Android', checked: true}, {name: 'IOS', checked: true}, {name: 'React Native', checked: true}, {name: 'Java', checked: true}, {name: 'JS', checked: true}] }); } }); // console.log(this.state.data); } render() { return <View style={styles.container}> <NavigationBar title="自定义分类" rightButton={this.getRightBtn()} leftButton={this.getLeftBtn()}/> <View style={{flexDirection: 'column'}}> {this.renderViews()} </View> <Toast ref="toast"/> </View> }}const styles = StyleSheet.create({ container: { flex: 1 }, checkbox: { tintColor: '#63B8FF' }});
看看最终效果图
其实这个第三方CheckBox 有个bug
当属性变化时 并没有刷新状态 那么 需要我进入源码 让他属性变化时 刷新他的状态
主要代码 进入源码后 加入下面的代码
//当组件接收到新的属性值时被调用 componentWillReceiveProps(nextProps) { //让状态跟着属性变化 this.setState({isChecked:nextProps.isChecked}); }
下面做一些完善 比对修改前后数据 弹出是否保存对话框
首页最热页面 读取保存的数据
首页的最热页面根据保存的分类读取数据
/** * Created by liuml on 2017/9/11. */import React, {Component} from 'react';import { AppRegistry, StyleSheet, Text, View, Image, ListView, RefreshControl, TouchableOpacity, AsyncStorage}from 'react-native';import NavigationBar from "../compont/NavigationBar.js"import ScrollableTabView from "react-native-scrollable-tab-view"import ProjectRow from "../compont/ProjectRow"/** * 最热页面 */export default class PapularPage extends Component { // 构造 constructor(props) { super(props); // 初始状态 this.state = { languages: [ {name: 'Android'}, {name: 'IOS'}, {name: 'React'}, {name: 'Java'}, {name: 'JS'} ] }; } getRightBtn = () => { return <View style={{flexDirection: 'row', alignItems: 'center'}}> <TouchableOpacity activeOpacity={0.7}> <Image source={require('../../res/images/ic_search_white_48pt.png')} style={{width: 24, height: 24}}></Image> </TouchableOpacity> <TouchableOpacity activeOpacity={0.7}> <Image source={require('../../res/images/ic_more_vert_white_48pt.png')} style={{width: 24, height: 24}}></Image> </TouchableOpacity> </View> } loadLanguages = () => { // AsyncStorage.clear(); AsyncStorage.getItem('custom_key') .then((value) => { console.log("读取的: " + value); console.log("读取的: " + JSON.parse(value)); if (value != null) { this.setState({languages: JSON.parse(value)}); } }); } componentDidMount() { this.loadLanguages(); } render() { return <View style={styles.container}> <NavigationBar rightButton={this.getRightBtn()} title="热门"/> <ScrollableTabView tabBarBackgroundColor="#63B8FF" tabBarActiveTextColor="#FFF" tabBarInactiveTextColor="#F5FFFA" tabBarUnderlineStyle={{backgroundColor: "#E7E7E7", height: 2}}> { this.state.languages.map((item, i) => { console.log(item); return (item.checked == undefined || item.checked ? <PopularTab key={`tab${i}`} tabLabel={item.name}/> : null) }) } </ScrollableTabView> </View> }}class PopularTab extends Component { //这里是Tab 的名字 static defaultProps = { tabLabel: 'android', } // 构造 constructor(props) { super(props); // 初始状态 this.state = { dataSource: new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2}),//是一个优化,节省无用的UI渲染 判断前后数据是否改变 如果改变就更新 isLoading: true }; } /*componentDidMount() { /!*this.setState({ dataSource: this.state.dataSource.cloneWithRows(['first', 'second', 'three']) } )*!/ this.loadData(); };*/ //和上面一样的效果 页面加载完成后加载数据 componentDidMount = () => { this.loadData(); } //渲染ListView的每一行 renderRow = (obj) => { return <ProjectRow item={obj}></ProjectRow> // return <Text>{obj.full_name}</Text> } //加载数据 loadData = () => { this.setState({isLoading: true}); fetch(`https://api.github.com/search/repositories?q=${this.props.tabLabel}&sort=stars`) .then(response => response.json()) //服务器响应response对象,继续变成json对象 .then(json => { //更新dataSource this.setState({ dataSource: this.state.dataSource.cloneWithRows(json.items), isLoading: false, }); }) .catch((error) => { console.error(error); }).done(); } handleRefresh = () => { this.loadData(); } render() { return <View style={styles.container}> <ListView dataSource={this.state.dataSource} renderRow={this.renderRow} refreshControl={ <RefreshControl refreshing={this.state.isLoading} tintColor="#63B8FF" title="正在加载..." titleColor="#63B8FF" colors={['#63B8FF']} /> } ></ListView> </View> }}const styles = StyleSheet.create({ container: { flex: 1 }});
主要的两段代码
读取本地保存的数据
componentDidMount() { this.loadLanguages(); } loadLanguages = () => { // AsyncStorage.clear(); AsyncStorage.getItem('custom_key') .then((value) => { console.log("读取的: " + value); console.log("读取的: " + JSON.parse(value)); if (value != null) { this.setState({languages: JSON.parse(value)}); } }); }
根据本地数据显示
<ScrollableTabView tabBarBackgroundColor="#63B8FF" tabBarActiveTextColor="#FFF" tabBarInactiveTextColor="#F5FFFA" tabBarUnderlineStyle={{backgroundColor: "#E7E7E7", height: 2}}> { this.state.languages.map((item, i) => { console.log(item); return (item.checked == undefined || item.checked ? <PopularTab key={`tab${i}`} tabLabel={item.name}/> : null) }) } </ScrollableTabView>
效果图
得注意下我这里做的是重新加载才更新了顶部标题,后面会做下不重新加载,就更新首页的最热标签栏.
下面做下分类排序页面
分类排序
效果图
分类排序 用到了第三方组件
安装命令
npm install react-native-sortable-listview –save
分类页面代码
/** * Created by liuml on 2017/10/22. */import React, {Component} from 'react';import { AppRegistry, StyleSheet, Text, View, Image, TouchableOpacity, TouchableHighlight, AsyncStorage,} from 'react-native';import NavigationBar from "../compoent/NavigationBar";import SortableListView from "react-native-sortable-listview";export default class SortKeyPage extends Component { // 构造 constructor(props) { super(props); // 初始状态 this.state = { data: [], }; } doBack = () => { this.props.navigation.goBack(); } getLeftBtn = () => { return <View style={{flexDirection: 'row', alignItems: 'center'}}> <TouchableOpacity activeOpacity={0.7} onPress={this.doBack}> <Image source={require('../../res/images/ic_arrow_back_white_36pt.png')} style={{width: 24, height: 24}}/> </TouchableOpacity> </View>; } componentDidMount() { AsyncStorage.getItem("custom_key") .then(value => { if (value != null) { //只获取checked为true语言,进行排序 forEach 不会返回一个数组 而map会返回一个数组 let d = []; JSON.parse(value).forEach((item) => { if (item.checked) { d.push(item); } }) this.setState({data: d}); var myorder = Object.keys(this.state.data); //Array of keys } }) } render() { return <View style={styles.container}> <NavigationBar title="语言分类排序" leftButton={this.getLeftBtn()}/> <SortableListView data={this.state.data} order={Object.keys(this.state.data)} rowActivationTime="10" renderRow={row => <RowComponent data={row}/>} onRowMoved={e => { this.state.data.splice(e.to, 0, this.state.data.splice(e.from, 1)[0]); this.forceUpdate(); }} /> </View> }}//https://github.com/deanmcpherson/react-native-sortable-listview/blob/master/Sortable/example.js 这里是SortableListView github地址 示例代码class RowComponent extends Component { static defaultProps = { data: {name: ""} }; render() { return <TouchableHighlight underlayColor="#EEE" style={styles.item} {...this.props.sortHandlers}> <View style={{flexDirection: 'row', paddingLeft: 10}}> <Image source={require('../../res/images/ic_sort.png')} style={styles.image}/> <Text>{this.props.data.name}</Text> </View> </TouchableHighlight> }}const styles = StyleSheet.create({ container: { flex: 1 }, item: { backgroundColor: '#F8F8F8', borderBottomWidth: 1, borderColor: '#EEE', height: 50, justifyContent: 'center' }, image: { width: 16, height: 16, marginRight: 10, tintColor: '#63B8FF' }});
项目地址
https://github.com/liudao01/ReactNativeProject
- react_native 项目实战 (4) 自定义分类 使用 CheckBox 以及 数据存储asyncStorage
- react native AsyncStorage 使用实例 异步存储数据以及读取
- react_native 项目实战 (3) 使用导航页面跳转 (ReactNaviation 完全自定义导航)
- React_Native 项目实战 (1) (首页,以及页面的切换)
- react_native 项目实战 (6) 趋势页面 列表抽取 popover使用
- React_Native项目实战之fetch请求
- react_native 项目实战 (5) DeviceEventEmitter 使用 ,webview 使用 react navigation进行参数传递
- react-native-AsyncStorage<持久化数据存储>
- ReactNative——数据存储AsyncStorage
- reactnative之AsyncStorage,简单使用以及坑
- ReactNative学习实例(九)数据永久化存储AsyncStorage
- RN 的持久化存储(AsyncStorage)的使用
- ReactNative(API)AsyncStorage存储
- QX项目实战-2.模块分类以及配置读取
- iOS项目开发实战——使用用户首选项数据API存储信息
- React-Native AsyncStorage使用
- 使用selector自定义checkbox
- nosql数据存储分类
- Mine
- 获取网络数据的工具类__NetDataUtil,带使用方法 与下面的网络判断一起用,
- hibernate 出现 is not mapped 问题
- NOIP2017普及组初赛总结
- 【BZOJ】4390 [Usaco2015 dec]Max Flow LCA+树上差分
- react_native 项目实战 (4) 自定义分类 使用 CheckBox 以及 数据存储asyncStorage
- Android7.0新签名对多渠道打包的影响
- 中位数图 BZOJ
- CopyOnWriteArrayList与CopyOnWriteArraySet源码简析
- Java序列化
- Python Handle data skill
- nested exception is java.lang.NoClassDefFoundError: org/apache/commons/pool/impl/GenericObjectPool
- 二位数组长度的求法
- 如何使用python.plot()画简单的聚类结果图?