【水滴石穿】douban-movies-react-native
这个项目的话,倒是可以做一个支架页面,就是你需要什么东西,你就可以在里面加,不过也是比较难的地方
就是数据流,数据处理的部分。react可以处理数据的方式很多,没有见过类似于古老的vue时候可以使用的
$.http(),我觉得实现功能是第一步,至于技术的高低,哎,捂脸
【博客后文把前面说的都否认了,talk is cheap,show me the code 】
项目地址为:https://github.com/XinmengSiRan/douban-movies-react-native
先看页面
//index.js
/** @format */
import {AppRegistry} from 'react-native';
import App from './App';
import {name as appName} from './app.json';
AppRegistry.registerComponent(appName, () => App);
//App.js
//定义了根App.js
/**
* Sample React Native App
* https://github.com/facebook/react-native
*
* @format
* @flow
*/
import React, {Component} from 'react';
import {StyleSheet, Text, View} from 'react-native';
import AppContainer from './src';
type Props = {
navigation: any
};
export default class App extends Component <Props>{
render() {
return (
<AppContainer />
);
}
}
//src/index.js
//定义底部和切换页面
import React, { Component } from 'react';
import { Dimensions, AppRegistry, StyleSheet, Text, View, ButtonTouchableOpacity, Image, ScrollView, FlatList, ActivityIndicator} from 'react-native';
import { createAppContainer, createStackNavigator, createBottomTabNavigator } from 'react-navigation';
import { createStore} from 'redux';
import ScrollableTabView, { DefaultTabBar, ScrollableTabBar } from 'react-native-scrollable-tab-view';
import PlayList from './components/PlayList';
import Search from './components/Search';
import My from './components/My';
import Icon from 'react-native-vector-icons/Ionicons';
/*为了注释调试提醒*/
console.ignoredYellowBox = ['Remote debugger'];
const BottomTabNavigator = createBottomTabNavigator({
热映: {
//通过createStackNavigator中的值来切换页面
screen: createStackNavigator({PlayList}),
navigationOptions: {
tabBarLabel: '热映',
tabBarIcon: ({tintColor}) => (
<Icon name="ios-tv" size={20} color={tintColor} />
)
}
},
找片: {
screen: createStackNavigator({Search}),
navigationOptions: {
tabBarLabel: '找片',
tabBarIcon: ({tintColor}) => (
<Icon name="ios-eye" size={20} color={tintColor} />
)
}
},
我的: {
screen: createStackNavigator({My}),
navigationOptions: {
tabBarLabel: '我的',
tabBarIcon: ({tintColor}) => (
<Icon name="ios-person" size={20} color={tintColor} />
)
}
}
}, {
tabBarPosition: 'bottom',
tabBarOptions: {
activeTintColor: '#494949',
inactiveTintColor: '#999999',
labelStyle: {
fontSize: 12,
marginBottom: 5
},
style: {
borderTopWidth: 1,
borderTopColor: '#eeeeee',
height: 50,
backgroundColor: '#ffffff'
}
}
});
//切换的底部页面
const AppContainer = createAppContainer(BottomTabNavigator);
export default AppContainer;
//其实我比较好奇这种写法,一下子组件都引进来了,会不会首页太大很卡的问题
//src/components/PlayList.js
import React, { Component } from 'react';
import { StyleSheet, Dimensions, Text, View, Button, FlatList } from 'react-native';
import ScrollableTabView, { DefaultTabBar } from 'react-native-scrollable-tab-view';
import { createAppContainer, createStackNavigator} from 'react-navigation';
import HotList from './HotList';
import SoonList from './SoonList';
export default class PlayList extends Component {
//这里定义的头部
static navigationOptions = {
title: 'Home'
};
render() {
return (
<View style={styles.container}>
<ScrollableTabView
renderTabBar={() => <DefaultTabBar/> }
tabBarUnderlineStyle={{
backgroundColor: '#000',
height: 2
}}
tabBarBackgroundColor='#fff'
tabBarActiveTextColor='#000'
tabBarInactiveTextColor='#959595'
tabBarTextStyle={{ fontSize: 16 }}
locked={false}
>
<View tabLabel='正在热映' style={{marginBottom:50}}>
<HotList navigation={this.props.navigation}></HotList>
</View>
<View tabLabel='即将上映' style={{marginBottom:50}}>
<SoonList navigation={this.props.navigation}></SoonList>
</View>
</ScrollableTabView>
</View>
);
}
}
//在页面里面判断的是不是iphonex做不做别的适配
const { width, height } = Dimensions.get('window');
const IS_IPHONE_X_SERIES = () => {
if (height == 812 || height == 896) {
return true;
}else{
return false;
}
}
const styles = StyleSheet.create({
container: {
width: width,
height: IS_IPHONE_X_SERIES ? (height - 88 - 34) : (height - 64),
paddingTop: 10,
backgroundColor: '#fff'
}
});
//里面有两个组件,代表的两个页面
我一开始以为页面真的就是架子,可是分析代码发现里面是有数据请求的
很惊讶阿,这种bug我不会调,先放代码
```js
//src/components/HotList.js
import React, { Component } from 'react';
import {
ActivityIndicator,
StyleSheet,
Dimensions,
Image,
Text,
TouchableOpacity,
TouchableWithoutFeedback,
View,
Button,
FlatList
} from 'react-native';
import Star from './Star';
export default class HotList extends Component {
constructor(props) {
super(props);
this.state = {
ready: true,
refreshing: false,
data: []
}
}
componentDidMount() {
this._fetchData();
}
handleOnPress = () => {
}
_fetchData = () => {
fetch('https://api.douban.com/v2/movie/in_theaters')
.then((response) => {
this.setState({refreshing: false});
return response.json();
}).then((responseJson) => {
console.log('response', responseJson);
const dataArr = responseJson.subjects;
this.setState({
ready: false,
refreshing: false,
data: dataArr
});
}).catch((error) => {
console.error(error);
});
}
_refreshData = () => {
this.setState({refreshing: true});
this._fetchData();
}
render() {
const {navigate} = this.props.navigation;
const {data} = this.state;
return (
<View style={styles.container}>
{
this.state.ready
? <ActivityIndicator size='large' style={styles.loadding}/>
: <FlatList
data={data}
onRefresh={this._refreshData}
refreshing={this.state.refreshing}
keyExtractor={(item, index ) => index+item}
renderItem={({item}) => {
return (
<TouchableOpacity
style={styles.item}
onPress={this.handleOnPress}>
<View style={{flex: 1,}}>
<Image
source={{uri: item.images.large}}
style={styles.image} />
</View>
<View style={{flex: 2, alignItems: 'flex-start', paddingLeft: 5}}>
<Text style={styles.title}>{item.title}</Text>
<View style={styles.star}>
<Star value={item.rating}></Star>
</View>
<Text style={styles.smallFont}>导演:{item.directors[0].name}</Text>
<Text style={styles.smallFont}>主演:{item.casts.map((v) => v.name).join('/')}</Text>
</View>
<View style={{alignItems: 'flex-end'}}>
<Text style={[styles.smallFont, styles.redFont]}>{
(item.collect_count / 10000.0 > 1)
? (item.collect_count / 10000.0).toFixed(1) + '万人看过'
: item.collect_count + '人看过'
}
</Text>
<TouchableOpacity
style={styles.buyTicket}>
<Text style={styles.redFont}>购票</Text>
</TouchableOpacity>
</View>
</TouchableOpacity>
);
}} />
}
</View>
);
}
}
const styles = StyleSheet.create({
loadding: {
marginTop: 30
},
item: {
height: 140,
paddingLeft: 18,
paddingRight: 18,
paddingTop: 10,
paddingBottom: 10,
flexDirection: 'row',
alignItems: 'center',
borderBottomWidth: 1,
borderBottomColor: '#eeeeee',
},
image: {
width: 80,
height: 120,
},
title: {
fontSize: 16,
fontWeight: 'bold'
},
smallFont: {
fontSize: 12,
lineHeight: 20,
color: '#A6A6A6'
},
buyTicket: {
width: 60,
height: 30,
marginTop: 5,
borderRadius: 5,
borderWidth: 1,
borderColor:'#FF4E65',
justifyContent: 'center',
alignItems: 'center'
},
redFont: {
color: '#FF4E65',
},
star: {
marginTop: 10,
marginBottom: 10
}
});
//src/components/SoonList.js
import React, { Component } from 'react';
import {
ActivityIndicator,
StyleSheet,
Image,
Text,
TouchableOpacity,
View,
FlatList,
} from 'react-native';
import Star from './Star';
export default class SoonList extends Component {
constructor(props) {
super(props);
this.state = {
ready: true,
refreshing: false,
data: []
}
}
componentDidMount() {
this._fetchData();
}
handleOnPress = () => {
}
_fetchData = () => {
fetch('https://api.douban.com/v2/movie/coming_soon')
.then((response => {
this.setState({refreshing: false});
return response.json();
})).then((responseJson) => {
console.log(responseJson);
const dataArr = responseJson.subjects;
this.setState({
ready: false,
refreshing: false,
data: dataArr
});
}).catch((eror) => {
console.error(error);
});
}
_refreshData = () => {
this.setState({refreshing: true});
this._fetchData();
}
renderMovieItem = (item) => {
return (
<TouchableOpacity
style={styles.item}
onPress={this.handleOnPress}>
<View style={{flex: 1,}}>
<Image
source={{uri: item.images.large}}
style={styles.image} />
</View>
<View style={{flex: 2, alignItems: 'flex-start', paddingLeft: 5}}>
<Text style={styles.title}>{item.title}</Text>
<View style={styles.star}>
<Star value={item.rating}></Star>
</View>
<Text style={styles.smallFont}>导演:{item.directors[0].name}</Text>
<Text style={styles.smallFont}>主演:{item.casts.map((v) => v.name).join('/')}</Text>
</View>
<View style={{alignItems: 'flex-end'}}>
<Text style={[styles.smallFont, styles.yellowFont]}>{
(item.collect_count / 10000.0 > 1)
? (item.collect_count / 10000.0).toFixed(1) + '万人想看'
: item.collect_count + '人想看'
}
</Text>
<TouchableOpacity
style={styles.buyTicket}>
<Text style={styles.yellowFont}>想看</Text>
</TouchableOpacity>
</View>
</TouchableOpacity>
);
}
render() {
const {data} = this.state;
const {navigate} = this.props.navigation;
return (
<View>
{
this.state.ready
? <ActivityIndicator size='large' style={styles.loadding} />
: <FlatList
data={data}
onRefresh={this._refreshData}
refreshing={this.state.refreshing}
keyExtractor={(item, index) => index + item}
renderItem={({item}) => this.renderMovieItem(item)} />
}
</View>
);
}
}
const styles = StyleSheet.create({
loadding: {
marginTop: 30
},
item: {
height: 140,
paddingLeft: 18,
paddingRight: 18,
paddingTop: 10,
paddingBottom: 10,
flexDirection: 'row',
alignItems: 'center',
borderBottomWidth: 1,
borderBottomColor: '#eeeeee',
},
image: {
width: 80,
height: 120,
},
title: {
fontSize: 16,
fontWeight: 'bold'
},
smallFont: {
fontSize: 12,
lineHeight: 20,
color: '#A6A6A6'
},
buyTicket: {
width: 60,
height: 30,
marginTop: 5,
borderRadius: 5,
borderWidth: 1,
borderColor:'#EFA300',
justifyContent: 'center',
alignItems: 'center'
},
yellowFont: {
color: '#EFA300'
},
star: {
marginTop: 10,
marginBottom: 10
}
});
//src/components/Search.js
import React, { Component } from 'react';
import { Dimensions, Text, View, Button, FlatList } from 'react-native';
import ScrollableTabView, { DefaultTabBar } from 'react-native-scrollable-tab-view';
import { createAppContainer, createStackNavigator} from 'react-navigation';
const { width, height } = Dimensions.get('window');
export default class Search extends Component {
static navigationOptions = {
title: 'Search',
};
render() {
const { navigate } = this.props.navigation;
return (
<View>
<Text>找片</Text>
</View>
);
}
}
//src/components/My.js
import React, { Component } from 'react';
import { Dimensions, Text, View, Button, FlatList } from 'react-native';
import ScrollableTabView, { DefaultTabBar } from 'react-native-scrollable-tab-view';
import { createAppContainer, createStackNavigator} from 'react-navigation';
const { width, height } = Dimensions.get('window');
export default class My extends Component {
static navigationOptions = {
title: 'My'
};
render() {
const { navigate } = this.props.navigation;
return (
<View>
<Text>我的</Text>
</View>
);
}
}
时时当勉励,岁月不待人,加油~~~加油~~~
-------------------------------------------
个性签名:一个人在年轻的时候浪费自己的才华与天赋是一件非常可惜的事情
如果觉得这篇文章对你有小小的帮助的话,记得在右下角点个“推荐”哦,博主在此感谢!
万水千山总是情,打赏5毛买辣条行不行,所以如果你心情还比较高兴,也是可以扫码打赏博主,哈哈哈(っ•̀ω•́)っ✎⁾⁾!
微信
支付宝