React_Native 项目实战 (1) (首页,以及页面的切换)

来源:互联网 发布:plug2view软件下载 编辑:程序博客网 时间:2024/06/06 10:52

写一个用reactnative 的项目 可以用于查看GitHub最受欢迎与最热项目的App。

https://github.com/liudao01/ReactNativeProject

github地址 还在更新中

项目开始 HomePage.js

PS 可以先拖动到底部看下效果图

新建一个reactnative项目 ,

底部因为有四个tab 选项卡 那么 我使用一个第三方组件react-native-tab-navigator

并且新建一个HomePage.js,关于第三方组件可以看下这篇文章 http://blog.csdn.net/true100/article/details/68066649

这里单独说下 npm install react-native-tab-navigator –save 后面这个–save 这个的作用是用户把这个库加入到package.json中去.

在Homepage.js里面 使用react-native-tab-navigatior

这是 index.android.js

/** * Sample React Native App * https://github.com/facebook/react-native * @flow */import React, { Component } from 'react';import {  AppRegistry,  StyleSheet,  Text,  View} from 'react-native';import Homepage from "./js/pages/HomePage";export default class testP extends Component {  render() {    return (      <View style={styles.container}>        <Homepage/>      </View>    );  }}const styles = StyleSheet.create({  container: {    flex: 1,  }});AppRegistry.registerComponent('testP', () => testP);

这是 Hmepage.js

/** * Created by liuml on 2017/9/8. */import React, {Component} from 'react';import {    AppRegistry,    StyleSheet,    Text,    View,    Image} from 'react-native';import TabNavigator from 'react-native-tab-navigator';import TabNavigatorItem from "react-native-tab-navigator/TabNavigatorItem";export default class Homepage extends Component {    // 构造    constructor(props) {        super(props);        // 初始状态        this.state = {selectedTab: 'papular'};    }    render() {        return <View style={styles.container}>            <TabNavigator>                <TabNavigator.Item                    selected={this.state.selectedTab === 'papular'}                    title="最热"                    slectedTitleStyle={{color: '#FFF'}}                    renderIcon={() => <Image style={styles.icon}                                             source={require('../../res/images/ic_popular.png')}></Image>}                    renderSelectedIcon={() =>                        <Image style={[styles.icon, {tintColor: '#63B8FF'}]}                               source={require('../../res/images/ic_popular.png')}/>}                    onPress={() => this.setState({selectedTab: 'papular'})}>                    <View style={{backgroundColor: '#FF0', flex: 1}}/>                </TabNavigator.Item>                <TabNavigator.Item                    selected={this.state.selectedTab === 'trending'}                    slectedTitleStyle={{color: '#0F0'}}                    renderIcon={() => <Image style={styles.icon}                                             source={require('../../res/images/ic_trending.png')}/>}                    renderSelectedIcon={() =>                        <Image style={[styles.icon, {tintColor: '#63B8FF'}]}                               source={require('../../res/images/ic_trending.png')}/>}                    onPress={() => this.setState({selectedTab: 'trending'})}                    title="趋势">                    <View style={{backgroundColor: '#0F0', flex: 1}}/>                </TabNavigator.Item>                <TabNavigator.Item                    selected={this.state.selectedTab === 'favorite'}                    slectedTitleStyle={{color: '#0F0'}}                    renderIcon={() => <Image style={styles.icon}                                             source={require('../../res/images/ic_favorite.png')}/>}                    renderSelectedIcon={() =>                        <Image style={[styles.icon, {tintColor: '#63B8FF'}]}                               source={require('../../res/images/ic_favorite.png')}/>}                    onPress={() => this.setState({selectedTab: 'favorite'})}                    title="收藏">                    <View style={{backgroundColor: '#0FF', flex: 1}}/>                </TabNavigator.Item>                <TabNavigator.Item                    selected={this.state.selectedTab === 'my'}                    slectedTitleStyle={{color: '#0F0'}}                    renderIcon={() => <Image style={styles.icon}                                             source={require('../../res/images/ic_my.png')}/>}                    renderSelectedIcon={() =>                        <Image style={[styles.icon, {tintColor: '#63B8FF'}]}                               source={require('../../res/images/ic_my.png')}/>}                    onPress={() => this.setState({selectedTab: 'my'})}                    title="我的">                    <View style={{backgroundColor: '#FFF', flex: 1}}/>                </TabNavigator.Item>            </TabNavigator>        </View>    }}const styles = StyleSheet.create({    container: {        flex: 1    },    icon: {        width: 26,        height: 26    }});

解释:

我这里拿出一个item 出来解释

renderSelectedIcon 这是选中后的图片
tintColor 是给图片渲染
title 就是名字
我在构造函数中定义了一个变量selectedTab 让他默认是最热

// 初始状态
this.state = {selectedTab: ‘papular’};

然后在item中判断selected={this.state.selectedTab === ‘papular’} 值是否为最热

通过selected 判断是否选中状态 根据值是否相等

在onPress 点击事件 里面给他重新设置值

在每个item 中间可以看到我填充了一个view

<View style={{backgroundColor: '#FF0', flex: 1}}/>

这个就是作为填充的视图

                <TabNavigator.Item                    selected={this.state.selectedTab === 'papular'}                    title="最热"                    slectedTitleStyle={{color: '#FFF'}}                    renderIcon={() => <Image style={styles.icon}                                             source={require('../../res/images/ic_popular.png')}></Image>}                    renderSelectedIcon={() =>                        <Image style={[styles.icon, {tintColor: '#63B8FF'}]}                               source={require('../../res/images/ic_popular.png')}/>}                    onPress={() => this.setState({selectedTab: 'papular'})}>                    <View style={{backgroundColor: '#FF0', flex: 1}}/>                </TabNavigator.Item>

然后 看下效果图

image


最后看下这个第三方库react-native-TabNavigator的item的源码 直接在import哪里点击引入就好(android studio
怎么点这里就怎么点)

export default class TabNavigatorItem extends React.Component {  static propTypes = {    renderIcon: PropTypes.func,    renderSelectedIcon: PropTypes.func,    badgeText: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),    renderBadge: PropTypes.func,    title: PropTypes.string,    titleStyle: Text.propTypes.style,    selectedTitleStyle: Text.propTypes.style,    tabStyle: ViewPropTypes.style,    selected: PropTypes.bool,    onPress: PropTypes.func,    allowFontScaling: PropTypes.bool,  };  static defaultProps = {  };  render() {    let child = React.Children.only(this.props.children);    return React.cloneElement(child, {      style: [child.props.style, this.props.style],    });  }}

可以看到 renderIcon renderSelectedIcon 等等的声明都在这里


最热页面 PapularPage.js : 以及导航栏 NavigationBar.js

说下对应关系 homepage 里面包含了最热页面 PapularPage.js 最热页面里面包含了导航栏 NaivgationBar.js

关于react native 布局 这篇文章很不错错 http://www.jianshu.com/p/688b9108a922

先写NavigationBar.js

/** * Created by liuml on 2017/9/11. */import React, {Component} from 'react';import {    AppRegistry,    StyleSheet,    Text,    View,    StatusBar,    Platform,    Image,    TouchableOpacity} from 'react-native';export default class NavigationBar extends Component {    render() {        return <View style={styles.container}>            <View style={styles.container}>                <StatusBar hidden={false} barStyle="light-content"/>            </View>            {/*顶部导航栏*/}            <View style={styles.navBar}>                <View style={styles.navBar}></View>                <View style={styles.titleWrapper}>                    <Text style={styles.title}>热门</Text>                </View>                <View style={styles.rightBar}>                    <TouchableOpacity activeOpacity={0.7}>                        <Image source={require('../../res/images/ic_search_white_48pt.png')}></Image>                    </TouchableOpacity>                    <TouchableOpacity activeOpacity={0.7}>                        <Image source={require('../../res/images/ic_more_vert_white_48pt.png')}></Image>                    </TouchableOpacity>                </View>            </View>        </View>    }}const styles = StyleSheet.create({    container: {        backgroundColor: '#63B8FF',    },    statusBar: {        height: Platform.OS === 'ios' ? 20 : 0    },    navBar: {        flexDirection: 'row',        justifyContent: 'space-between',        alignItems: 'center',    },    titleWrapper: {        flexDirection: 'column',        justifyContent:'center',        alignItems:'center',        position:'absolute',        left:40,        right:40,    },    title: {        fontSize: 16,        color: '#FFF'    },    rightBar: {        flexDirection: 'row',        alignItems: 'center',        paddingRight:8    }});

看下效果图

mark

分析 从样式分析

statusBar

NavigationBar 会包含状态栏,还有顶部导航栏 状态栏用到一个控件 StatusBar (ios用的)

注意这里ios和android 稍微有点不同了ios StatusBar 有效果 就是显示顶部的状态栏.安卓没效果

关于状态栏说下 ios 可以使用 android 无效果 所以得区分下 这里我使用了Platfrom 判断是ios 还是android

flexDirection: ‘row’, 让主轴方向是横向

justifyContent: ‘space-between’, 让主轴排列方式是在每行上均匀分配弹性元素。相邻元素间距离相同。每行第一个元素与行首

对齐,每行最后一个元素与行尾对齐。( 这里面有个技巧: 因为控件只有三个

会造成热门文字不在中间, 那么我就在最左边再添加一个view )

titleWrapper

flexDirection: ‘column’, 让主轴方向是纵轴

justifyContent: ‘center’, 主轴排列方式居中

alignItems: ‘center’, 交叉轴的排列方式也是居中的

position: 'absolute',    left: 40,    right: 40,   

说下为什么这里需要position ,可以尝试下不加position 会造成热门并不在中间.那么就给他使用position 并且微调下

position enum(‘absolute’,’relative’)属性设置元素的定位方式,为将要定位的元素定义定位规则。

absolute 生成绝对定位的元素,元素的位置通过 “left”, “top”, “right” 以及 “bottom” 属性进行规定。

relative:生成相对定位的元素,相对于其正常位置进行定位。因此,”left:20” 会向元素的 LEFT 位置添加 20 像素。

title

没啥说的就是设置了颜色和大小

也没啥说的 就是给设置了宽高 右边的搜索和更多的图片宽高

rightBar

包裹右面两个图片的样式

flexDirection: ‘row’, 主轴方向横向

alignItems: ‘center’, 主轴对齐方式居中对齐

paddingRight: 8 居右8?  我不清楚这个是dp 还是像素

TouchableOpacity(透明度变化)

TouchableOpacity组件介绍
该组件封装了响应触摸事件。当点击按下的时候,该组件的透明度会降低。该组件使用过程中

并不会改变视图的层级关系,而且我们可以非常容易的添加到应用并且不会产生额外的异常错误。

创建 PapularPage.js 里面包含了NavigationBar.js

/** * Created by liuml on 2017/9/11. */import React, {Component} from 'react';import {    AppRegistry,    StyleSheet,    Text,    View,    Image}from 'react-native';import NavigationBar from "../compoent/NavigationBar.js"export default class PapularPage extends Component {    render() {        return <View style={styles.container}>            <NavigationBar/>        </View>    }}const styles = StyleSheet.create({    container: {        flex: 1    }});

没啥说的 非常简单就是把NavigationBar加入到了这个Papular页面

把上面的做好之后的效果图就是我上面的效果图


OK 下面在PapularPage页面内添加 可以左右滑动的控件(选项卡控件)

react-native-scrollable-tab-view

用到一个第三方组件 http://www.jianshu.com/p/b7788c3d106e

上面有使用方式 我把他引入我的项目

/** * Created by liuml on 2017/9/11. */import React, {Component} from 'react';import {    AppRegistry,    StyleSheet,    Text,    View,    Image}from 'react-native';import NavigationBar from "../compoent/NavigationBar.js"import ScrollableTabView from "react-native-scrollable-tab-view"export default class PapularPage extends Component {    render() {        return <View style={styles.container}>            <NavigationBar/>            <ScrollableTabView                tabBarBackgroundColor="#63B8FF"                tabBarActiveTextColor="#FFF"                tabBarInactiveTextColor="#F5FFFA"                tabBarUnderlineStyle={{backgroundColor: "#E7E7E7", height: 2}}>                <Text tabLabel='IOS'/>                <Text tabLabel='Android'/>                <Text tabLabel='Java'/>                <Text tabLabel='JavaScript'/>            </ScrollableTabView>        </View>    }}const styles = StyleSheet.create({    container: {        flex: 1    }});

mark

比较简单没啥说的.

现在的数据是写死的 后面会动态改变

tabBarUnderlineStyle(style)
设置DefaultTabBar和ScrollableTabBarTab选中时下方横线的颜色

tabBarBackgroundColor(String)
设置整个Tab这一栏的背景颜色

tabBarActiveTextColor(String)
设置选中Tab的文字颜色

tabBarInactiveTextColor(String)
设置未选中Tab的文字颜色

tabBarTextStyle(Object)
设置Tab文字的样式,比如字号、字体等


下面是关于布局的总结:

容器的属性

flexDirection

flexWrap

justifyContent

alignItems

项目的属性

flex

alignSelf

flexDirection属性

flexDirection属性决定主轴的方向(即项目的排列方向)。
它可能有4个值:

row:主轴为水平方向,起点在左端。

row-reverse:主轴为水平方向,起点在右端。

column(默认值):主轴为垂直方向,起点在上沿。

column-reverse:主轴为垂直方向,起点在下沿。

flexWrap属性

默认情况下,项目都排在一条线(又称”轴线”)上。flex-wrap属性定义,如果一条轴线排不下,如何换行。它可能取三个值。

(1)nowrap(默认):不换行。

(2)wrap:换行,第一行在上方。

justifyContent属性

justify-content属性定义了项目在主轴上的对齐方式。

它可能取5个值,具体对齐方式与轴的方向有关。下面假设主轴为从左到右。
flex-start(默认值):左对齐

flex-end:右对齐

center: 居中

space-between:两端对齐,项目之间的间隔都相等。

space-around:每个项目两侧的间隔相等。所以,项目之间的间隔比项目与边框的间隔大一倍。

alignItems属性

align-items属性定义项目在交叉轴上如何对齐。
它可能取5个值。具体的对齐方式与交叉轴的方向有关,下面假设交叉轴从上到下。

flex-start:交叉轴的起点对齐。

flex-end:交叉轴的终点对齐。

center:交叉轴的中点对齐。

baseline: 项目的第一行文字的基线对齐。

stretch(默认值):如果项目未设置高度或设为auto,将占满整个容器的高度。

flex属性

flex属性是flex-grow, flex-shrink 和 flex-basis的简写,默认值为0 1 auto。后两个属性可选。

flex-grow属性

flex-grow属性定义项目的放大比例,默认为0,即如果存在剩余空间,也不放大。

如果所有项目的flex-grow属性都为1,则它们将等分剩余空间(如果有的话)。如果一个项目的flex-grow属性为2,其他项目都为1,则前者占据的剩余空间将比其他项多一倍。

alignSelf属性

alignSelf属性允许单个项目有与其他项目不一样的对齐方式,可覆盖align-items属性。

默认值为auto,表示继承父元素的align-items属性,如果没有父元素,则等同于stretch。

该属性可能取6个值,除了auto,其他都与align-items属性完全一致。

阅读全文
0 0