搭建广告展示页Start
·
想自定义广告-
场景: app冷启动/热启动-有广告需求,就打开广告页,没有的话就去登录或者主页
- 有的app有的需要广告页,有的不需要,搞个配置呗!!!
- 通过首选项配置存储我们的一些常用配置,比如要不要广告页,还有广告页的路由地址,点击广告页跳转的链接,广告页倒计时的秒数
- 在入口处进行判断是否需要广告页,需要的话,跳转广告页-广告页根据设置的参数进行渲染
- 广告页能不能设置???--- 因为运营人员肯定不能每次都去改我们底层的代码-这里我还可以设置成动态的-就是初始化的时候通过请求去读一下云端的请求,然后把我们的图片和一些参数配置下来,这样每次你启动app就是运营人员给你配置的广告和设置了
1.新建一个关于广告类的数据模型
export class AdvertClass {
showAd: boolean = false // 是否展示广告
isFull: boolean = true // 是否全屏
adTime: number = 5 // 倒计时数据
adUrl?: string = "" // 要跳转的连接
adImg?: ResourceStr = "" // 图片连接
}
// 全屏广告 半屏广告
2.在utils中新建一个关于读取首选项的类,用来读取和设置首选项的广告设置- utils/setting.ets
export const defaultAd: AdvertClass = {
showAd: true,
isFull: true,
adTime: 5,
adImg: $r('[basic].media.start')
}
export const USER_SETTING = 'fast_driver_setting' // 用来存储用户设置的首选项的key
export const USER_SETTING_AD = 'fast_driver_setting_ad' // 用来存储用户设置广告首选项的key
// 负责首选项的读取
export class UserSetting {
context: Context
constructor(context: Context) {
this.context = context
}
// 获取仓库
getStore() {
return preferences.getPreferencesSync(this.context || getContext(), {
name: USER_SETTING
})
}
// 设置用户广告
async setUserAd(ad: AdvertClass) {
const store = this.getStore()
store.putSync(USER_SETTING_AD, ad)
await store.flush() // 让外界能够控制自己的流程
}
// 获取用户广告
getUserAd() {
const store = this.getStore()
return store.getSync(USER_SETTING_AD, defaultAd) as AdvertClass
}
}
export const userSetting = new UserSetting(getContext()) // 导出一个单例
3.实现Start页的页面结构及倒计时逻辑
import { window } from '@kit.ArkUI'
import { AdvertClass, UserSetting } from 'home'
@Entry
@Component
struct Start {
userSetting: UserSetting = new UserSetting(getContext(this))
@State
adObj: AdvertClass = {
showAd: false,
adTime: 0
}
timer: number = -1
closeWin() {
window.findWindow("ad_window").destroyWindow()
}
async aboutToAppear() {
this.adObj = await this.userSetting.getUserAd()
this.timer = setInterval(() => {
if (this.adObj.adTime === 0) {
clearInterval(this.timer)
this.closeWin()
return
}
this.adObj.adTime--
}, 1000)
}
aboutToDisappear(): void {
clearInterval(this.timer)
}
build() {
Stack({ alignContent: Alignment.TopEnd }) {
Image(this.adObj.adImg).objectFit(ImageFit.Cover)
Text(`${this.adObj.adTime}秒后跳过`)
.padding({ left: 10, right: 10 })
.margin({ right: 20, top: 20 })
.height(30)
.fontSize(14)
.borderRadius(15)
.backgroundColor($r('[basic].color.MW'))
.textAlign(TextAlign.Center)
.onClick(() => {
this.closeWin()
})
}
.height('100%')
.width('100%')
.padding({ top: 40 })
}
}
4.封装window窗口广告模式
import { display, window } from '@kit.ArkUI'
import { util } from '@kit.ArkTS'
export class AdManager {
context?: Context // 是给ability使用的
private winNames: string [] = []
// 展示广告 采用windows窗口的创建和销毁的方式
async showAd(url: string, width?: number, height?: number) {
if (url) {
let name = `win_${util.generateRandomUUID()}`
const win = await window.createWindow({
name,
windowType: window.WindowType.TYPE_DIALOG,
ctx: this.context || getContext()
})
if (width && width >= 320 && height && height >= 240) {
const screen = display.getDefaultDisplaySync()
let mainWidth = vp2px(width)
let mainHeight = vp2px(height)
win.resizeAsync(mainWidth, mainHeight)
win.moveWindowToAsync((screen.width - mainWidth) / 2, (screen.height - mainHeight) / 2)
}
await win.showWindow() // 展示窗口
win.setUIContent(url) // 设置地址
this.winNames.push(name)
return name
}
return ""
}
// 关闭广告
async closeAd(name?: string) {
if (name) {
window.findWindow(name).destroyWindow()
this.winNames = this.winNames.filter(item => item !== name) //清空数组内容
} else {
// 不传就认为 想关闭所有
let index = 0
while (index < this.winNames.length) {
await window.findWindow(this.winNames[index]).destroyWindow()
index++
}
this.winNames = [] // 清空数组
}
}
}
export const adManger = new AdManager()
5.采用与页面解耦的模式实现广告
import { AdvertClass } from '../viewmodels'
import { ComponentContent, promptAction, window } from '@kit.ArkUI'
import { util } from '@kit.ArkTS'
// 展示广告的结构最重要写的代码
@Builder
function AdBuilder(ad: AdvertClass) {
Column() {
Image(ad.adImg)
.width("100%")
.height("100%")
.objectFit(ImageFit.Cover)
.borderRadius(10)
Row() {
Image($r("app.media.ic_btn_close"))
.width(14)
.aspectRatio(1)
.fillColor("#ccc")
}
.width(30)
.aspectRatio(1)
.justifyContent(FlexAlign.Center)
.borderRadius(15)
.border({
color: '#ff343232',
width: 2
})
.margin({
top: 40
})
.onClick(() => {
if (ad.dialogName) {
adManagerFinal.closeAd(ad.dialogName) // ? name从哪里进来
}
})
}
.width(ad.isFull ? "100%" : "80%")
.height(ad.isFull ? "100%" : "50%")
}
export class AdManagerFinal {
context?: Context
// 所有的弹窗都放到这个map中 通过name来标识
private map: Map<string, ComponentContent<AdvertClass>> = new Map()
// 实际上需要广告
async showAd(ad: AdvertClass) {
// 按照文档实现
// UIContext上下文必须得等到页面初始化之后才可以进行获取
// 生成一个name
let name = `dialog_${util.generateRandomUUID()}`
// 通过当前的主窗口来获取
const mainWin = await window.getLastWindow(this.context || getContext())
let uiContext = mainWin.getUIContext() // 拿到UIContext
let promptAction = uiContext.getPromptAction();
ad.dialogName = name // 目的是将dialog的弹窗名称传递到builder中
let contentNode = new ComponentContent(uiContext, wrapBuilder(AdBuilder), ad);
let options: promptAction.BaseDialogOptions = {
alignment: DialogAlignment.Center,
autoCancel: false
};
this.map.set(name, contentNode) // 将key/value写入到map中
promptAction.openCustomDialog(contentNode, options);
// 一般半屏广告 是得用户手动点击才能关闭的 一般不会自动关闭
// setTimeout(() => {
// promptAction.closeCustomDialog(contentNode)
// }, 2000)
}
async closeAd(name: string) {
if (name) {
const mainWin = await window.getLastWindow(this.context || getContext())
let uiContext = mainWin.getUIContext() // 拿到UIContext
let promptAction = uiContext.getPromptAction();
promptAction.closeCustomDialog(this.map.get(name))
// 清理map
this.map.delete(name) // 删除已经关闭的弹窗
}
}
}
export const adManagerFinal = new AdManagerFinal()
6.完整代码-EntryAbility
async onWindowStageCreate(windowStage: window.WindowStage): Promise<void> {
// Main window is created, set main page for this ability
hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageCreate');
// 开启全屏
const win = windowStage.getMainWindowSync()
win.setWindowLayoutFullScreen(true)
// 获取安全区域
const top = win.getWindowAvoidArea(window.AvoidAreaType.TYPE_SYSTEM)
.topRect
AppStorage.setOrCreate<number>('safeTop', px2vp(top.height))
const bottom = win.getWindowAvoidArea(window.AvoidAreaType.TYPE_NAVIGATION_INDICATOR)
.bottomRect
AppStorage.setOrCreate<number>('safeBottom', px2vp(bottom.height))
windowStage.loadContent('pages/Index', (err) => {
if (err.code) {
hilog.error(0x0000, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? '');
return;
}
hilog.info(0x0000, 'testTag', 'Succeeded in loading the content.');
getUser.initUser()
auth.initUser()
});
//广告
// 发起一个向云端获取广告数据的请求
const userSetting = new UserSetting(this.context)
const result = await new Promise<AdvertClass>((resolve, reject) => {
setTimeout(() => {
resolve({
showAd: true,
adTime: 5,
adImg: $r('[basic].media.start')
} as AdvertClass)
}, 1000)
})
await userSetting.setUserAd(result) // 写入首选项
if (result.showAd) {
const win = await windowStage.createSubWindow("ad_window")
await win.showWindow()
win.setUIContent("pages/StartPage")
}
}
更多推荐




所有评论(0)