react native 开发APP(三)引导页和广告页

react native 引导页和广告页

官网 https://reactnative.cn/

项目下载地址:https://github.com/hebiao6446/DemoProject
陆续更新中。。。

1.先看效果

这是app store上随机找的一个APP
在这里插入图片描述
引导页面大部分APP都有的 。。。 尽管这东西没什么用不说,还占APP控件(总有些2B的设计喜好搞那些鲜艳颜色的高清图)所以大一点的厂或者知名的APP逐渐的废弃了这个功能,我们来分析下 。。。
其实这个就是几张图片和一个分页的控件

在这里插入图片描述

react native里面大部分东西都是模块化的,这个其实也不例外,我们可以把每一个page看做成一个模块页面,其实我们的page就是一张图片
我们用代码实现看并观察效果
先看效果
在这里插入图片描述
代码如下 这个是单个page的代码

import React, {Component} from 'react';
import {Image, StyleSheet, View} from 'react-native';
const img_guide1 = require('../appimages/guide1.png');
class GuideView extends Component{

    render(){
        return (
            <View>
                <Image source={img_guide1}  style={styles.imgStyle} ></Image>
            </View>
        );
    }
}
const styles = StyleSheet.create({

    imgStyle:{
        resizeMode:'cover',
        height: '100%',
        width: '100%',
    },

});
export default GuideView;

下面的代码是引用单个page
在这里插入图片描述

上代码

import React, {Component} from 'react';
import {View, StyleSheet, Text} from 'react-native';
import GuideView from './appcode/GuideView';

class App extends Component{
        render() {
            return (
                <View style={styles.view1}>
                     <GuideView/>
                </View>
            )
        }
}
const styles = StyleSheet.create({
    view1:{
        flex:1,
        justifyContent:'center',
    }
});
export default App;

这里有一个问题就是通常页面有很多个, 而这里却只有一个页面
所以我们需要多个GuideView,我们之前说到react native 所有的东西都可以模块化, 我们可以把多个GuideView封装起来 ,也就是我们有5个类似的GuideView 需要左右滑动,并且有页面效果 ,这里react native提供了一个控件叫 ViewPager
https://github.com/react-native-community/react-native-viewpager

import ViewPager from "@react-native-community/viewpager";
React native iOS Android
ViewPager UIScrollView ViewPager
PageControl UIPageControl

单个引导页我们已经完成了 ,但是通常的APP都有多个引导页面,也就是我们需要把 GuideView重复多次 , 这个时候我们想到react是模块化的东西,一切皆模块 我们需要一个group来管理GuideView ,并且用 viewpager 将其关联,引入 viewpager

在这里插入图片描述
一般跟翻页一起的就是 PageControl了 ,这哥们的作用就是page上面的几个点,这个属于通用功能,多了就不解释了。。。 这个哥们也需要引入
https://github.com/silentcloud/react-native-page-control

yarn add @react-native-community/viewpager 
npm install react-native-page-control --save

也别纳闷,为啥有时候用 yarn 有时候 用npm 这个自己百度,我是按照GitHub上作者的操作搬下来的,理论上这两个差不多,细小差别自行百度就行。

在这里插入图片描述

安装完以后ios别忘记 ,Android 可以不用处理

pod install 

在这里插入图片描述

2.管理所有的素材(图片)

react native 在引用图片的时候跟ios和Android不同,ios和Android都有固定的文件夹存放素材 多的不说,看代码
在这里插入图片描述

3.引导页最终效果与代码

在这里插入图片描述
单个页面Page

import React, {Component} from 'react';
import {Image, StyleSheet, View} from 'react-native';
class GuideView extends Component{
    render(){
        return (
            <View>
                <Image source={this.props.name} key={this.props.key} style={styles.imgStyle} ></Image>
            </View>
        );
    }
}
const styles = StyleSheet.create({
    imgStyle:{
        resizeMode:'cover',
        height: '100%',
        width: '100%',
    },
});
export default GuideView;

页面Page组的代码如下

import React, {Component} from 'react';
import HbImages from "./utils/HbImages";
import {StyleSheet, TouchableOpacity, View} from "react-native";
import GuideView from "./GuideView";
import PageControl from 'react-native-page-control';
import ViewPager from "@react-native-community/viewpager";
class GuideGroup extends Component{
    constructor(pros){
        super(pros);
        this.state = {
            imgArray:[HbImages.img_guide1,HbImages.img_guide2,HbImages.img_guide3,HbImages.img_guide4,HbImages.img_guide5],
            showButton:false,
            currentPage:0,
        }
        this.viewPagerSelectCurrent = this.viewPagerSelectCurrent.bind(this);
    }
    viewPagerSelectCurrent(tag) {
        this.setState({
            currentPage:tag.nativeEvent.position,
            showButton:tag.nativeEvent.position === 4,
        })
    }
    render(){
        return <View style={styles.container}>
            <ViewPager style={styles.viewPager}
                       initialPage={0} orientation={'horizontal'}
                       onPageSelected={this.viewPagerSelectCurrent}
            >
                {
                    this.state.imgArray.map(function (v,i) {
                        return <GuideView name={v} key={i} />
                    })
                }
            </ViewPager>
            <TouchableOpacity style={styles.btnView} onPress={
                () => {
                    if (!this.state.showButton) return;
                    this.props.onButtonClick();
                }
            } >
            </TouchableOpacity>
            <PageControl
                style={{position:'absolute', left:0, right:0, bottom:15}}
                numberOfPages={5}
                currentPage={this.state.currentPage}
                hidesForSinglePage
                pageIndicatorTintColor='#abaaaa'
                currentPageIndicatorTintColor='#313232'
                indicatorStyle={{borderRadius: 5}}
                currentIndicatorStyle={{borderRadius: 5}}
                indicatorSize={{width:8, height:8}}
            />
        </View>
    }
}
const styles = StyleSheet.create({
    container:{
        flex:1,
    },
    viewPager:{
        flex:1,
    },
    btnView:{
        backgroundColor:"#00ff0000",
        width:350,
        height:70,
        position:'absolute',
        // left:'50%',
        bottom:30,
        ...Platform.select({
            // ios:{ transform:[{translateX:'-150'}],},
            // android:{},
        })
    },
});
export default GuideGroup;


引导页算告一段落了,现在处理下广告页面,不过在处理广告页面之前我们先需要来研究一个新的东西就是本地存贮 storage

4.react native 里面的本地存储

我喜欢用这个 AsyncStorage ,其实有很多第三方的框架,找到适合自己的就行,其他的不重要

React native iOS Android
AsyncStorage NSUserDefaults SharedPreferences
异步 同步 同步

但是重点来了, 在react native 里面本地存储是异步的,这可能就是react native的一个蛋疼的开始了 。。。。 同样第一步导入包

yarn add @react-native-community/async-storage

https://github.com/react-native-community/async-storage
同样别忘记 进入 ios的目录

pod install

在这里插入图片描述
我们需要新建一个工具类来使用这东西,直接上代码

import AsyncStorage from '@react-native-community/async-storage';

class HbDataStorage {
    /**
     * 获取
     * @param key
     * @returns {Promise<T>|*|Promise.<TResult>}
     */
    static async get(key) {
        // const value = ;
        return await AsyncStorage.getItem(key);
    }
    /**
     * 保存
     * @param key
     * @param value
     * @returns {*}
     */
    static async save(key, value) {
        try {
            await  AsyncStorage.setItem(key, value.toString());
        } catch (e) {

        }
    }
}
export default HbDataStorage;

5.广告页

APP开发广告也是个老生常谈的问题,先看一个广告
在这里插入图片描述
那么 我们总结通常的广告页面的几个要素 :
1)是否有广告 , 2)广告的图片地址 , 3)广告的持续时间,4)点击广告的web页面地址, 5)点击广告web的标题,6)是否是第一次启动软件
我们需要搞一个跟开机闪屏广告有关的工具类

import HbDataStorage from "./HbDataStorage";

class ADUtil {
    static AD_HAVE_AD = "ad_have_ad";
    static AD_IMG_URL = "ad_img_url";
    static AD_DURING_TIME = "ad_during_time";
    static AD_WEB_TITEL = "ad_web_title";
    static AD_WEB_URL = "ad_web_url";
    static  AD_FT_START = "ad_firsttime_start";
    static async ftStart(){
        return await HbDataStorage.get(this.AD_FT_START) ;
    }
    static async setFtStart(b) {
        await HbDataStorage.save(this.AD_FT_START, b);
    }
    static async hasAd(){
       return  await HbDataStorage.get(this.AD_HAVE_AD) ;
    }
    static setHasAd(b){
        HbDataStorage.save(this.AD_HAVE_AD,b);
    }
    static async getAdDuringTime(){
        return  await HbDataStorage.get(this.AD_DURING_TIME);
    }
    static async getAdWebTitle(){
        return  await HbDataStorage.get(this.AD_WEB_TITEL);
    }
    static async getAdWebUrl(){
        return  await HbDataStorage.get(this.AD_WEB_URL);
    }
    static async getAdUrlImg(){
        return  await HbDataStorage.get(this.AD_IMG_URL);
    }
    static setAdUrlImg(v){
        HbDataStorage.save(this.AD_IMG_URL,v);
    }
    static setAdDuringTime(v){
        HbDataStorage.save(this.AD_DURING_TIME,v);
    }
    static setAdWebTitle(v){
        HbDataStorage.save(this.AD_WEB_TITEL,v);
    }
    static setAdWebUrl(v){
        HbDataStorage.save(this.AD_WEB_URL,v);
    }
}

export default ADUtil;

广告工具类写完后,我们注意到HbDataStorage ,react native的本地存储保存和获取都是异步的,保存可以先晾着一边,获取重点拿出来看下

ADUtil.hasAd().then((res)=>{
            if (res || res == 'true'){
                this.setState({
                    haveAD:true,
                })
            }
        }).catch((e)=>{
        });

这玩意是个异步,而且获取出来的值是字符串 (如果获取成功)
基于这些我们把广告也的逻辑代码展示下

import React, {Component} from 'react';
import {Image, Platform, StyleSheet, Text, TouchableOpacity, View} from "react-native";
import HbImages from "./utils/HbImages";
import React from "react";
import ADUtil from "./utils/ADUtil";

class ADView extends Component{
    constructor(pros){
        super(pros)
        this.state = {
            haveAD:false,
            adImgUrl:'',
            remainTime:5,
        }
    }
    render(){
        let showAD = this.state.haveAD && this.state.adImgUrl.length > 0 ;
        let showText = showAD ? <Image defaultSource={HbImages.img_launch}  style={styles.bgImage} source={{uri:this.state.adImgUrl}}></Image> : <Image defaultSource={HbImages.img_launch}  style={styles.bgImage}></Image> ;
        return (
            <View style={styles.container}>
                {showText}
                <View style={styles.djsView}  >
                    <Text style={styles.djsText}  onPress={
                        () => {
                            this.props.onButtonClick();
                        }
                    }
                    >{this.state.remainTime}s</Text>
                </View>
                <TouchableOpacity onPress={
                    () => {
                        this.props.onButtonClick();
                    }
                } >
                    <View style={styles.btnView} ></View>
                </TouchableOpacity>

            </View>)
    }
    componentDidMount(): void {

        ADUtil.getAdUrlImg().then((res)=>{
            this.setState({
                adImgUrl:res,
            })
        }).catch((e)=>{
        });
        ADUtil.hasAd().then((res)=>{
            if (res || res == 'true'){
                this.setState({
                    haveAD:true,
                })
            }
        }).catch((e)=>{

        });

        ADUtil.getAdDuringTime().then((res)=>{
            let rmt = Number.parseInt(res);
            this.setState({
                remainTime:rmt,
            })
            this.counFun(rmt);
        }).catch((e)=>{

        });
    }

    counFun(time):void{
        this.timer = setInterval(()=>{
            let t = this.state.remainTime - 1;
            if (t == 0){
                clearInterval(this.timer);
                this.props.onButtonClick();
            }else {
                this.setState({
                    remainTime:t,
                })
            }

        },1000);
    }

    componentWillUnmount(){
        clearInterval(this.timer);
    }
}
const styles = StyleSheet.create({
    container:{
        flex:1,
    },
    bgImage:{
        width:'100%',
        height:'100%',
    },
    djsView:{
        width: 46,
        height: 46,
        position:'absolute',
        backgroundColor:'#e8e8e8',
        borderRadius: 23,
        top:'5%',
        left:'80%',


    },
    djsText:{
        width: 46,
        height: 46,
        fontSize:16,
        fontWeight: '200',
        textAlign:'center',
        textAlignVertical: 'center',
        ...Platform.select({
            ios:{lineHeight: 46},
            android:{},
        })
    },
    btnView:{
        backgroundColor:"#00000000",
        width:300,
        height:150,
        position:'absolute',
        left:'50%',
        bottom:30,
        transform:[{translateX:-150}],
    },

});
export default ADView;

这里面涉及到 react native的生命周期的话,自行百度

React native iOS Android
componentDidMount ViewDidLoad onCreate
componentWillUnmount viewWillUnload onDestroy(不太准确)

我们来看效果 。。。
在这里插入图片描述
引导页和广告也分别都完成了, 这里面有个逻辑

Created with Raphaël 2.2.0启动APP第一次启动?加载引导页面进入APP内容加载广告页面yesno

也就是引导页面是广告页面是互斥的, 为什吗?? 第一次启动的时候广告也说不定还没有请求过来。。。。

项目下载地址:https://github.com/hebiao6446/DemoProject
陆续更新中。。。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章