add yohoCoin RN UI review by zhanglixia
Showing
8 changed files
with
432 additions
and
1 deletions
@@ -2,6 +2,12 @@ | @@ -2,6 +2,12 @@ | ||
2 | 2 | ||
3 | import React, {Component} from 'react'; | 3 | import React, {Component} from 'react'; |
4 | import Immutable, {Map} from 'immutable'; | 4 | import Immutable, {Map} from 'immutable'; |
5 | +import LoadMoreIndicator from '../../../common/components/LoadMoreIndicator'; | ||
6 | +import YohoCoinNumHeader from './YohoCoinNumHeader'; | ||
7 | +import YohoCoinBanner from './YohoCoinBanner'; | ||
8 | +import BrandProductListCell from '../../../common/components/ListCell/ProductListCell'; | ||
9 | +import DeviceInfo from 'react-native-device-info'; | ||
10 | +import Weixin from '../../../guang/components/detail/Weixin'; | ||
5 | 11 | ||
6 | import ReactNative, { | 12 | import ReactNative, { |
7 | View, | 13 | View, |
@@ -21,6 +27,13 @@ export default class YohoCoin extends Component { | @@ -21,6 +27,13 @@ export default class YohoCoin extends Component { | ||
21 | 27 | ||
22 | constructor(props) { | 28 | constructor(props) { |
23 | super(props); | 29 | super(props); |
30 | + this.renderRow = this.renderRow.bind(this); | ||
31 | + this.renderSectionHeader = this.renderSectionHeader.bind(this); | ||
32 | + | ||
33 | + this.dataSource = new ListView.DataSource({ | ||
34 | + rowHasChanged: (r1, r2) => !Immutable.is(r1, r2), | ||
35 | + sectionHeaderHasChanged: (s1, s2) => !Immutable.is(s1, s2), | ||
36 | + }); | ||
24 | } | 37 | } |
25 | 38 | ||
26 | shouldComponentUpdate(nextProps){ | 39 | shouldComponentUpdate(nextProps){ |
@@ -32,6 +45,50 @@ export default class YohoCoin extends Component { | @@ -32,6 +45,50 @@ export default class YohoCoin extends Component { | ||
32 | } | 45 | } |
33 | } | 46 | } |
34 | 47 | ||
48 | + renderRow(rowData, sectionID, rowID, highlightRow) { | ||
49 | + if (sectionID == 'yohoCoin') { | ||
50 | + return (<YohoCoinNumHeader resource = {rowData} onPressYohoCoinDetail = {this.props.onPressYohoCoinDetail}/>) | ||
51 | + }else if (sectionID == 'banner') { | ||
52 | + return(<YohoCoinBanner resource = {rowData} onPressProduct={this.props.onPressBanner}/>) | ||
53 | + }else if (sectionID == 'weixin') { | ||
54 | + return(<Weixin resource={rowData} onPressWeixin={this.props.onPressWeixin}/>) | ||
55 | + }else if (sectionID == 'favoriteTitle') { | ||
56 | + let listNum = rowData; | ||
57 | + if (listNum == 0) { | ||
58 | + return null; | ||
59 | + } | ||
60 | + let fontFamilyStyle = {}; | ||
61 | + if (Platform.OS === 'ios') { | ||
62 | + let systemVersion = DeviceInfo.getSystemVersion(); | ||
63 | + systemVersion = parseFloat(systemVersion); | ||
64 | + if (systemVersion >= 9.0) { | ||
65 | + fontFamilyStyle = {fontFamily: 'PingFang SC'}; | ||
66 | + } | ||
67 | + } | ||
68 | + return( | ||
69 | + <View style={styles.title}> | ||
70 | + <Text style={[styles.text, fontFamilyStyle]}>你可能喜欢</Text> | ||
71 | + </View> | ||
72 | + ); | ||
73 | + }else if (sectionID == 'favorite') { | ||
74 | + let paddingLeft = rowID % 2 == 1 ? rowMarginHorizontal / 2 : rowMarginHorizontal; | ||
75 | + let customStyle = rowID == 0 || rowID == 1 ? {paddingLeft} : {paddingLeft}; | ||
76 | + return ( | ||
77 | + <BrandProductListCell | ||
78 | + style={[styles.listContainer, customStyle]} | ||
79 | + key={'row' + rowID} | ||
80 | + rowID={rowID} | ||
81 | + data={rowData} | ||
82 | + onPressProduct={this.props.onPressProductCell}/> | ||
83 | + ); | ||
84 | + } | ||
85 | + return null; | ||
86 | + } | ||
87 | + | ||
88 | + renderSectionHeader(sectionData, sectionID) { | ||
89 | + return null; | ||
90 | + } | ||
91 | + | ||
35 | render() { | 92 | render() { |
36 | 93 | ||
37 | let {resource} = this.props; | 94 | let {resource} = this.props; |
@@ -42,18 +99,62 @@ export default class YohoCoin extends Component { | @@ -42,18 +99,62 @@ export default class YohoCoin extends Component { | ||
42 | favorite, | 99 | favorite, |
43 | } = resource; | 100 | } = resource; |
44 | 101 | ||
102 | + let list = favorite?favorite.get('list'):null; | ||
103 | + | ||
104 | + let dataSource = { | ||
105 | + yohoCoin: [yohoCoin], | ||
106 | + banner: [banner], | ||
107 | + weixin: [weixin], | ||
108 | + favoriteTitle: [list?list.size:0], | ||
109 | + favorite: list?list.toArray():[], | ||
110 | + } | ||
111 | + | ||
45 | return ( | 112 | return ( |
46 | <View style={styles.container}> | 113 | <View style={styles.container}> |
47 | - <Text>YohoCoin</Text> | 114 | + <ListView |
115 | + ref='YohoCoinList' | ||
116 | + contentContainerStyle={styles.contentContainer} | ||
117 | + enableEmptySections={true} | ||
118 | + dataSource={this.dataSource.cloneWithRowsAndSections(dataSource)} | ||
119 | + renderRow={this.renderRow} | ||
120 | + renderSectionHeader={this.renderSectionHeader} | ||
121 | + onEndReached={() => { | ||
122 | + if (list && list.size > 0) { | ||
123 | + this.props.onEndReached && this.props.onEndReached(); | ||
124 | + } | ||
125 | + }} | ||
126 | + /> | ||
48 | </View> | 127 | </View> |
49 | ); | 128 | ); |
50 | } | 129 | } |
51 | } | 130 | } |
52 | 131 | ||
53 | let {width, height} = Dimensions.get('window'); | 132 | let {width, height} = Dimensions.get('window'); |
133 | +let rowWidth = Math.ceil(137.5 * width / 320); | ||
134 | +let rowMarginHorizontal = (width - rowWidth * 2) / 3; | ||
54 | 135 | ||
55 | let styles = StyleSheet.create({ | 136 | let styles = StyleSheet.create({ |
56 | container: { | 137 | container: { |
57 | flex: 1, | 138 | flex: 1, |
58 | }, | 139 | }, |
140 | + contentContainer:{ | ||
141 | + flexDirection: 'row', | ||
142 | + flexWrap: 'wrap', | ||
143 | + }, | ||
144 | + listContainer: { | ||
145 | + width: width / 2, | ||
146 | + }, | ||
147 | + title: { | ||
148 | + alignItems: 'center', | ||
149 | + justifyContent: 'center', | ||
150 | + height: 40, | ||
151 | + width: width, | ||
152 | + backgroundColor: 'white', | ||
153 | + }, | ||
154 | + text: { | ||
155 | + textAlign: 'left', | ||
156 | + fontSize: 17, | ||
157 | + fontWeight: 'bold', | ||
158 | + color: 'rgba(0,0,0,0.3)', | ||
159 | + }, | ||
59 | }); | 160 | }); |
1 | +'use strict'; | ||
2 | + | ||
3 | +import React from 'react'; | ||
4 | +import ReactNative from 'react-native'; | ||
5 | +import Swiper from 'react-native-swiper'; | ||
6 | +import YH_Image from '../../../common/components/YH_Image'; | ||
7 | +import {getSlicedUrl} from '../../../classify/utils/Utils'; | ||
8 | + | ||
9 | +const { | ||
10 | + View, | ||
11 | + TouchableOpacity, | ||
12 | + StyleSheet, | ||
13 | + Dimensions, | ||
14 | + Platform, | ||
15 | +} = ReactNative; | ||
16 | + | ||
17 | +import Immutable, {Map} from 'immutable'; | ||
18 | + | ||
19 | +export default class YohoCoinBanner extends React.Component { | ||
20 | + | ||
21 | + constructor(props) { | ||
22 | + super (props); | ||
23 | + | ||
24 | + this.dot = <View | ||
25 | + style={{ | ||
26 | + backgroundColor:'rgba(0,0,0,.2)', | ||
27 | + width: 6, | ||
28 | + height: 6, | ||
29 | + borderRadius: 3, | ||
30 | + marginLeft: 3, | ||
31 | + marginRight: 3, | ||
32 | + marginTop: (Platform.OS === 'ios')?3:1, | ||
33 | + marginBottom: 0, | ||
34 | + }} | ||
35 | + />; | ||
36 | + this.activeDot = <View | ||
37 | + style={{ | ||
38 | + backgroundColor:'white', | ||
39 | + width: 6, | ||
40 | + height: 6, | ||
41 | + borderRadius: 3, | ||
42 | + marginLeft: 3, | ||
43 | + marginRight: 3, | ||
44 | + marginTop: 3, | ||
45 | + marginBottom: 0, | ||
46 | + }} | ||
47 | + />; | ||
48 | + } | ||
49 | + | ||
50 | + shouldComponentUpdate(nextProps){ | ||
51 | + if (Immutable.is(nextProps.resource, this.props.resource)) { | ||
52 | + return false; | ||
53 | + } else { | ||
54 | + return true; | ||
55 | + } | ||
56 | + } | ||
57 | + | ||
58 | + render() { | ||
59 | + | ||
60 | + let resource = this.props.resource?this.props.resource.toJS():null; | ||
61 | + | ||
62 | + if (!resource) { | ||
63 | + return null; | ||
64 | + } | ||
65 | + let error = resource.error; | ||
66 | + let data = resource.list; | ||
67 | + if (error) { | ||
68 | + return null; | ||
69 | + } | ||
70 | + | ||
71 | + if (data.length == 1) { | ||
72 | + let newSrc = getSlicedUrl(data[0].src, width, swiperHeight); | ||
73 | + return ( | ||
74 | + <View style={styles.container}> | ||
75 | + <View style={{ | ||
76 | + width: width, | ||
77 | + height: 20, | ||
78 | + backgroundColor: 'rgb(240,240,240)', | ||
79 | + }}/> | ||
80 | + <TouchableOpacity | ||
81 | + activeOpacity={1} | ||
82 | + style={{width: width, height: swiperHeight}} | ||
83 | + onPress={() => { | ||
84 | + this.props.onPressProduct && this.props.onPressProduct(data[0].url) | ||
85 | + }} | ||
86 | + > | ||
87 | + <YH_Image | ||
88 | + url={newSrc} | ||
89 | + style={{ width: width, height: swiperHeight}} | ||
90 | + /> | ||
91 | + </TouchableOpacity> | ||
92 | + <View style={{ | ||
93 | + width: width, | ||
94 | + height: 15, | ||
95 | + backgroundColor: 'rgb(240,240,240)', | ||
96 | + }}/> | ||
97 | + </View> | ||
98 | + ); | ||
99 | + } else { | ||
100 | + return ( | ||
101 | + <View style={styles.container}> | ||
102 | + <View style={{ | ||
103 | + width: width, | ||
104 | + height: 20, | ||
105 | + backgroundColor: '#e0e0e0', | ||
106 | + }}/> | ||
107 | + <Swiper | ||
108 | + style={styles.banner} | ||
109 | + showsButtons={false} | ||
110 | + loop={true} | ||
111 | + autoplay={true} | ||
112 | + autoplayTimeout={2} | ||
113 | + paginationStyle={{bottom: 8}} | ||
114 | + dot={this.dot} | ||
115 | + activeDot={(Platform.OS === 'ios')?this.activeDot:null} | ||
116 | + width={width} | ||
117 | + height={swiperHeight} | ||
118 | + > | ||
119 | + {data.map((item, i) => { | ||
120 | + let newSrc = getSlicedUrl(item.src, width, swiperHeight); | ||
121 | + return ( | ||
122 | + <TouchableOpacity | ||
123 | + key={i} | ||
124 | + activeOpacity={1} | ||
125 | + onPress={() => { | ||
126 | + this.props.onPressProduct && this.props.onPressProduct(item.url,row_ID,1,template_name,template_id) | ||
127 | + }} | ||
128 | + > | ||
129 | + <YH_Image | ||
130 | + url={newSrc} | ||
131 | + style={{width: width, height: swiperHeight}} | ||
132 | + /> | ||
133 | + </TouchableOpacity> | ||
134 | + ); | ||
135 | + })} | ||
136 | + </Swiper> | ||
137 | + <View style={{ | ||
138 | + width: width, | ||
139 | + height: 15, | ||
140 | + backgroundColor: '#e0e0e0', | ||
141 | + }}/> | ||
142 | + </View> | ||
143 | + ); | ||
144 | + } | ||
145 | + } | ||
146 | +} | ||
147 | + | ||
148 | +let {width, height} = Dimensions.get('window'); | ||
149 | +let swiperHeight = Math.ceil((200 / 640) * width); | ||
150 | + | ||
151 | +let styles = StyleSheet.create({ | ||
152 | + container: { | ||
153 | + width: width, | ||
154 | + height: swiperHeight + 20 + 15, | ||
155 | + backgroundColor: 'white', | ||
156 | + }, | ||
157 | + | ||
158 | +}); |
1 | +'use strict'; | ||
2 | + | ||
3 | +import React from 'react'; | ||
4 | +import ReactNative from 'react-native'; | ||
5 | + | ||
6 | +const { | ||
7 | + Image, | ||
8 | + View, | ||
9 | + Text, | ||
10 | + StyleSheet, | ||
11 | + Dimensions, | ||
12 | + TouchableOpacity, | ||
13 | +} = ReactNative; | ||
14 | + | ||
15 | +export default class YohoCoinNumHeader extends React.Component { | ||
16 | + | ||
17 | + constructor(props) { | ||
18 | + super (props); | ||
19 | + } | ||
20 | + | ||
21 | + componentDidMount() { | ||
22 | + | ||
23 | + } | ||
24 | + | ||
25 | + render() { | ||
26 | + let resource = this.props.resource?this.props.resource.toJS():null; | ||
27 | + if (!resource) { | ||
28 | + return null; | ||
29 | + } | ||
30 | + let notice = resource.notice; | ||
31 | + let yohocoin_num = resource.yohocoin_num; | ||
32 | + let yohoCoinCode = resource.yohoCoinCode; | ||
33 | + | ||
34 | + let heigth_t = notice == '' ? headerHeight : headerHeight + noticeViewHeight; | ||
35 | + return ( | ||
36 | + <View style={{width: width,height: heigth_t,backgroundColor: 'white',}}> | ||
37 | + <View style={{width: width,height: headerHeight,backgroundColor: 'white',}}> | ||
38 | + <View style={styles.numView}> | ||
39 | + <Text style={styles.numText}>{yohocoin_num}</Text> | ||
40 | + </View> | ||
41 | + <View style={styles.numDetailView}> | ||
42 | + <Image style={styles.icon} source={require('../../image/yohocoin_icon.png')}/> | ||
43 | + <Text style={styles.numDetailText}>个有货币</Text> | ||
44 | + </View> | ||
45 | + <View style={styles.button}> | ||
46 | + <TouchableOpacity | ||
47 | + activeOpacity={1} | ||
48 | + style={{width: 100, height: ( 38/154 ) * 100}} | ||
49 | + onPress={() => { | ||
50 | + this.props.onPressYohoCoinDetail && this.props.onPressYohoCoinDetail(yohoCoinCode) | ||
51 | + }} | ||
52 | + > | ||
53 | + <Image style={styles.image} source={require('../../image/check_detail_btn.png')}/> | ||
54 | + </TouchableOpacity> | ||
55 | + </View> | ||
56 | + </View> | ||
57 | + {notice != '' ? | ||
58 | + <View style={styles.notice}> | ||
59 | + <Image style={styles.noticeIcon} source={require('../../image/yohocoin_notice_ic.png')}/> | ||
60 | + <Text style={styles.noticeText}>{notice}</Text> | ||
61 | + </View> | ||
62 | + : null} | ||
63 | + </View> | ||
64 | + ) | ||
65 | + } | ||
66 | +}; | ||
67 | + | ||
68 | +let {width, height} = Dimensions.get('window'); | ||
69 | +let headerHeight = Math.ceil((250 / 640) * width); | ||
70 | +let noticeViewHeight = Math.ceil((70 / 640) * width); | ||
71 | + | ||
72 | +const styles = StyleSheet.create({ | ||
73 | + numView: { | ||
74 | + marginTop: 20, | ||
75 | + width: width, | ||
76 | + height: 60, | ||
77 | + backgroundColor: 'white', | ||
78 | + alignItems: 'center', | ||
79 | + justifyContent: 'center', | ||
80 | + }, | ||
81 | + numText: { | ||
82 | + width:width, | ||
83 | + backgroundColor: 'white', | ||
84 | + color: 'rgb(206,11,36)', | ||
85 | + fontSize: 60, | ||
86 | + textAlign: 'center', | ||
87 | + }, | ||
88 | + numDetailView: { | ||
89 | + width: width, | ||
90 | + height: 25, | ||
91 | + backgroundColor: 'white', | ||
92 | + alignItems: 'center', | ||
93 | + justifyContent: 'center', | ||
94 | + flexDirection: 'row', | ||
95 | + }, | ||
96 | + icon: { | ||
97 | + width: 15, | ||
98 | + height: 15, | ||
99 | + }, | ||
100 | + numDetailText: { | ||
101 | + backgroundColor: 'white', | ||
102 | + color: 'gray', | ||
103 | + fontSize: 14, | ||
104 | + textAlign: 'center', | ||
105 | + }, | ||
106 | + button: { | ||
107 | + marginTop: 7, | ||
108 | + width: width, | ||
109 | + height: 40, | ||
110 | + backgroundColor: 'white', | ||
111 | + alignItems: 'center', | ||
112 | + justifyContent: 'center', | ||
113 | + }, | ||
114 | + image: { | ||
115 | + width: 100, | ||
116 | + height: ( 38/154 ) * 100, | ||
117 | + }, | ||
118 | + notice: { | ||
119 | + width: width, | ||
120 | + height: noticeViewHeight, | ||
121 | + backgroundColor: 'rgb(217,217,217)', | ||
122 | + flexDirection: 'row', | ||
123 | + alignItems: 'center', | ||
124 | + }, | ||
125 | + noticeIcon: { | ||
126 | + width: 15, | ||
127 | + height: 15, | ||
128 | + marginLeft: 15, | ||
129 | + }, | ||
130 | + noticeText: { | ||
131 | + backgroundColor: 'transparent', | ||
132 | + color: 'rgb(206,11,36)', | ||
133 | + fontSize: 11, | ||
134 | + marginLeft: 20, | ||
135 | + } | ||
136 | +}); |
@@ -44,6 +44,11 @@ function mapDispatchToProps(dispatch) { | @@ -44,6 +44,11 @@ function mapDispatchToProps(dispatch) { | ||
44 | class YohoCoinContainer extends Component { | 44 | class YohoCoinContainer extends Component { |
45 | constructor(props) { | 45 | constructor(props) { |
46 | super(props); | 46 | super(props); |
47 | + this._onEndReached = this._onEndReached.bind(this); | ||
48 | + this._onPressProductCell = this._onPressProductCell.bind(this); | ||
49 | + this._onPressWeixin = this._onPressWeixin.bind(this); | ||
50 | + this._onPressBanner = this._onPressBanner.bind(this); | ||
51 | + this._onPressYohoCoinDetail = this._onPressYohoCoinDetail.bind(this); | ||
47 | } | 52 | } |
48 | 53 | ||
49 | componentDidMount() { | 54 | componentDidMount() { |
@@ -57,6 +62,31 @@ class YohoCoinContainer extends Component { | @@ -57,6 +62,31 @@ class YohoCoinContainer extends Component { | ||
57 | 62 | ||
58 | } | 63 | } |
59 | 64 | ||
65 | + _onPressWeixin(data) { | ||
66 | + ReactNative.NativeModules.YH_CommonHelper.copyWechatIdToClipboard(data); | ||
67 | + } | ||
68 | + | ||
69 | + _onEndReached() { | ||
70 | + this.props.actions.fetchFavoriteList(); | ||
71 | + } | ||
72 | + | ||
73 | + _onPressYohoCoinDetail(yohoCoinCode) { | ||
74 | + ReactNative.NativeModules.YH_MyAssetsViewHelper.pushCoinDetail(yohoCoinCode); | ||
75 | + } | ||
76 | + | ||
77 | + _onPressBanner (url){ | ||
78 | + ReactNative.NativeModules.YH_CommonHelper.jumpWithUrl(url); | ||
79 | + } | ||
80 | + | ||
81 | + _onPressProductCell(product) { | ||
82 | + let productSkn = product && product.get('product_skn', 0); | ||
83 | + if (!productSkn) { | ||
84 | + return; | ||
85 | + } | ||
86 | + let url = `http://m.yohobuy.com?openby:yohobuy={"action":"go.productDetail","params":{"product_skn":"${productSkn}"}}`; | ||
87 | + ReactNative.NativeModules.YH_CommonHelper.jumpWithUrl(url); | ||
88 | + } | ||
89 | + | ||
60 | render() { | 90 | render() { |
61 | let {yohoCoin} = this.props; | 91 | let {yohoCoin} = this.props; |
62 | 92 | ||
@@ -64,6 +94,11 @@ class YohoCoinContainer extends Component { | @@ -64,6 +94,11 @@ class YohoCoinContainer extends Component { | ||
64 | <View style={styles.container}> | 94 | <View style={styles.container}> |
65 | <YohoCoin | 95 | <YohoCoin |
66 | resource={yohoCoin} | 96 | resource={yohoCoin} |
97 | + onEndReached={this._onEndReached} | ||
98 | + onPressProductCell= {this._onPressProductCell} | ||
99 | + onPressWeixin={this._onPressWeixin} | ||
100 | + onPressBanner={this._onPressBanner} | ||
101 | + onPressYohoCoinDetail={this._onPressYohoCoinDetail} | ||
67 | /> | 102 | /> |
68 | </View> | 103 | </View> |
69 | ); | 104 | ); |
js/myAssets/image/check_detail_btn@2x.png
0 → 100755
2.83 KB
js/myAssets/image/yohocoin_icon@2x.png
0 → 100755
2.12 KB
js/myAssets/image/yohocoin_notice_ic@2x.png
0 → 100755
1.52 KB
-
Please register or login to post a comment