Authored by 于良

增加section view review by 阿瑟

... ... @@ -5,7 +5,7 @@ import ReactNative from 'react-native';
import ImmutablePropTypes from 'react-immutable-proptypes';
import Banner from './Banner';
import Notice from './Notice';
import Section from './Section';
import YH_SectionView from './YH_SectionView';
import ListCell from './ListCell';
const {
... ... @@ -22,6 +22,7 @@ const {
let {width, height} = Dimensions.get('window');
let bannerHeight = Math.ceil((363 / 750) * width);
let sectionHeight = Math.ceil((435 / 750) * width);
export default class Home extends React.Component {
... ... @@ -45,8 +46,24 @@ export default class Home extends React.Component {
section: ImmutablePropTypes.listOf(
ImmutablePropTypes.listOf(
ImmutablePropTypes.contains({
image: React.PropTypes.string.isRequired,
url: React.PropTypes.string,
header: ImmutablePropTypes.contains({
logo: React.PropTypes.string.isRequired,
title: React.PropTypes.string.isRequired,
postNum: React.PropTypes.string.isRequired,
commentNum: React.PropTypes.string.isRequired,
laudCount: React.PropTypes.string.isRequired,
}),
hot: ImmutablePropTypes.contains({
avatar: React.PropTypes.string.isRequired,
content: React.PropTypes.string.isRequired,
}),
new: ImmutablePropTypes.contains({
avatar: React.PropTypes.string.isRequired,
content: React.PropTypes.string.isRequired,
}),
num: ImmutablePropTypes.contains({
onedayAddNum: React.PropTypes.string.isRequired,
}),
})
),
),
... ... @@ -115,17 +132,15 @@ export default class Home extends React.Component {
);
case 'section':
return (
<Section
data={rowData}
width={width}
height={210}
onPress={(url) => {
this.props._onPressSection && this.props._onPressSection(url);
<YH_SectionView
style={styles.carouselSection}
items={rowData}
onClick={(index) => {
this.props.onPressSection && this.props.onPressSection(index);
}}
/>
);
case 'recommendation':
console.log(rowData);
return (
<ListCell
key={sectionID + rowID}
... ... @@ -175,9 +190,9 @@ export default class Home extends React.Component {
render() {
let dataSource = {
banner: this.props.banner.toObject(),
notice: this.props.notice.toObject(),
section: this.props.section.toObject(),
banner: this.props.banner.toArray(),
notice: this.props.notice.toArray(),
section: this.props.section.toArray(),
recommendation: this.props.recommendation.toArray(),
}
return (
... ... @@ -205,6 +220,10 @@ let styles = StyleSheet.create({
container: {
flex: 1,
},
carouselSection: {
width,
height: sectionHeight,
},
sectionHeader: {
flexDirection: 'row',
height: 32,
... ...
'use strict';
import React from 'react';
import ReactNative from 'react-native';
import ImmutablePropTypes from 'react-immutable-proptypes';
const {
View,
Image,
TouchableOpacity,
ListView,
ScrollView,
StyleSheet,
Dimensions,
Animated,
Text,
} = ReactNative;
export default class Section extends React.Component {
static propTypes = {
data: ImmutablePropTypes.listOf(
ImmutablePropTypes.contains({
image: React.PropTypes.string.isRequired,
url: React.PropTypes.string.isRequired,
})
),
width: React.PropTypes.number.isRequired,
height: React.PropTypes.number.isRequired,
onPress: React.PropTypes.func,
};
constructor(props) {
super (props);
this.animatedValue = new Animated.Value(Dimensions.get('window').width / 2);
this._renderRow = this._renderRow.bind(this);
this.state = {
offsetX: 0,
offsetXCenter: 0 + Dimensions.get('window').width / 2,
offsetXCenterAnim: new Animated.Value(Dimensions.get('window').width / 2),
};
}
_renderRow(item, i) {
return (
<TouchableOpacity
style={styles.page}
key={i}
>
<Animated.Image source={{uri: item.get('image')}} style={[styles.image]}/>
</TouchableOpacity>
);
}
render() {
let width = this.props.width;
let height = this.props.height;
let data = this.props.data.toArray();
return (
<View style={styles.container}>
<ScrollView
contentContainerStyle={styles.contentContainer}
horizontal={true}
pagingEnabled={false}
scrollEventThrottle={100}
bounces={false}
onScroll={(event) => {
// console.log(event.nativeEvent);
// this.offsetX = event.nativeEvent.contentOffset.x;
this.setState({
offsetX: event.nativeEvent.contentOffset.x,
offsetXCenter: event.nativeEvent.contentOffset.x + Dimensions.get('window').width / 2,
});
}}
onTouchEnd={(event) => {
// console.log('offsetY:', this.offsetY);
// console.log('touch info:', event.nativeEvent);
}}
>
{data.map((item, i) => {
let pageSize = 180;
let pageCenter = pageSize / 2 + i * pageSize;
let offsetXCenter = this.state.offsetXCenter;
// console.log(offsetXCenter);
// let distance = Math.abs(pageCenter - offsetXCenter);
let distance = offsetXCenter - pageCenter;
// i == 1 && console.log(distance);
distance = Math.abs(distance);
distance = distance > 180 ? 180 : distance;
// i == 1 && console.log(distance);
// distance = Math.round(distance * 100) / 100;
let scale = this.animatedValue.interpolate({
inputRange: [-200, -distance, -distance/2, 0, distance/2, distance, 200],
// inputRange: [-distance*2, -distance, -distance/2, 0, distance/2, distance, distance*2],
outputRange: [1, 0.65, 0.65, 0.85, 0.65, 0.65, 1],
});
// console.log(scale);
return (
<TouchableOpacity
style={styles.page}
key={i}
>
<Animated.Image source={{uri: item.get('image')}} style={[styles.image, {transform: [{ scale }]}]}/>
</TouchableOpacity>
);
})}
</ScrollView>
</View>
);
}
}
let styles = StyleSheet.create({
container: {
// flexDirection: 'row',
// height: 360,
// backgroundColor: 'green'
},
contentContainer: {
flexDirection: 'row',
// width: 220,
backgroundColor: 'gray'
},
page: {
width: 180,
// justifyContent: 'center',
paddingHorizontal: 15,
backgroundColor: 'gray',
},
image: {
width: 160,
height: 150,
// marginHorizontal: 15,
},
});
import React from 'react';
import ReactNative from 'react-native';
import ImmutablePropTypes from 'react-immutable-proptypes';
let {
requireNativeComponent
} = ReactNative;
// requireNativeComponent automatically resolves this to "YH_SectionViewManager"
module.exports = requireNativeComponent('YH_SectionView', null);
class SectionView extends React.Component {
constructor(props) {
super(props);
this._onClick = this._onClick.bind(this);
}
_onClick(event: Event) {
console.log(event.nativeEvent);
if (!this.props.onClick) {
return;
}
this.props.onClick(event.nativeEvent);
}
render() {
return <YH_SectionView {...this.props} onClick={this._onClick} />;
}
}
SectionView.propTypes = {
items: ImmutablePropTypes.listOf(
ImmutablePropTypes.contains({
header: ImmutablePropTypes.contains({
logo: React.PropTypes.string.isRequired,
title: React.PropTypes.string.isRequired,
postNum: React.PropTypes.string.isRequired,
commentNum: React.PropTypes.string.isRequired,
laudCount: React.PropTypes.string.isRequired,
}),
hot: ImmutablePropTypes.contains({
avatar: React.PropTypes.string.isRequired,
content: React.PropTypes.string.isRequired,
}),
new: ImmutablePropTypes.contains({
avatar: React.PropTypes.string.isRequired,
content: React.PropTypes.string.isRequired,
}),
num: ImmutablePropTypes.contains({
onedayAddNum: React.PropTypes.string.isRequired,
}),
})
),
onClick: React.PropTypes.func,
};
let YH_SectionView = requireNativeComponent('YH_SectionView', SectionView);
module.exports = SectionView;
... ...
... ... @@ -2,9 +2,9 @@ import keyMirror from 'key-mirror';
export default keyMirror({
HOME_BANNER_REQUEST: null,
HOME_BANNER_SUCCESS: null,
HOME_BANNER_FAILURE: null,
HOME_BANNER_AND_SECTION_REQUEST: null,
HOME_BANNER_AND_SECTION_SUCCESS: null,
HOME_BANNER_AND_SECTION_FAILURE: null,
HOME_NOTICE_REQUEST: null,
HOME_NOTICE_SUCCESS: null,
... ...
... ... @@ -178,30 +178,85 @@ class HomeContainer extends React.Component {
let section = [
[
{
image: 'https://img10.static.yhbimg.com/yhb-img01/2016/06/28/17/0180ef2077db7ec5117756e47c0b61a7b1.jpg?imageView2/2/w/640/h/240',
url: 'https://www.baidu.com'
header: {
logo: 'https://img10.static.yhbimg.com/yhb-img01/2016/06/28/12/01dcc29b14bdd04d9051c2e5ce40fe6516.jpg?imageView2/2/w/640/h/240',
title: '永恒的潮流1111',
postNum: '1222',
commentNum: '3444',
laudCount: '6765',
},
{
image: 'https://img11.static.yhbimg.com/yhb-img01/2016/06/28/11/01f429fffdff555ed0c141a5ec2b4fd421.jpg?imageView2/2/w/640/h/240',
url: 'https://www.baidu.com'
hot: {
avatar: 'https://img11.static.yhbimg.com/yhb-img01/2016/06/28/11/01f429fffdff555ed0c141a5ec2b4fd421.jpg?imageView2/2/w/640/h/240',
content: '学院风的格子衫可能是每个男生衣橱里都会有的单件衣服学院风的格子衫可能是每个男生衣橱里都会有的单件衣服',
},
{
image: 'https://img10.static.yhbimg.com/yhb-img01/2016/06/28/12/01dcc29b14bdd04d9051c2e5ce40fe6516.jpg?imageView2/2/w/640/h/240',
url: 'https://www.baidu.com'
new: {
avatar: 'https://img11.static.yhbimg.com/yhb-img01/2016/06/28/11/01f429fffdff555ed0c141a5ec2b4fd421.jpg?imageView2/2/w/640/h/240',
content: '学院风的格子衫可能是每个男生衣橱里都会有的单件衣服学院风的格子衫可能是每个男生衣橱里都会有的单件衣服',
},
num: {
onedayAddNum: '233334',
}
},
{
image: 'https://img10.static.yhbimg.com/yhb-img01/2016/06/28/17/0180ef2077db7ec5117756e47c0b61a7b1.jpg?imageView2/2/w/640/h/240',
url: 'https://www.baidu.com'
header: {
logo: 'https://img10.static.yhbimg.com/yhb-img01/2016/06/28/12/01dcc29b14bdd04d9051c2e5ce40fe6516.jpg?imageView2/2/w/640/h/240',
title: '永恒的潮流2222',
postNum: '2222',
commentNum: '222',
laudCount: '2222',
},
hot: {
avatar: 'https://img11.static.yhbimg.com/yhb-img01/2016/06/28/11/01f429fffdff555ed0c141a5ec2b4fd421.jpg?imageView2/2/w/640/h/240',
content: '学院风的格子衫可能是每个男生衣橱里都会有的单件衣服学院风的格子衫可能是每个男生衣橱里都会有的单件衣服',
},
new: {
avatar: 'https://img11.static.yhbimg.com/yhb-img01/2016/06/28/11/01f429fffdff555ed0c141a5ec2b4fd421.jpg?imageView2/2/w/640/h/240',
content: '学院风的格子衫可能是每个男生衣橱里都会有的单件衣服学院风的格子衫可能是每个男生衣橱里都会有的单件衣服',
},
num: {
onedayAddNum: '2222',
}
},
{
image: 'https://img11.static.yhbimg.com/yhb-img01/2016/06/28/11/01f429fffdff555ed0c141a5ec2b4fd421.jpg?imageView2/2/w/640/h/240',
url: 'https://www.baidu.com'
header: {
logo: 'https://img10.static.yhbimg.com/yhb-img01/2016/06/28/12/01dcc29b14bdd04d9051c2e5ce40fe6516.jpg?imageView2/2/w/640/h/240',
title: '永恒的潮流3333',
postNum: '3333',
commentNum: '3333',
laudCount: '3333',
},
hot: {
avatar: 'https://img11.static.yhbimg.com/yhb-img01/2016/06/28/11/01f429fffdff555ed0c141a5ec2b4fd421.jpg?imageView2/2/w/640/h/240',
content: '学院风的格子衫可能是每个男生衣橱里都会有的单件衣服学院风的格子衫可能是每个男生衣橱里都会有的单件衣服',
},
new: {
avatar: 'https://img11.static.yhbimg.com/yhb-img01/2016/06/28/11/01f429fffdff555ed0c141a5ec2b4fd421.jpg?imageView2/2/w/640/h/240',
content: '学院风的格子衫可能是每个男生衣橱里都会有的单件衣服学院风的格子衫可能是每个男生衣橱里都会有的单件衣服',
},
num: {
onedayAddNum: '33333',
}
},
{
image: 'https://img10.static.yhbimg.com/yhb-img01/2016/06/28/12/01dcc29b14bdd04d9051c2e5ce40fe6516.jpg?imageView2/2/w/640/h/240',
url: 'https://www.baidu.com'
header: {
logo: 'https://img10.static.yhbimg.com/yhb-img01/2016/06/28/12/01dcc29b14bdd04d9051c2e5ce40fe6516.jpg?imageView2/2/w/640/h/240',
title: '永恒的潮流4444',
postNum: '4444',
commentNum: '4444',
laudCount: '4444',
},
hot: {
avatar: 'https://img11.static.yhbimg.com/yhb-img01/2016/06/28/11/01f429fffdff555ed0c141a5ec2b4fd421.jpg?imageView2/2/w/640/h/240',
content: '学院风的格子衫可能是每个男生衣橱里都会有的单件衣服学院风的格子衫可能是每个男生衣橱里都会有的单件衣服',
},
new: {
avatar: 'https://img11.static.yhbimg.com/yhb-img01/2016/06/28/11/01f429fffdff555ed0c141a5ec2b4fd421.jpg?imageView2/2/w/640/h/240',
content: '学院风的格子衫可能是每个男生衣橱里都会有的单件衣服学院风的格子衫可能是每个男生衣橱里都会有的单件衣服',
},
num: {
onedayAddNum: '4444',
}
},
],
];
let recommendation = [
... ...
... ... @@ -11,9 +11,9 @@ import HomeService from '../../services/HomeService';
const {
HOME_BANNER_REQUEST,
HOME_BANNER_SUCCESS,
HOME_BANNER_FAILURE,
HOME_BANNER_AND_SECTION_REQUEST,
HOME_BANNER_AND_SECTION_SUCCESS,
HOME_BANNER_AND_SECTION_FAILURE,
HOME_NOTICE_REQUEST,
HOME_NOTICE_SUCCESS,
... ... @@ -29,22 +29,22 @@ const {
} = require('../../constants/actionTypes').default;
export function bannerRequest() {
export function bannerAndSectionRequest() {
return {
type: HOME_BANNER_REQUEST,
type: HOME_BANNER__AND_SECTIONREQUEST,
};
}
export function bannerSuccess(json) {
export function bannerAndSectionSuccess(json) {
return {
type: HOME_BANNER_SUCCESS,
type: HOME_BANNER_AND_SECTION_SUCCESS,
payload: json
};
}
export function bannerFailure(error) {
export function bannerAndSectionFailure(error) {
return {
type: HOME_BANNER_FAILURE,
type: HOME_BANNER_AND_SECTION_FAILURE,
payload: error
};
}
... ... @@ -68,25 +68,6 @@ export function noticeFailure(error) {
payload: error
};
}
export function sectionRequest() {
return {
type: HOME_SECTION_REQUEST,
};
}
export function sectionSuccess(json) {
return {
type: HOME_SECTION_SUCCESS,
payload: json
};
}
export function sectionFailure(error) {
return {
type: HOME_SECTION_FAILURE,
payload: error
};
}
export function recommendationRequest() {
return {
... ... @@ -108,16 +89,15 @@ export function recommendationFailure(error) {
};
}
export function banner(shopId) {
export function bannerAndSection() {
return dispatch => {
dispatch(bannerRequest());
return new HomeService().banner(shopId)
dispatch(bannerAndSectionRequest());
return new HomeService().bannerAndSection(appType)
.then(json => {
dispatch(bannerSuccess(json));
dispatch(bannerAndSectionSuccess(json));
})
.catch(error => {
dispatch(bannerFailure(error));
dispatch(bannerAndSectionFailure(error));
});
};
}
... ...
... ... @@ -17,9 +17,9 @@ import {Record, List, Map} from 'immutable';
let InitialState = Record({
isFetching: false,
error: null,
banner: new Map(),
notice: new Map(),
section: new Map(),
banner: List(),
notice: List(),
section: List(),
recommendation: List(),
});
... ...
... ... @@ -13,9 +13,9 @@ import InitialState from './homeInitialState';
const {
HOME_BANNER_REQUEST,
HOME_BANNER_SUCCESS,
HOME_BANNER_FAILURE,
HOME_BANNER_AND_SECTION_REQUEST,
HOME_BANNER_AND_SECTION_SUCCESS,
HOME_BANNER_AND_SECTION_FAILURE,
HOME_NOTICE_REQUEST,
HOME_NOTICE_SUCCESS,
... ... @@ -43,7 +43,7 @@ export default function homeReducer(state = initialState, action) {
switch (action.type) {
case HOME_BANNER_REQUEST:
case HOME_BANNER_AND_SECTION_REQUEST:
case HOME_NOTICE_REQUEST:
case HOME_SECTION_REQUEST:
case HOME_RECOMMENDATION_REQUEST: {
... ... @@ -59,7 +59,7 @@ export default function homeReducer(state = initialState, action) {
return nextState;
}
case HOME_BANNER_FAILURE:
case HOME_BANNER_AND_SECTION_FAILURE:
case HOME_NOTICE_FAILURE:
case HOME_SECTION_FAILURE:
case HOME_RECOMMENDATION_FAILURE:
... ...
... ... @@ -8,6 +8,27 @@ export default class HomeService {
this.api = new Request();
}
async bannerAndSection(appType) {
let authorId = 2222222;
let lastedTime = 1467116660000;
let limit = 10;
return await this.api.get({
url: '',
body: {
method: 'app.social.getHomePagePostList',
authorId,
lastedTime,
limit
}
})
.then((json) => {
return json;
})
.catch((error) => {
throw(error);
});
}
async recommendation(authorId, lastedTime) {
authorId = 2222222;
lastedTime = 1467116660000;
... ...