资料:连接: https://pan.baidu.com/s/1b3abwy 密码: k8p5php
源码托管到 github 上,须要源码的 点我下载,喜欢的话记得 Star,谢谢!react
译注:android
建议打开 视频 配合 文字 学习,以避免有某些细节文中没有提到,但以文中内容为准(根据反馈进行相应更新)ios
之因此选择这款APP,和我我的的爱好有关,固然关键仍是由于这个APP总体并不复杂,包含了市面上常见APP的样式,而且很顺利地就获取到全部请求参数和图片资源,很适合咱们体验 React-native 大体的开发流程。git
在开发APP前,产品经理大体会进行需求的分析,而后开会讨论开发过程当中须要使用到的技术、会遇到的难点、分配相应任务、倾听开发人员意见并进行相应的修改,最终肯定总体原型图、开发流程、技术、周期等等,固然其中还有UI的介入,咱们没有产品经理,UI也有现成的,因此大体给你们划分如下几块:es6
需求分析:这款APP主要是经过抓取各大电商平台的 商品优惠信息 进行筛选、分类并最终展示给用户,使用户能够方便、快捷、实时的获取高质量的优惠信息。github
开发模型:咱们这边相似基于 原型模型 开发。json
使用的技术:React-Nativereact-native
功能模块:主要分为 首页、海淘模块、小时风云榜 三大模块等其它附属模块(酌情增长)。api
命名规则:参考 编码规范文档(不一样公司之间都有差别,具体看公司提供的文档,这边先遵照下面提到的规则便可)
测试:MDZZ,谁测试→→!
全部须要用到的资源点击下载。
General
—— App Icons and Launch Images
—— 修改 Launch Images Source
为 Images.xcassets
文件夹内的 LaunchImage ,清除 Launch Screen File
内容。General
—— Deployment Info
—— Device Orientation
—— 只保留 Portrait 选项。IPV6标准
能够忽略这一步)OK,至此 iOS 端配置完毕。
设置 APP图标 进入 GD/android/app/sec/ 打开 AndroidManifest 文件,修改 android:icon 项,以下:
<applicatio> android:icon="@drawable/icon" </application>
设置 APP名称 进入 GD/android/app/src/main/res/values/ 中,打开 strings.xml 文件,作以下修改:
<resources> <string name="app_name">逛丢学习</string> </resources>
OK,至此 Android 配置完毕。
目录结构:
译注:
这边来说下在 React-Native 中怎么导入第三方框架
到此,第三方框架导入完成,使用在下面会提到。
上面提到使用 TabBar 做为主体框架,可是官方只提供了iOS端的 TabBarIOS ,时间缘由为了加快开发进度,而且顺带讲解 第三方框架使用 因此咱们使用 <react-native-tab-navigator>进行开发
既然要使用框架,确定要先引入框架文件。
// 引用第三方框架 import TabNavigator from 'react-native-tab-navigator';
export default class GD extends Component { // ES6 // 构造 constructor(props) { super(props); // 初始状态 this.state = { selectedTab:'home', }; } // 返回TabBar的Item renderTabBarItem(title, selectedTab, image, selectedImage, component) { return( <TabNavigator.Item selected={this.state.selectedTab === selectedTab} title={title} selectedTitleStyle={{color:'black'}} renderIcon={() => <Image source={{uri:image}} style={styles.tabbarIconStyle} />} renderSelectedIcon={() => <Image source={{uri:selectedImage}} style={styles.tabbarIconStyle} />} onPress={() => this.setState({ selectedTab: selectedTab })}> // 添加导航功能 <Navigator // 设置路由 initialRoute={{ name:selectedTab, component:component }} renderScene={(route, navigator) => { let Component = route.component; return <Component {...route.params} navigator={navigator} /> }} /> </TabNavigator.Item> ); } render() { return ( <TabNavigator> {/* 首页 */} {this.renderTabBarItem("首页", 'home', 'tabbar_home_30x30', 'tabbar_home_selected_30x30', Home)} {/* 海淘 */} {this.renderTabBarItem("海淘", 'ht', 'tabbar_abroad_30x30', 'tabbar_abroad_selected_30x30', HT)} {/* 小时风云榜 */} {this.renderTabBarItem("小时风云榜", 'hourlist', 'tabbar_rank_30x30', 'tabbar_rank_selected_30x30', HourList)} </TabNavigator> ); } } const styles = StyleSheet.create({ container: { flex: 1, justifyContent: 'center', alignItems: 'center', backgroundColor: '#F5FCFF', }, tabbarIconStyle: { width:Platform.OS === 'ios' ? 30 : 25, height:Platform.OS === 'ios' ? 30 : 25, } });
从效果图中能够看出,导航栏的样式都差很少,由于咱们前面已经设置了 Navigator ,这边的话咱们还须要自定义 Navigator 的样式,能够看到全部的 Navigator 样式都是相近的,因此这边咱们就抽出来,让全部的 Navigator 共用一个组件就能够了。
那么首先咱们在 main 文件夹中建立 GDCommunalNavBar 文件并初始化一下里面基本的内容
接着,咱们来看下首页的导航栏,首页导航栏分别有左中右三个按钮,左边为半小时热门,中间为点击下拉显示支持筛选的平台的列表,右边则是商品搜索,一般 Navigator 也只有这3个组件,为了使用者高度地自定义,这边咱们只在 currencyNavBar 中设置3个组件的布局,而后提供接口,获取外部传入的值,并在内部判断是否须要建立相应的组件。
export default class GDCommunalNavBar extends Component { static propTypes = { leftItem:PropTypes.func, titleItem:PropTypes.func, rightItem:PropTypes.func, }; // 左边 renderLeftItem() { if (this.props.leftItem === undefined) return; return this.props.leftItem(); } // 中间 renderTitleItem() { if (this.props.titleItem === undefined) return; return this.props.titleItem(); } // 右边 renderRightItem() { if (this.props.rightItem === undefined) return; return this.props.rightItem(); } render() { return ( <View style={styles.container}> {/* 左边 */} <View> {this.renderLeftItem()} </View> {/* 中间 */} <View> {this.renderTitleItem()} </View> {/* 右边 */} <View> {this.renderRightItem()} </View> </View> ); } } const styles = StyleSheet.create({ container: { width:width, height:Platform.OS === 'ios' ? 64 : 44, backgroundColor:'white', flexDirection:'row', justifyContent:'space-between', alignItems:'center', borderBottomWidth:0.5, borderBottomColor:'gray', paddingTop:Platform.OS === 'ios' ? 15 : 0, }, });
[Upload 自定义Navigator样式.gif failed. Please try again.]
咱们先将数据请求下来,肯定正确获取到数据后,再来定义 cell 的样式。
接下来咱们来自定义一下 cell 样式
export default class GDCommunalNavBar extends Component { static propTypes = { image:PropTypes.string, title:PropTypes.string, }; render() { return ( <View style={styles.container}> {/* 左边图片 */} <Image source={{uri:this.props.image}} style={styles.imageStyle} /> {/* 中间的文中 */} <View> <Text numberOfLines={3} style={styles.titleStyle}>{this.props.title}</Text> </View> {/* 右边的箭头 */} <Image source={{uri:'icon_cell_rightArrow'}} style={styles.arrowStyle} /> </View> ); } } const styles = StyleSheet.create({ container: { flexDirection:'row', alignItems:'center', justifyContent:'space-between', backgroundColor:'white', height:100, width:width, borderBottomWidth:0.5, borderBottomColor:'gray', marginLeft:15 }, imageStyle: { width:70, height:70, }, titleStyle: { width:width * 0.65, }, arrowStyle: { width:10, height:10, marginRight:30 } });
export default class GDHalfHourHot extends Component { // 构造 constructor(props) { super(props); // 初始状态 this.state = { dataSource: new ListView.DataSource({rowHasChanged:(r1, r2) => r1 !== r2}), }; // 绑定 this.fetchData = this.fetchData.bind(this); } // 网络请求 fetchData() { fetch('http://guangdiu.com/api/gethots.php') .then((response) => response.json()) .then((responseData) => { this.setState({ dataSource: this.state.dataSource.cloneWithRows(responseData.data) }); }) .done() } popToHome() { this.props.navigator.pop(); } // 返回中间按钮 renderTitleItem() { return( <Text style={styles.navbarTitleItemStyle}>近半小时热门</Text> ); } // 返回右边按钮 renderRightItem() { return( <TouchableOpacity onPress={()=>{this.popToHome()}} > <Text style={styles.navbarRightItemStyle}>关闭</Text> </TouchableOpacity> ); } // 返回每一行cell的样式 renderRow(rowData) { return( <CommunalHotCell image={rowData.image} title={rowData.title} /> ); } componentDidMount() { this.fetchData(); } render() { return ( <View style={styles.container}> {/* 导航栏样式 */} <CommunalNavBar titleItem = {() => this.renderTitleItem()} rightItem = {() => this.renderRightItem()} /> <ListView dataSource={this.state.dataSource} renderRow={this.renderRow} showsHorizontalScrollIndicator={false} style={styles.listViewStyle} /> </View> ); } } const styles = StyleSheet.create({ container: { flex:1, alignItems: 'center', }, navbarTitleItemStyle: { fontSize:17, color:'black', marginLeft:50 }, navbarRightItemStyle: { fontSize:17, color:'rgba(123,178,114,1.0)', marginRight:15 }, listViewStyle: { width:width, } });
{/* 顶部提示 */} <View style={styles.headerPromptStyle}> <Text>根据每条折扣的点击进行统计,每5分钟更新一次</Text> </View>
样式部分:
headerPromptStyle: { height:44, width:width, backgroundColor:'rgba(239,239,239,0.5)', justifyContent:'center', alignItems:'center' }
// ES6 // 构造 constructor(props) { super(props); // 初始状态 this.state = { selectedTab:'home', isHiddenTabBar:false, // 是否隐藏tabbar }; } <TabNavigator tabBarStyle={this.state.isHiddenTabBar !== true ? {} : {height:0, overflow:'hidden'}} sceneStyle={this.state.isHiddenTabBar !== true ? {} : {paddingBottom:0}} > {/* 首页 */} {this.renderTabBarItem("首页", 'home', 'tabbar_home_30x30', 'tabbar_home_selected_30x30', Home)} {/* 海淘 */} {this.renderTabBarItem("海淘", 'ht', 'tabbar_abroad_30x30', 'tabbar_abroad_selected_30x30', HT)} {/* 小时风云榜 */} {this.renderTabBarItem("小时风云榜", 'hourlist', 'tabbar_rank_30x30', 'tabbar_rank_selected_30x30', HourList)} </TabNavigator>
这边咱们引入新的知识 —— 通知
使用通知很简单,首先须要注册通知并在适当的地方进行销毁
componentDidMount() { // 注册通知 this.subscription = DeviceEventEmitter.addListener('isHiddenTabBar', (data)=>{this.tongZhi(data)}); } componentWillUnmount() { // 销毁 this.subscription.remove(); }
componentWillMount() { // 发送通知 DeviceEventEmitter.emit('isHiddenTabBar', true); } componentWillUnmount() { // 发送通知 DeviceEventEmitter.emit('isHiddenTabBar', false); }