資料:連接: 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); }