南通网站建设公司百度关键词搜索
想自定义广告-
场景: 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' // 用来存储用户设置的首选项的keyexport const USER_SETTING_AD = 'fast_driver_setting_ad' // 用来存储用户设置广告首选项的key// 负责首选项的读取
export class UserSetting {context: Contextconstructor(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))@StateadObj: AdvertClass = {showAd: false,adTime: 0}timer: number = -1closeWin() {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 = 0while (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上下文必须得等到页面初始化之后才可以进行获取// 生成一个namelet name = `dialog_${util.generateRandomUUID()}`// 通过当前的主窗口来获取const mainWin = await window.getLastWindow(this.context || getContext())let uiContext = mainWin.getUIContext() // 拿到UIContextlet 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() // 拿到UIContextlet promptAction = uiContext.getPromptAction();promptAction.closeCustomDialog(this.map.get(name))// 清理mapthis.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 abilityhilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageCreate');// 开启全屏const win = windowStage.getMainWindowSync()win.setWindowLayoutFullScreen(true)// 获取安全区域const top = win.getWindowAvoidArea(window.AvoidAreaType.TYPE_SYSTEM).topRectAppStorage.setOrCreate<number>('safeTop', px2vp(top.height))const bottom = win.getWindowAvoidArea(window.AvoidAreaType.TYPE_NAVIGATION_INDICATOR).bottomRectAppStorage.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")}}