这个项目应该是一个标杆项目,看到之前很有几个项目都是按照这个项目的页面摆放顺序来的
不过可以作为自己做项目的一种方式
源码地址为:https://github.com/pgg-pgg/imooc_gp
项目的数据流是mobx
启动页不是定时器自动跳转那种,而是滑动那种
我们分析代码如下



上面是启动页的

//index.js
/** @format */import {AppRegistry} from 'react-native';
import setup from "./js/pages/setup"
import {name as appName} from './app.json';AppRegistry.registerComponent(appName, () => setup);
//js/pages/setup.js
/*** Sample React Native App* https://github.com/facebook/react-native** @format* @flow*/import React, {Component} from 'react';
import {Navigator} from 'react-native-deprecated-custom-components'
import MobxTest from "../MobxTest";
import MyPageTest from "./My/MyPageTest";
import WelcomePage from "./WelcomePage";function setup() {//进行一些初始化的配置class Root extends Component {renderScene(route, navigator) {let Component = route.component;return <Component {...route.params} navigator={navigator}/>}render() {return <NavigatorinitialRoute={{component: WelcomePage}}renderScene={(route, navigator)=>this.renderScene(route, navigator)}/>}}return <Root/>;
}module.exports = setup;

首先进入的是welcomePage页面

//js/pages/WelcomePage.js
import React, {Component} from 'react';
import {Platform,StyleSheet,Image,Text,View, AsyncStorage,
} from 'react-native';
import NavigationBar from "../common/NavigationBar"
import HomePage from "./HomePage"
import GuidePage from "./GuidePage";
import ThemeDao from "../expand/dao/ThemeDao";
import SplashScreen from 'react-native-splash-screen'
export default class WelcomePage extends Component{openApp(){//进行了判断是不是第一次打开AsyncStorage.getItem('isFirst',(error,result)=>{if (result === 'false') {console.log('不是第一次打开');this.props.navigator.resetTo({//不是第一次打开就是进入home页面component:HomePage,params:{theme:this.theme,...this.props}})} else  {console.log('第一次打开');//是第一次打开就进入导航页this.props.navigator.replace({component:GuidePage,params:{theme:this.theme,...this.props}})}});}componentDidMount(): void {new ThemeDao().getTheme().then(data=>{this.theme = data;})this.timer = setTimeout(()=>{SplashScreen.hide();this.openApp()},1000)}componentWillUnmount(): void {this.timer&&clearTimeout(this.timer);}constructor(props){super(props)}render(){return null;}
}

第一次打开进入的导航页面

//GuidePage
import {StyleSheet, View, Button, Text, Image, TouchableOpacity,AsyncStorage} from 'react-native';
import React, {Component} from 'react';
import {PagerTabIndicator, IndicatorViewPager, PagerTitleIndicator, PagerDotIndicator} from 'rn-viewpager';
import HomePage from "./HomePage";export default class GuidePage extends Component {render() {let text1 = '消费者第一\n合作伙伴第二\nQunar第三';let text2 = '大声说话\n无\'总\'称谓\n遇到批评三不问';let text3 = '高层不诿过\n中层不放羊\n基层不跳步';return (<View style={{flex: 1}}><IndicatorViewPagerstyle={{flex: 1}}indicator={GuidePage._renderDotIndicator()}><View style={{backgroundColor: '#ff8800', justifyContent: 'center'}}><Image resizeMode={'contain'} style={styles.image}source={require('../../res/images/s_0_1.png')}/><Text style={styles.text_desc}>{text1}</Text></View><View style={{backgroundColor: '#669900', justifyContent: 'center'}}><Image resizeMode={'contain'} style={styles.image}source={require('../../res/images/s_1_1.png')}/><Text style={styles.text_desc}>{text2}</Text></View><View style={{backgroundColor: '#aa66cc', justifyContent: 'center'}}><Image resizeMode={'contain'} style={styles.image}source={require('../../res/images/s_2_1.png')}/><Text style={styles.text_desc}>{text3}</Text><TouchableOpacity onPress={()=>{// 存储AsyncStorage.setItem('isFirst','false',(error)=>{if (error) {alert(error);}});this.props.navigator.resetTo({component:HomePage,params:{// theme:this.props.theme,...this.props}})}}><Text style={styles.text}>开始使用</Text></TouchableOpacity></View></IndicatorViewPager></View>);}static _renderDotIndicator() {return <PagerDotIndicator pageCount={3}/>;}}const styles = StyleSheet.create({text: {alignSelf: 'center',padding: 5,backgroundColor: '#2196f3',borderRadius: 5,fontSize: 18,color: 'white',},text_desc: {height:200,textAlign: 'center',textAlignVertical:'center',fontSize: 20,color: 'white',alignSelf: 'center',},image: {width: 200,height: 200,alignSelf: 'center'},btn: {width: 150,height: 40,backgroundColor: '#1296db',borderRadius: 8,justifyContent: 'center',alignItems: 'center',marginBottom: 50},btnText: {fontSize: 18,color: '#fff'},});

//js/pages/HomePage.js
//里面的tab切换,根据选中的跳转进去不同的页面
/*** Sample React Native App* https://github.com/facebook/react-native** @format* @flow*/import React, {Component} from 'react';
import {Platform,StyleSheet,Image,Text,View,DeviceEventEmitter,} from 'react-native';
import TabNavigator from 'react-native-tab-navigator'
import PopularPage from "./popular/PopularPage";
import Toast ,{DURATION}from "react-native-easy-toast";
import TrendingPage from "./trending/TrendingPage";
import FavoritePage from "./favorite/FavoritePage";
import MyPage from "./My/MyPage";
import BaseComponent from "./BaseComponent";
import codePush from "react-native-code-push";export const ACTION_HOME = {A_SHOW_TOAST:'showToast',A_RESTART:'restart',A_THEME:'THEME'};
export const FLAG_TAB={flag_popularTab:'tb_popular',flag_trendingTab:'tb_trending',flag_favoriteTab:'tb_favorite',flag_myTab:'tb_my',
}
export default class HomePage extends BaseComponent {constructor(props) {super(props);let selectedTab=this.props.selectedTab?this.props.selectedTab:'tb_popular';this.state = {selectedTab: selectedTab,theme:this.props.theme,}}componentDidMount(): void {super.componentDidMount();this.listener = DeviceEventEmitter.addListener('ACTION_HOME',(action,params)=>this.onAction(action,params));this.update();}/*** 想codepush检查更新*/update(){codePush.sync({updateDialog:{appendReleaseDescription:true,descriptionPrefix:'更新内容',title:'更新',mandatoryUpdateMessage:'',mandatoryContinueButtonLabel:'更新',},mandatoryInstallMode:codePush.InstallMode.ON_NEXT_RESTART,});}/*** 通知回调事件处理* @param action* @param params*/onAction(action,params){if(ACTION_HOME.A_RESTART===action){this.onRestart(params)}else if(ACTION_HOME.A_SHOW_TOAST===action){this.toast.show(params.text,DURATION.LENGTH_SHORT);}}/*** 重启首页* @param jumpToTab*/onRestart(jumpToTab){this.props.navigator.resetTo({component:HomePage,params:{...this.props,selectedTab:jumpToTab}})}componentWillUnmount(): void {super.componentWillUnmount();if (this.listener) {this.listener.remove();}}_renderType(Component,selectTab,title,renderIcon){return  <TabNavigator.Itemselected={this.state.selectedTab === selectTab}selectedTitleStyle={this.state.theme.styles.selectedTitleStyle}title={title}renderIcon={() => <Image style={styles.image} source={renderIcon}/>}renderSelectedIcon={() => <Image style={[styles.image,this.state.theme.styles.tabBarSelectedIcon]} source={renderIcon}/>}// badgeText="1"onPress={() => this.setState({selectedTab: selectTab})}><View style={styles.page1}><Component {...this.props} theme={this.state.theme}/></View></TabNavigator.Item>}render() {return (// tab切换<View style={styles.container}><TabNavigator>{this._renderType(PopularPage,'tb_popular','最热',require('../../res/images/ic_polular.png'))}{this._renderType(TrendingPage,'tb_trending','趋势',require('../../res/images/ic_trending.png'))}{this._renderType(FavoritePage,'tb_favorite','收藏',require('../../res/images/ic_favorite.png'))}{this._renderType(MyPage,'tb_my','我的',require('../../res/images/ic_my.png'))}</TabNavigator><Toast ref={toast=>this.toast=toast}/></View>);}
}const styles = StyleSheet.create({container: {flex: 1,backgroundColor: '#F5FCFF',},page1:{flex: 1,},page2:{flex: 2,backgroundColor: 'green'},image:{width:22,height:22}
});
//其实挺有意思的

tab首先的页面

应该只是布局,然后从后端请求数据渲染即可
代码如下:

//js/pages/popular/PopularPage.js
import React, {Component} from 'react';
import {Image,StyleSheet, TouchableOpacity,View,
} from 'react-native';
import NavigationBar from "../../common/NavigationBar";
import ScrollableTabView, {ScrollableTabBar} from 'react-native-scrollable-tab-view'
import LanguageDao, {FLAG_LANGUAGE} from '../../expand/dao/LanguageDao'
import PopularTab from "./PopularTab";
import ViewUtils from "../../util/ViewUtils";
import SearchPage from "../SearchPage";
import {MORE_MENU} from "../../common/MoreMenu";
import {FLAG_TAB} from "../HomePage";
import MoreMenu from "../../common/MoreMenu";
import BaseComponent from "../BaseComponent";
import CustomTheme from "../My/CustomTheme";export default class PopularPage extends BaseComponent {constructor(props) {super(props);this.languageDao = new LanguageDao(FLAG_LANGUAGE.flag_key);this.state = {languages: [],customThemeViewVisible: false,theme:this.props.theme,}}componentDidMount() {super.componentDidMount()//渲染数据this.loadData();}loadData() {//取出数据this.languageDao.fetch().then(result => {this.setState({languages: result})}).catch(error => {console.log(error)})}
//点击不同的语言界面,最后是进入不同的语言列表新闻中renderRightButton() {return <View style={{flexDirection:'row'}}><TouchableOpacityonPress={()=> {this.props.navigator.push({component:SearchPage,params:{...this.props}})}}><View style={{padding:5,marginRight:8}}><Imagestyle={{width:24,height:24}}source={require('../../../res/images/ic_search_white_48pt.png')}/></View></TouchableOpacity>{ViewUtils.getMoreButton(()=>this.refs.moreMenu.open())}</View>}renderMoreView(){let params={...this.props,fromPage:FLAG_TAB.flag_popularTab};return <MoreMenuref="moreMenu"{...params}menus={[MORE_MENU.Custom_Key,MORE_MENU.Sort_Key,MORE_MENU.Remove_Key,MORE_MENU.Share,MORE_MENU.Custom_Theme,MORE_MENU.About_Author,MORE_MENU.About]}anchorView={()=>this.refs.moreMenuButton}onMoreMenuSelect={(e)=> {if (e === MORE_MENU.Custom_Theme) {this.setState({customThemeViewVisible:true})}}}/>}renderCustomThemeView() {return (<CustomTheme visible={this.state.customThemeViewVisible}{...this.props}onClose={() => {this.setState({customThemeViewVisible: false,})}}/>)}render() {let statusBar = {backgroundColor:this.state.theme.themeColor,barStyle:'light-content',};//判断语言切换的,这边用到的是ScrollableTabView组件let content = this.state.languages.length > 0 ? <ScrollableTabViewtabBarBackgroundColor={this.state.theme.themeColor}tabBarActiveTextColor='#fff'tabBarInactiveTextColor='#333'tabBarUnderlineStyle={{backgroundColor: '#e7e7e7', height: 2}}renderTabBar={() => <ScrollableTabBar/>}>{this.state.languages.map((result, i, arr) => {let lan = arr[i];return lan.checked ?<PopularTab key={i} tabLabel={lan.name} {...this.props}/>: null;})}</ScrollableTabView> : null;//底部图标切换return <View style={styles.container}><NavigationBartitle={'最热'}leftButton={<View/>}rightButton={this.renderRightButton()}statusBar={statusBar}style={this.state.theme.styles.navBar}/>{content}{this.renderMoreView()}{this.renderCustomThemeView()}</View>}
}const styles = StyleSheet.create({container: {flex: 1,backgroundColor: '#F5FCFF',},});
//js/pages/popular/PopularTab.js
//下拉刷新和获取数据
import React, {Component} from 'react';
import {DeviceEventEmitter, ListView, RefreshControl, StyleSheet, View} from "react-native";
import ProjectModel from "../../model/ProjectModel";
import Utils from "../../util/Utils";
import DescPage from "./DescPage";
import {FLAG_STORAGE} from "../../expand/dao/DataRepository";
import RepositoryCell from "../../common/RepositoryCell";
import FavoriteDao from "../../expand/dao/FavoriteDao";
import DataRepository from "../../expand/dao/DataRepository";
import ActionUtils from "../../util/ActionUtils";const URL = "https://api.github.com/search/repositories?q=";
const QUERY_STR = '&sort=stars';
const favoriteDao = new FavoriteDao(FLAG_STORAGE.flag_popular);
const dataRepository = new DataRepository(FLAG_STORAGE.flag_popular);export default class PopularTab extends Component {constructor(props) {super(props);this.isFavoriteChange=false;this.state = {result: '',isLoading: false,dataSource: new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2}),favoriteKeys :[],theme:this.props.theme,}}componentDidMount(): void {this.onLoad();this.listener= DeviceEventEmitter.addListener('favoriteChanged_popular',()=>{this.isFavoriteChange = true;})}componentWillUnmount(): void {if (this.listener){this.listener.remove();}}componentWillReceiveProps(nextProps: Readonly<P>, nextContext: any): void {if (this.isFavoriteChange) {this.isFavoriteChange=false;this.getFavoriteKeys()}else if (nextProps.theme !== this.state.theme) {this.updateState({theme:nextProps.theme,})this.flushFavoriteState()}}/*** 更新project item收藏状态*/flushFavoriteState(){let projectModels = [];let items = this.items;for(let i =0 ,len = items.length;i<len;i++){projectModels.push(new ProjectModel(items[i],Utils.checkFavorite(items[i],this.state.favoriteKeys)))}this.updateState({isLoading:false,dataSource:this.getDataSource(projectModels),})}getDataSource(data){return this.state.dataSource.cloneWithRows(data);}getFavoriteKeys(){favoriteDao.getFavoriteKeys().then(keys=>{if (keys) {this.updateState({favoriteKeys: keys})}this.flushFavoriteState();}).catch(e=>{this.flushFavoriteState()})}updateState(dic){if (!this) return;this.setState(dic);}onLoad() {this.updateState({isLoading: true});let url = URL + this.props.tabLabel + QUERY_STR;dataRepository.fetchRepository(url).then(result => {this.items = result && result.items ? result.items : result ? result : [];this.getFavoriteKeys();if (!this.items||result && result.update_date && !dataRepository.checkData(result.update_date)) {return dataRepository.fetchNetRepository(url)}}).then(items => {if (!items || items.length === 0) {return;} else {this.items=items;this.getFavoriteKeys()}}).catch(error => {console.log(error);this.updateState({isLoading:false,})});}choose(projectModel) {return <RepositoryCellonSelect={()=>ActionUtils.onSelectRepository({flag: FLAG_STORAGE.flag_popular,...this.props,projectModel: projectModel,})}theme={this.state.theme}key={projectModel.item.id}onFavorite={(item,isFavorite)=>ActionUtils.onFavorite(favoriteDao,item, isFavorite)}projectModel={projectModel}/>}render() {return <View style={styles.container}><ListViewdataSource={this.state.dataSource}renderRow={(data) => this.choose(data)}refreshControl={<RefreshControlrefreshing={this.state.isLoading}onRefresh={() => this.onLoad()}color={this.state.theme.themeColor}tintColor={this.state.theme.themeColor}title={'Loading...'}titleColor={this.state.theme.themeColor}/>}/></View>}}const styles = StyleSheet.create({container: {flex: 1,backgroundColor: '#F5FCFF',},page1: {flex: 1,backgroundColor: 'red'},page2: {flex: 2,backgroundColor: 'green'},image: {width: 22,height: 22},item: {backgroundColor: '#169',height: 100,margin: 15,alignItems: 'center',justifyContent: 'center',},text_my: {color: 'black',fontSize: 20,},text: {color: 'white',fontSize: 20,},indicatorContainer: {alignItems: 'center'},indicator: {color: 'red',margin: 10}
});
//js/pages/popular/store/Store.js
import {observable} from "mobx";
import DataRepository from "../../../expand/dao/DataRepository";export default class PopularStore {api;@observable popularItems=[];constructor(){this.api=new DataRepository();}getPopularItem(id){return this.popularItems.find(item=>item.id.toString()===id);}@action.bound()fetchPopularList(tabLabel){return this.api.getPopularInfo(tabLabel).then(action(result => {this.items = result && result.items ? result.items : result ? result : [];this.getFavoriteKeys();if (!this.items||result && result.update_date && !dataRepository.checkData(result.update_date)) {return dataRepository.fetchNetRepository(url)}}).then(items => {if (!items || items.length === 0) {return;} else {this.items=items;this.getFavoriteKeys()}}).catch(error => {console.log(error);this.updateState({isLoading:false,})}));}}
//js/pages/popular/model/ProjectModel.js
import {observable} from "mobx";export default class ProjectModel{@observable item;@observable isFavorite;
}
//js/pages/popular/DescPage.js
import React, {Component} from 'react'
import {View,StyleSheet,WebView,TouchableOpacity,Image,} from 'react-native'
import NavigationBar from "../../common/NavigationBar";
import ViewUtils from "../../util/ViewUtils";
import FavoriteDao from "../../expand/dao/FavoriteDao";
import share from "../../../res/data/share";
import UShare from "../../common/UShare";
import BackPressComponent from "../../common/BackPressComponent";const TRENDING_URL = 'https://github.com/';
export default class DescPage extends Component {constructor(props) {super(props);// alert(this.props.title);this.backPress = new BackPressComponent({backPress:(e)=>this.onBackPress(e)});this.url = this.props.projectModel.item.html_url ? this.props.projectModel.item.html_url : TRENDING_URL + this.props.projectModel.item.fullName;let title = this.props.projectModel.item.full_name ? this.props.projectModel.item.full_name : this.props.projectModel.item.fullName;this.favoriteDao = new FavoriteDao(this.props.flag);this.state = {url: this.url,title: title,canGoBack: false,isFavorite: this.props.projectModel.isFavorite,favoriteIcon: this.props.projectModel.isFavorite ? require('../../../res/images/ic_star.png'): require('../../../res/images/ic_star_navbar.png'),theme: this.props.theme,}}componentDidMount(): void {this.backPress.componentDidMount();}componentWillUnmount(): void {this.backPress.componentWillUnmount();if (this.props.onUpdateFavorite)this.props.onUpdateFavorite();}onBack() {if (this.state.canGoBack) {this.webView.goBack()} else {this.props.navigator.pop();}}onBackPress(e){this.onBack();return true;}go() {this.setState({url: this.text})}onNavigationStateChange(e) {this.setState({canGoBack: e.canGoBack,url: e.url,})}onRightButtonClick() {let projectModel = this.props.projectModel;this.setFavoriteState(projectModel.isFavorite = !projectModel.isFavorite);const key = projectModel.item.fullName ? projectModel.item.fullName : projectModel.item.id.toString();if (projectModel.isFavorite) {this.favoriteDao.saveFavoriteItem(key, JSON.stringify(projectModel.item))} else {this.favoriteDao.removeFavoriteItem(key)}}setFavoriteState(isFavorite) {this.setState({isFavorite: isFavorite,favoriteIcon: isFavorite ? require('../../../res/images/ic_star.png'): require('../../../res/images/ic_star_navbar.png')})}renderRightButton() {return <View style={{flexDirection: 'row'}}>{ViewUtils.getShareButton(()=>this.shareInfo())}<TouchableOpacity onPress={() => this.onRightButtonClick()}><Image style={{width: 20, height: 20, marginRight: 10}} source={this.state.favoriteIcon}/></TouchableOpacity></View>}shareInfo(){const shareApp = share.share_app;UShare.share(shareApp.title, shareApp.content,shareApp.imgUrl,shareApp.url,()=>{},()=>{});}render() {let statusBar = {backgroundColor: this.state.theme.themeColor};let titleLayoutStyle = this.state.title.length>20?{paddingRight: 30}:null;return <View style={styles.container}><NavigationBartitle={this.state.title}statusBar={statusBar}titleLayoutStyle={titleLayoutStyle}style={this.state.theme.styles.navBar}rightButton={this.renderRightButton()}leftButton={ViewUtils.getLeftButton(() => this.onBack())}/><WebView ref={webView => this.webView = webView}source={{uri: this.state.url}}startInLoadingState={true}onNavigationStateChange={(e) =>this.onNavigationStateChange(e)}></WebView></View>}}const styles = StyleSheet.create({container: {flex: 1},tips: {fontSize: 20},row: {flexDirection: 'row',alignItems: 'center',margin: 10},input: {height: 40,flex: 1,borderWidth: 1,margin: 2,}
});

趋势页面跟最热页面类似

//js/pages/trending/TrendingPage.js
import React, {Component} from 'react';
import {Platform,StyleSheet,Image,Text,View,TextInput,ListView,RefreshControl,DeviceEventEmitter,TouchableOpacity,
} from 'react-native';
import NavigationBar from "../../common/NavigationBar"
import DataRepository, {FLAG_STORAGE} from "../../expand/dao/DataRepository"
import ScrollableTabView, {ScrollableTabBar} from 'react-native-scrollable-tab-view'
import RepositoryCell from "../../common/RepositoryCell";
import LanguageDao, {FLAG_LANGUAGE} from '../../expand/dao/LanguageDao'
import DescPage from "../popular/DescPage";
import TrendingCell from "../../common/TrendingCell";
import TimeSpan from "../../model/TimeSpan";
import Popover from "../../common/Popover";
import FavoriteDao from "../../expand/dao/FavoriteDao";
import ProjectModel from "../../model/ProjectModel";
import Utils from "../../util/Utils";
import ActionUtils from "../../util/ActionUtils";
import {FLAG_TAB} from "../HomePage";
import MoreMenu, {MORE_MENU} from "../../common/MoreMenu";
import ViewUtils from "../../util/ViewUtils";
import BaseComponent from "../BaseComponent";
import CustomTheme from "../My/CustomTheme";const API_URL = "https://github.com/trending/";
var timeSpanTextArray = [new TimeSpan('今 天', 'since=daily'), new TimeSpan('本 周', 'since=weekly'), new TimeSpan('本 月', 'since=monthly')];
var favoriteDao = new FavoriteDao(FLAG_STORAGE.flag_trending);
var dataRespository = new DataRepository(FLAG_STORAGE.flag_trending);export default class TrendingPage extends BaseComponent {constructor(props) {super(props);this.languageDao = new LanguageDao(FLAG_LANGUAGE.flag_language);this.state = {languages: [],isVisible: false,buttonRect: {},timeSpan: timeSpanTextArray[0],theme:this.props.theme,customThemeViewVisible: false,}}componentDidMount() {super.componentDidMount();this.loadData();}componentWillReceiveProps(nextProps: Readonly<P>, nextContext: any): void {if (nextProps.timeSpan !== this.props.timeSpan) {this.loadData(nextProps.timeSpan)}}loadData() {this.languageDao.fetch().then(result => {this.setState({languages: result})}).catch(error => {console.log(error)})}showPopover() {this.refs.button.measure((ox, oy, width, height, px, py) => {this.setState({isVisible: true,buttonRect: {x: px, y: py, width: width, height: height}});});}closePopover() {this.setState({isVisible: false,});}renderTitleView() {return <View><TouchableOpacity ref={'button'} onPress={() => {this.showPopover()}}><View style={{flexDirection: 'row', alignItems: 'center'}}><Text style={{fontSize: 18,color: 'white',fontWeight: '400'}}>趋势 {this.state.timeSpan.showText}</Text><Image style={{width: 12, height: 12, marginLeft: 5}}source={require('../../../res/images/ic_spinner_triangle.png')}/></View></TouchableOpacity></View>}onSelectTimeSpan(timeSpan) {this.setState({timeSpan: timeSpan,isVisible: false,})}renderMoreView() {let params = {...this.props, fromPage: FLAG_TAB.flag_popularTab};return <MoreMenuref="moreMenu"{...params}menus={[MORE_MENU.Custom_Language, MORE_MENU.Sort_Language,MORE_MENU.Share, MORE_MENU.Custom_Theme,MORE_MENU.About_Author, MORE_MENU.About]}anchorView={() => this.refs.moreMenuButton}onMoreMenuSelect={(e) => {if (e === MORE_MENU.Custom_Theme) {this.setState({customThemeViewVisible: true})}}}/>}renderCustomThemeView() {return (<CustomTheme visible={this.state.customThemeViewVisible}{...this.props}onClose={() => {this.setState({customThemeViewVisible: false,})}}/>)}render() {let statusBar = {backgroundColor:this.state.theme.themeColor};let content = this.state.languages.length > 0 ? <ScrollableTabViewtabBarBackgroundColor={this.state.theme.themeColor}tabBarActiveTextColor='#fff'tabBarInactiveTextColor='#333'tabBarUnderlineStyle={{backgroundColor: '#e7e7e7', height: 2}}renderTabBar={() => <ScrollableTabBar/>}>{this.state.languages.map((result, i, arr) => {let lan = arr[i];return lan.checked ?<TrendingTab key={i} tabLabel={lan.name}timeSpan={this.state.timeSpan} {...this.props}>{lan.name}</TrendingTab> : null;})}</ScrollableTabView> : null;let timeSpanView = <PopoverisVisible={this.state.isVisible}fromRect={this.state.buttonRect}placement={'bottom'}contentStyle={{backgroundColor: '#343434', opacity: 0.5}}onClose={() => this.closePopover()}>{timeSpanTextArray.map((result, i, arr) => {return <TouchableOpacity key={i} underlayColor={'transparent'}onPress={() => this.onSelectTimeSpan(arr[i])}><Text style={{fontSize: 18, color: 'white', padding: 8, fontWeight: '400'}}>{arr[i].showText}</Text></TouchableOpacity>})}</Popover>;return <View style={styles.container}><NavigationBartitleView={this.renderTitleView()}leftButton={<View/>}rightButton={ViewUtils.getMoreButton(() => this.refs.moreMenu.open())}statusBar={statusBar}style={this.state.theme.styles.navBar}/>{content}{timeSpanView}{this.renderMoreView()}{this.renderCustomThemeView()}</View>}
}class TrendingTab extends Component {constructor(props) {super(props);this.isFavoriteChange = false;this.state = {result: '',isLoading: false,dataSource: new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2}),favoriteKeys: [],theme:this.props.theme,}}/*** 更新project item收藏状态*/flushFavoriteState() {let projectModels = [];let items = this.items;for (let i = 0, len = items.length; i < len; i++) {projectModels.push(new ProjectModel(items[i], Utils.checkFavorite(items[i], this.state.favoriteKeys)))}this.updateState({isLoading: false,dataSource: this.getDataSource(projectModels),})}getDataSource(data) {return this.state.dataSource.cloneWithRows(data);}getFavoriteKeys() {favoriteDao.getFavoriteKeys().then(keys => {if (keys) {this.updateState({favoriteKeys: keys})}this.flushFavoriteState();}).catch(e => {this.flushFavoriteState()})}updateState(dic) {if (!this) return;this.setState(dic);}componentDidMount(): void {this.onLoad(this.props.timeSpan, true)this.listener = DeviceEventEmitter.addListener('favoriteChanged_trending', () => {this.isFavoriteChange = true;})}onUpdateFavorite() {this.getFavoriteKeys();}componentWillUnmount(): void {if (this.listener) {this.listener.remove();}}componentWillReceiveProps(nextProps: Readonly<P>, nextContext: any): void {if (this.isFavoriteChange) {this.isFavoriteChange = false;this.getFavoriteKeys()}else if (nextProps.theme !== this.state.theme) {this.updateState({theme:nextProps.theme,});this.flushFavoriteState()}}getFetchUrl(timeSpan, category) {return API_URL + category + '?' + timeSpan.searchText}onLoad(timeSpan, isRefresh) {this.updateState({isLoading: true});let url = this.getFetchUrl(timeSpan, this.props.tabLabel)dataRespository.fetchRepository(url).then(result => {this.items = result && result.items ? result.items : result ? result : [];this.getFavoriteKeys();if (!this.items || isRefresh && result && result.update_date && !dataRespository.checkData(result.update_date)) {return dataRespository.fetchNetRepository(url)}}).then(items => {if (!items || items.length === 0) {return;} else {this.items = items;this.getFavoriteKeys();}}).catch(error => {this.updateState({isLoading: false})});}choose(projectModel) {return <TrendingCellonSelect={() => ActionUtils.onSelectRepository({projectModel: projectModel,flag: FLAG_STORAGE.flag_trending,...this.props,parentComponent: this,onUpdateFavorite: ()=>this.onUpdateFavorite(),})}theme={this.props.theme}key={projectModel.item.fullName}onFavorite={(item, isFavorite) => ActionUtils.onFavorite(favoriteDao, item, isFavorite, FLAG_STORAGE.flag_trending)}projectModel={projectModel}/>}onRefresh() {this.onLoad(this.props.timeSpan, true);}render() {return <View style={styles.container}><ListViewdataSource={this.state.dataSource}renderRow={(data) => this.choose(data)}refreshControl={<RefreshControlrefreshing={this.state.isLoading}onRefresh={() => this.onRefresh()}color={this.state.theme.themeColor}tintColor={this.state.theme.themeColor}title={'Loading...'}titleColor={this.state.theme.themeColor}/>}/></View>}}const styles = StyleSheet.create({container: {flex: 1,backgroundColor: '#F5FCFF',},page1: {flex: 1,backgroundColor: 'red'},page2: {flex: 2,backgroundColor: 'green'},image: {width: 22,height: 22},item: {backgroundColor: '#169',height: 100,margin: 15,alignItems: 'center',justifyContent: 'center',},text_my: {color: 'black',fontSize: 20,},text: {color: 'white',fontSize: 20,},indicatorContainer: {alignItems: 'center'},indicator: {color: 'red',margin: 10}
});

//收藏页面
//js/pages/favorite/FavoritePage.js
import React, {Component} from 'react';
import {StyleSheet,View,ListView,RefreshControl,DeviceEventEmitter,
} from 'react-native';
import NavigationBar from "../../common/NavigationBar"
import {FLAG_STORAGE} from "../../expand/dao/DataRepository"
import ScrollableTabView, {ScrollableTabBar} from 'react-native-scrollable-tab-view'
import RepositoryCell from "../../common/RepositoryCell";
import DescPage from "../popular/DescPage";
import ProjectModel from "../../model/ProjectModel";
import FavoriteDao from "../../expand/dao/FavoriteDao";
import TrendingCell from "../../common/TrendingCell";
import ArrayUtils from "../../util/ArrayUtils";
import ActionUtils from "../../util/ActionUtils";
import MoreMenu, {MORE_MENU} from "../../common/MoreMenu";
import {FLAG_TAB} from "../HomePage";
import ViewUtils from "../../util/ViewUtils";
import BaseComponent from "../BaseComponent";
import CustomTheme from "../My/CustomTheme";export default class FavoritePage extends BaseComponent {constructor(props) {super(props);this.state = {theme: this.props.theme,customThemeViewVisible: false,}}renderMoreView() {let params = {...this.props, fromPage: FLAG_TAB.flag_popularTab}return <MoreMenuref="moreMenu"{...params}menus={[MORE_MENU.Custom_Theme, MORE_MENU.Share,MORE_MENU.About_Author, MORE_MENU.About]}anchorView={() => this.refs.moreMenuButton}onMoreMenuSelect={(e) => {if (e === MORE_MENU.Custom_Theme) {this.setState({customThemeViewVisible: true})}}}/>}renderCustomThemeView() {return (<CustomTheme visible={this.state.customThemeViewVisible}{...this.props}onClose={() => {this.setState({customThemeViewVisible: false,})}}/>)}render() {let statusBar = {backgroundColor: this.state.theme.themeColor};let content = <ScrollableTabViewtabBarBackgroundColor={this.state.theme.themeColor}tabBarActiveTextColor='#fff'tabBarInactiveTextColor='#333'tabBarUnderlineStyle={{backgroundColor: '#e7e7e7', height: 2}}renderTabBar={() => <ScrollableTabBar/>}><FavoriteTab tabLabel='最热' flag={FLAG_STORAGE.flag_popular} {...this.props}/><FavoriteTab tabLabel='趋势' flag={FLAG_STORAGE.flag_trending} {...this.props}/></ScrollableTabView>return <View style={styles.container}><NavigationBartitle={'收藏'}leftButton={<View/>}rightButton={ViewUtils.getMoreButton(() => this.refs.moreMenu.open())}statusBar={statusBar}style={this.state.theme.styles.navBar}/>{content}{this.renderMoreView()}{this.renderCustomThemeView()}</View>}
}class FavoriteTab extends Component {constructor(props) {super(props);this.unFavoriteItems = [];this.favoriteDao = new FavoriteDao(this.props.flag);this.state = {result: '',isLoading: false,dataSource: new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2}),favoriteKeys: [],theme: this.props.theme,}}componentDidMount(): void {this.onLoad(true)}componentWillReceiveProps(nextProps: Readonly<P>, nextContext: any): void {this.onLoad(false)}updateState(dic) {if (!this) return;this.setState(dic);}getDataSource(data) {return this.state.dataSource.cloneWithRows(data);}onLoad(isShowLoading) {if (isShowLoading) {this.updateState({isLoading: true});}this.favoriteDao.getAllItems().then(items => {let resultData = [];for (let i = 0, len = items.length; i < len; i++) {resultData.push(new ProjectModel(items[i], true));}this.updateState({isLoading: false,dataSource: this.getDataSource(resultData)})}).catch(e => {this.updateState({isLoading: false})})}choose(projectModel) {let CellComponent = this.props.flag === FLAG_STORAGE.flag_popular ? RepositoryCell : TrendingCell;return <CellComponentonSelect={() => ActionUtils.onSelectRepository({flag: FLAG_STORAGE.flag_popular,...this.props,projectModel: projectModel,})}theme={this.props.theme}key={this.props.flag === FLAG_STORAGE.flag_popular ? projectModel.item.id : projectModel.item.fullName}onFavorite={(item, isFavorite) => ActionUtils.onFavorite(this.favoriteDao, item, isFavorite, this.props.flag)}projectModel={projectModel}/>}render() {return <View style={styles.container}><ListViewdataSource={this.state.dataSource}renderRow={(data) => this.choose(data)}enableEmptySections={true}refreshControl={<RefreshControlrefreshing={this.state.isLoading}onRefresh={() => this.onLoad()}color={this.state.theme.themeColor}tintColor={this.state.theme.themeColor}title={'Loading...'}titleColor={this.state.theme.themeColor}/>}/></View>}}const styles = StyleSheet.create({container: {flex: 1,backgroundColor: '#F5FCFF',},page1: {flex: 1,backgroundColor: 'red'},page2: {flex: 2,backgroundColor: 'green'},image: {width: 22,height: 22},item: {backgroundColor: '#169',height: 100,margin: 15,alignItems: 'center',justifyContent: 'center',},text_my: {color: 'black',fontSize: 20,},text: {color: 'white',fontSize: 20,},indicatorContainer: {alignItems: 'center'},indicator: {color: 'red',margin: 10}
});

//js/pages/My/MyPage.js
import React, {Component} from 'react';
import {StyleSheet,Text,View,ScrollView,TouchableHighlight,Image,
} from 'react-native';
import NavigationBar from "../../common/NavigationBar";
import GlobalStyles from "../../../res/styles/GlobalStyles"
import ViewUtils from "../../util/ViewUtils";
import CustomKeyPage from "./CustomKeyPage";
import {FLAG_LANGUAGE} from "../../expand/dao/LanguageDao";
import SortKeyPage from "./SortKeyPage";
import AboutMePage from "./about/AboutMePage";
import AboutPage from "./about/AboutPage";
import {MORE_MENU} from "../../common/MoreMenu";
import CustomTheme from "./CustomTheme";
import BaseComponent from "../BaseComponent";
import codePush from "react-native-code-push";export default class MyPage extends BaseComponent {constructor(props) {super(props);this.state = {customThemeViewVisible: false,theme:this.props.theme,}}onClick(tab) {let TargetComponent, params = {...this.props, menuType: tab};switch (tab) {case MORE_MENU.Custom_Language:TargetComponent = CustomKeyPage;params.flag = FLAG_LANGUAGE.flag_language;break;case MORE_MENU.Custom_Key:TargetComponent = CustomKeyPage;params.flag = FLAG_LANGUAGE.flag_key;break;case MORE_MENU.Remove_Key:TargetComponent = CustomKeyPage;params.flag = FLAG_LANGUAGE.flag_key;params.isRemoveKey = true;break;case MORE_MENU.Sort_Language:TargetComponent = SortKeyPage;params.flag = FLAG_LANGUAGE.flag_language;break;case MORE_MENU.Sort_Key:TargetComponent = SortKeyPage;params.flag = FLAG_LANGUAGE.flag_key;break;case MORE_MENU.Custom_Theme:this.setState({customThemeViewVisible: true});break;case MORE_MENU.About_Author:TargetComponent = AboutMePage;break;case MORE_MENU.About:TargetComponent = AboutPage;break;case '更新':// this.update();break;}if (TargetComponent) {this.props.navigator.push({component: TargetComponent,params: params,});}}getItem(tag, icon, text) {return ViewUtils.getSettingItem(() => this.onClick(tag), icon, text, this.state.theme.styles.tabBarSelectedIcon, null);}renderCustomThemeView() {return (<CustomTheme visible={this.state.customThemeViewVisible}{...this.props}onClose={() => {this.setState({customThemeViewVisible: false,})}}/>)}render() {let statusBar = {backgroundColor:this.state.theme.themeColor};let navigatorBar = <NavigationBar title={'我的'}statusBar={statusBar}style={this.state.theme.styles.navBar}/>;return <View style={GlobalStyles.root_container}>{navigatorBar}<ScrollView>{/*最热管理*/}<TouchableHighlight onPress={() => this.onClick(MORE_MENU.About)}><View style={[styles.item, {height: 90}]}><View style={{flexDirection: 'row', alignItems: 'center'}}><Image source={require('../../../res/images/ic_trending.png')}style={[{width: 40, height: 40, marginRight: 10}, this.state.theme.styles.tabBarSelectedIcon]}/><Text>Github Popular</Text></View><Image style={[{marginRight: 10, height: 22, width: 22,}, this.state.theme.styles.tabBarSelectedIcon]}source={require('../../../res/images/ic_tiaozhuan.png')}/></View></TouchableHighlight><View style={GlobalStyles.line}/>{/*趋势管理*/}<Text style={styles.groupTitle}>趋势管理</Text><View style={GlobalStyles.line}/>{/*自定义语言*/}{this.getItem(MORE_MENU.Custom_Language, require('./img/ic_custom_language.png'), '自定义语言')}<View style={GlobalStyles.line}/>{/*语言排序*/}{this.getItem(MORE_MENU.Sort_Language, require('./img/ic_sort.png'), '语言排序')}<View style={GlobalStyles.line}/>{/*标签管理*/}<Text style={styles.groupTitle}>标签管理</Text><View style={GlobalStyles.line}/>{/*自定义标签*/}{this.getItem(MORE_MENU.Custom_Key, require('./img/ic_custom_language.png'), '自定义标签')}<View style={GlobalStyles.line}/>{/*标签排序*/}{this.getItem(MORE_MENU.Sort_Key, require('./img/ic_swap_vert.png'), '标签排序')}<View style={GlobalStyles.line}/>{/*标签移除*/}{this.getItem(MORE_MENU.Remove_Key, require('./img/ic_remove.png'), '标签移除')}<View style={GlobalStyles.line}/>{/*设置*/}<Text style={styles.groupTitle}>设置</Text><View style={GlobalStyles.line}/>{this.getItem(MORE_MENU.Custom_Theme, require('./img/ic_custom_theme.png'), '自定义主题')}<View style={GlobalStyles.line}/>{this.getItem(MORE_MENU.About_Author, require('./img/ic_insert_emoticon.png'), '关于作者')}<View style={GlobalStyles.line}/></ScrollView>{this.renderCustomThemeView()}</View>}
}const styles = StyleSheet.create({container: {flex: 1,backgroundColor: '#F5FCFF',},item: {flexDirection: 'row',justifyContent: 'space-between',alignItems: 'center',padding: 10,height: 60,backgroundColor: 'white',},groupTitle: {marginLeft: 10,marginTop: 10,marginBottom: 5,fontSize: 12,color: 'gray',}
});
//js/pages/My/CustomTheme.js
import React, {Component} from 'react';
import {StyleSheet,Text,View,ScrollView,TouchableHighlight,Image,Platform,DeviceEventEmitter,Modal,
} from 'react-native';import GlobalStyles from "../../../res/styles/GlobalStyles"
import ThemeFactory,{ThemeFlags} from "../../../res/styles/ThemeFactory"
import ThemeDao from "../../expand/dao/ThemeDao";
import {ACTION_HOME} from "../HomePage";export default class CustomTheme extends Component {constructor(props) {super(props);this.themeDao = new ThemeDao();}onSelectTheme(themeKey){this.props.onClose();this.themeDao.save(ThemeFlags[themeKey]);DeviceEventEmitter.emit('ACTION_BASE',ACTION_HOME.A_THEME,ThemeFactory.createTheme(ThemeFlags[themeKey]))}getThemeItem(themeKey){return <TouchableHighlight underlayColor={'white'} onPress={()=>this.onSelectTheme(themeKey)} style={{flex: 1}}><View style={[{backgroundColor: ThemeFlags[themeKey]},styles.themeItem]}><Text style={styles.themeText}>{themeKey}</Text></View></TouchableHighlight>}/*** 创建主题列表* @returns {Array}*/renderThemeItems(){const views = [];for (let i=0,keys=Object.keys(ThemeFlags),l=keys.length;i<l;i+=3){const key1 = keys[i], key2 = keys[i + 1], key3 = keys[i + 2];views.push(<View keys={i} style={{flexDirection: 'row'}}>{this.getThemeItem(key1)}{this.getThemeItem(key2)}{this.getThemeItem(key3)}</View>)}return views;}renderContentView(){return <Modal animationType={"slide"}transparent={true}visible={this.props.visible}onRequestClose={() => {this.props.onClose()}}><View style={styles.modalContainer}><ScrollView>{this.renderThemeItems()}</ScrollView></View></Modal>}render() {let view = this.props.visible?<View style={GlobalStyles.root_container}>{this.renderContentView()}</View>:null;return view;}
}const styles = StyleSheet.create({container: {flex: 1,backgroundColor: '#F5FCFF',},modalContainer:{flex:1,margin: 10,marginTop: Platform.OS==='ios'?20:10,backgroundColor:'white',borderRadius: 3,shadowColor: 'gray',shadowOffset: {width: 2,height: 2},shadowOpacity: 0.5,shadowRadius: 2,padding: 3},themeItem:{flex:1,height: 120,margin: 3,padding:3,borderRadius:2,alignItems: 'center',justifyContent: 'center',flexDirection: 'row',},themeText:{color:'white',fontWeight: '500',fontSize:16,}});

by最后,如果你看代码看的想睡觉,那么它是提醒你,换一个项目看看~
没有看代码看睡着的人,只有不够有吸引力的代码

转载于:https://www.cnblogs.com/smart-girl/p/10900386.html

【水滴石穿】imooc_gp相关推荐

  1. 做人晶莹剔透,做事水滴石穿

    看了余世维的讲座,在最后的闭幕中,出现了这样的文字:做人晶莹剔透,做事水滴石穿.晶莹剔透意味着诚信光明,水滴石穿意味着用心坚持.让我心一惊,真是说得太对了.我要用他来鼓舞激励自己. 现在很多人都很虚伪 ...

  2. Redis 水滴石穿之(六)哨兵

    Redis-水滴石穿之(六)哨兵 目录 Redis-水滴石穿之(六)哨兵 一.概述 二.哨兵应用 2.1.主从及哨兵配置 2.2.依次启动主.从.哨兵 2.3.主从节点验证 2.4.故障迁移演示 2. ...

  3. 水滴石穿、坚持不懈,必能有所精进

    在跟随这门课程学习的过程中,我增长了很多大数据相关的知识,对于大数据技术和相关开源组件,也有了更深的了解.今天正好可以借着这个机会,来记录下自己的一点心得体会,也跟你分享一下我的学习思路,咱们一起聊一 ...

  4. 2.4 找准位置,水滴石穿

            考试时的方法多数不是"灵机一动"现场创造出来的,而是平时刻苦训练中积累出来的. 俗话说得好,"水滴石穿",但"水滴未必石穿" ...

  5. Redis 水滴石穿之(四)持久化

    Redis 水滴石穿之(四)持久化 目录 Redis 水滴石穿之(四)持久化 一.概述 二.RDB 1.RDB快照触发时机 1.1 手动触发 (save & bgsave) 1.2 自动触发 ...

  6. 不会-Redis 水滴石穿之(七)集群

    Redis 水滴石穿之(七)集群 目录 Redis 水滴石穿之(七)集群 一.概述 二.集群搭建 2.1.手动搭建集群 1.修改配置文件 2.启动节点 3.节点握手 4.分配槽 5.指定主从关系 2. ...

  7. 期货开户水滴石穿知行合一

    上千年来,人生价值一直都在改变,唯一没有改变的就是价值本身的规律.如果从另一个角度去观察,或许会有另外一番心境,有句老话叫做后生可畏,也许后生并不可畏,真正让人可畏可敬的或许是代表一个时代的思想和精神 ...

  8. 2022-1-14持之以恒,水滴石穿

    1.读到曾文正公修身之难皆因无恒,刚过30的我深有体会,回想往事从幼时读书学习开始总是3分钟热度,学习总浮于表面,老师布置的作业草草了事,出社会参加工作后书倒是买了一大堆,每本书总是翻完几页又想去读其 ...

  9. 水滴石穿oracle之脚本安装

    水滴石穿oracle之脚本安装 上一篇文章带领大家在redhat5.5上一步一步安装了oracle10g,并且详细讲解了每一步操作,图文并茂相信可以帮到一些有需要朋友! 成功动手搭建过一次的朋友们有没 ...

最新文章

  1. 进击的Waymo,掘进无人驾驶深水区
  2. axios post body参数_Vue开发中的一些问题(axios封装)
  3. 如何解决tmux中Anaconda虚拟环境下的python版本不正确的问题
  4. 支持服务器CPU的ITX主板,Mini-ITX主板能装28核处理器,华擎推出EPC621D4I-2M主板
  5. 2021-04-17 深入理解SLAM技术 【3】 数学基础概述
  6. ITK:将图像从一种类型投射到另一种类型,但限制在输出值范围内
  7. Android 编译系统分析(三)
  8. leetcode115 不同的子序列
  9. Toad9.7与Oracle11g在X86的Win7下的情况
  10. 提出建议Do you want to..._44
  11. jQuery 异步上传插件 Uploadify 使用 (Java平台)
  12. anaconda-ks.cfg详解
  13. Oracle 基础笔记4
  14. SM3算法的编程实现
  15. 属于计算机网络资源子网的,属于计算机网络的资源子网.pdf
  16. webview的一些使用小窍门和需注意的地方
  17. VMware vCenter Server 7.0安装配置
  18. Unity制作出《超级马里奥》的2D和3D混合效果
  19. php mysql die_【PHP】当mysql遇上PHP
  20. MySQL约束条件和多表查询方式详解

热门文章

  1. 自定义标签报 无法为TAG [my2:hello]加载标记处理程序类[null]
  2. Linux日志 系统日志及分析
  3. JAVA国际化输出日期格式
  4. array DEMO
  5. Android 动态类加载实现免安装更新
  6. CentOS6.4卸载自带的OpenJDK并安装jdk1.6.21
  7. SQL Server索引进阶第六篇:书签
  8. onvif 客户端的发现
  9. tslib 编译移植步骤
  10. 嵌入式linux ext4映像制作工具说明 real210_v62