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(不太準確) |
我們來看效果 。。。
引導頁和廣告也分別都完成了, 這裏面有個邏輯
也就是引導頁面是廣告頁面是互斥的, 爲什嗎?? 第一次啓動的時候廣告也說不定還沒有請求過來。。。。
項目下載地址:https://github.com/hebiao6446/DemoProject
陸續更新中。。。