如何迈出第一步

在算法前5课结束后,我渐渐的明白了一个道理:不管前方多难,放手去做吧,最难的是迈出第一步,迈出去了,以后就掌控在你手中了。快排、最短路径、二叉树算是算法的基础内容,但是之前一直不敢下手把他们写出来,因为工作3年多了,都是在创业公司,重重的业务负担让人满脑子充斥的都是业务逻辑、UI界面,5年前学的东西都忘的干净,所以我不假思索的在日程中加入了写算法文章,并且马上买了一本算法的书。然后逼着自己写了开篇之后,发现每天上午上班,先放开手中的工作,安静的读书、实践代码、写出来自己的思想并分享给大家是一件很不错的事情,而且渐渐的觉得重新拾起了算法。其实我买的书的内容,就是讲解到了二叉树就完结了,我大概用了4天的时间读完了这本书。

然后就是今天所写的react-native,其实在RN刚出的时候,我就开始入手了(忠实的FaceBook技术粉),但是一直在给自己找理由不去实践,每次版本更新,也只是去官网看看例子,觉得理解就行了。这段时间有朋友问到我相关的东西,我发现,在实际动手的时候,我就写个登录界面都写的不是很得心应手。所以决定迈出写项目的第一步。那,又有人要问了,写什么项目呢?先别急,既然是迈出第一步,那就要慢慢来。我姑且当读者都熟悉HTML、CSS、JS。

当我们下载一个新的App的时候,我们最先看到的是什么?没错,启动页,引导图。启动页是配置到配置文件中的,所以我们来完成我们第一个引导页的制作

如果按照App的开发角度,这个界面可以用ScrollView、pageControl、Button来完成,当然在RN中也我们也假定是这样的。大家各自新建一个RN的项目,并且我们以iOS为准。

项目名大家随便搞一个,我们先不急着对文件进行分组归类,也不需要想着任何有关架构设想的事情。直接在index.ios.js中开始我们第一个界面的制作,当然,按照App的思想,这个视图控制器的基本层级是: View:ScrollView:pageControl, Button,所以我们先渲染一个全屏的View,背景色为skyblue

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import React, { Component } from 'react';
import {
AppRegistry,
StyleSheet,
View
} from 'react-native'
class Project extends Component {
render() {
return (
<View style={styles.container}>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: 'skyblue',
}
});
AppRegistry.registerComponent('Project', () => Project);

接着,我们写一个ScrollView上去:并且在上边加入3个屏幕大小的不同颜色的View,并对scrollView做一些简单的配置。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
import React, { Component } from 'react';
import {
AppRegistry,
StyleSheet,
View,
ScrollView,
Text,
Dimensions
} from 'react-native'
class Project extends Component {
render() {
var windowWidth = Dimensions.get('window').width;
var windowHeight = Dimensions.get('window').height;
return (
<View style={styles.container}>
<ScrollView
horizontal={true}
showsHorizontalScrollIndicator={false}
alwaysBounceHorizontal={true}
pagingEnabled={true}
style={styles.scrollView}>
<View style={{ backgroundColor: 'orange', height: windowHeight, width: windowWidth }} />
<View style={{ backgroundColor: 'red', height: windowHeight, width: windowWidth }} />
<View style={{ backgroundColor: 'yellow', height: windowHeight, width: windowWidth }} />
</ScrollView>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1
},
scrollView: {
flex: 1,
backgroundColor: 'skyblue'
}
});
AppRegistry.registerComponent('Project', () => Project);

接下来我们亲自写一个小组件,用于放至中间的一张图片以及一段文字,新建一个js文件,姑且命名为scrollContent.js,先别急着写,先把这个组件引入到index.js种,然后替换到刚刚我们的View。 然后再开始编写,这里要注意,我们先约定,组件的样式定义到组件里。

组件内容,我们大致的拆分为:图片,标题,详情,附加详情。 原本应该是这样的,但是我们看到下边还有一个页面指示器,所以我们还需要一个占位的视图。至于下边的跳过按钮,我暂时觉得这个不太好,我们应该在最后一页才展示一个进入App的按钮(要求用户必须看完。。),所以我们先写一个这样的按钮放到底部。我一度没有正规的学过前端,所以css写的特别烂!希望可以在博客之路找到个好的老司机带路上车!先来看组件的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
import React, { Component, } from 'react'
import {
View,
StyleSheet,
Image,
Text,
Dimensions,
TouchableOpacity,
} from 'react-native'
class ScrollContent extends Component {
static propTypes = {}
static defaultProps = {}
constructor(props) {
super(props)
this.state = {}
}
render() {
return (
// http://ocef2grmj.bkt.clouddn.com/Clothes-illustration.png
// http://ocef2grmj.bkt.clouddn.com/Group1.png
<View>
<View style={ styles.container }>
<Image source={{ uri:'http://ocef2grmj.bkt.clouddn.com/Group.png' }} style={ styles.image }/>
<Text style={ styles.title }>Shopping directly</Text>
<Text style={ styles.detail }>Know your factories. Know your costs.</Text>
<Text style={ styles.subDetail }>Always ask why.</Text>
<View style={ styles.placeHold }></View>
</View>
<View style={ styles.buttonGroup }>
<TouchableOpacity onPress={() => {}} activeOpacity={50 / 100}>
<Text style={ styles.enterButton }>Enter</Text>
</TouchableOpacity>
</View>
</View>
)
}
}
const contentWidth = Dimensions.get('window').width;
const contentHeight = Dimensions.get('window').height - 60;
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
backgroundColor: 'white',
width: contentWidth,
height: contentHeight
},
image: {
width: 253,
height: 200
},
title: {
fontSize: 24,
color: '#358ED7',
fontWeight: "400",
marginTop: 50
},
detail: {
fontSize: 14,
color: '#1D1D26',
fontWeight: "400",
marginTop: 20
},
subDetail: {
fontSize: 14,
color: '#1D1D26',
fontWeight: "400",
marginTop: 2
},
placeHold: {
marginTop: 40,
height: 15,
width: 80
},
buttonGroup: {
height: 60,
width: contentWidth,
flex: 1,
alignItems: 'center',
justifyContent: 'center',
backgroundColor: 'white'
},
enterButton: {
padding: 15,
paddingTop: 5,
paddingBottom: 5,
borderWidth: 1,
color: '#34A3FF',
fontSize: 17,
borderColor: '#34A3FF',
borderRadius: 3
}
});
export default ScrollContent

然后看使用:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
import React, { Component } from 'react';
import {
AppRegistry,
StyleSheet,
View,
ScrollView,
} from 'react-native'
import ScrollContent from './ScrollContent'
class Project extends Component {
render() {
return (
<View style={styles.container}>
<ScrollView
horizontal={true}
showsHorizontalScrollIndicator={false}
alwaysBounceHorizontal={true}
pagingEnabled={true}
style={styles.scrollView}>
<ScrollContent />
<ScrollContent />
<ScrollContent />
</ScrollView>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1
},
scrollView: {
flex: 1,
backgroundColor: 'skyblue'
}
});
AppRegistry.registerComponent('Project', () => Project);

这个时候,我们发现组件里的内容还是外界传入比较好,所以使用props,我们来修改自己的组件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
return (
<View>
<View style={ styles.container }>
<Image source={{ uri: this.props.uri }} style={ styles.image }/>
<Text style={ styles.title }>{this.props.title}</Text>
<Text style={ styles.detail }>{this.props.detail}</Text>
<Text style={ styles.subDetail }>{this.props.subDetail}</Text>
<View style={ styles.placeHold }></View>
</View>
<View style={ styles.buttonGroup }>
<TouchableOpacity onPress={() => {}} activeOpacity={50 / 100}>
{
this.props.showEnter == true?
(<Text style={ styles.enterButton }>Enter</Text>): (null)
}
</TouchableOpacity>
</View>
</View>
)

然后在使用:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<ScrollContent
uri="http://ocef2grmj.bkt.clouddn.com/Group.png"
title="Shopping directly"
detail="Know your factories. Know your costs."
subDetail="Always ask why."
showEnter={false} />
<ScrollContent
uri="http://ocef2grmj.bkt.clouddn.com/Clothes-illustration.png"
title="Buy shoes"
detail="Know your factories. Know your costs."
subDetail="Always ask why."
showEnter={false} />
<ScrollContent
uri="http://ocef2grmj.bkt.clouddn.com/Group1.png"
title="Shopping directly"
detail="Know your factories. Know your costs."
subDetail="Always ask why."
showEnter={true} />

这样完成了之后,我们来看一下初期的效果:

你们完成了么?然后大家发现,我们只是完成了一部分,少了一个指示器,然后我们来自定义这个控件,新建js文件pageControl.js。最简单的思维,3个小View(这里我们先写死3个)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
import React, { Component, } from 'react'
import { View, StyleSheet } from 'react-native'
class PageControl extends Component {
static propTypes = {}
static defaultProps = {}
constructor(props) {
super(props)
this.state = {}
}
render() {
return (
<View style={styles.container}>
<View style={this.props.index == 0 ? styles.itemHighLight : styles.item}></View>
<View style={this.props.index == 1 ? styles.itemHighLight : styles.item}></View>
<View style={this.props.index == 2 ? styles.itemHighLight : styles.item}></View>
</View>
)
}
}
const styles = StyleSheet.create({
container: {
backgroundColor: 'white',
flexDirection: 'row',
alignItems: 'center',
justifyContent: "space-between",
width: 50,
marginTop: 40
},
item: {
width: 10,
height: 10,
borderRadius: 5,
backgroundColor: 'white',
borderColor: '#34a3ff',
borderWidth: 1
},
itemHighLight: {
width: 10,
height: 10,
borderRadius: 5,
backgroundColor: 'skyblue'
}
});
export default PageControl

这里写的比较作死, 这里应该是外界传入items的个数,然后每次设置一下index就好了,这里偷懒了,我们继续来优化这个pageControl,稍作修改:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
render() {
var number = this.props.number;
var index = this.props.index;
var items = new Array();
for (var i=0; i<number; i++) {
var item = (
<View style={i == index ? styles.itemHighLight : styles.item} key={i} ></View>
);
items.push(item);
}
return (
<View style={styles.container}>
{items}
</View>
)
}

这样在使用的时候就可以:

1
<PageControl style={styles.pageControl} number={3} index={this.props.index}/>

到现在,我们总算磕磕绊绊的完成了一个滑动视图,而且还有很多的缺陷。明天我们继续来优化这个小的组件,争取做到每个方面都很极致。

代码的地址,以后每次更新之后都会修改这里的代码。

评论