oops-framework框架 之 界面管理(三)

news2025/2/25 14:33:35

引擎: CocosCreator 3.8.0

环境: Mac

Gitee: oops-game-kit

注: 作者dgflashoops-framework框架QQ群: 628575875


回顾


在上文中主要通过oops-game-kit大家了一个新的模版项目, 主要注意项是resources目录下的两个文件夹:

  • common 用于放置公共资源,在游戏启动时进行的必须加载
  • game 用于放置动态非必须资源,在游戏进度条显示时进行的加载

两个文件夹必须存在,否则程序会有报错。更多内容,可参考博客:

oops-framework框架 之 创建项目(二)

今天的文章主要讲述下框架的界面管理,以用于创建页面、切换页面、弹窗显示等处理。

若理解不当,欢迎您的指出。


界面管理


oops-framework的作者dgflash 针对于界面的管理主要分为了如下几个类型:

类型说明
Game游戏层,比如地图逻辑处理
UI主界面层,比如地图上方的菜单页面
PopUp弹窗层, 窗口显示后,支持非窗口区域点击,可显示多个不同配置的弹窗
Dialog模式窗口层,窗口显示后,非窗口区域不可透点
System系统窗口层,与Dialog类似,可用于显示系统信息的弹窗错误提示
Notify提示信息层, Tip信息显示,显示以后会上移消失
Guide新手引导层,用于新手的强制引导

注:界面类型来源于LayerManager.ts的枚举: LayerType

页面的显示,我们通常使用预制体Prefab实现,然后挂载上组件脚本。在框架中编写组件脚本,不需要特意的去继承什么,依然是Component即可。

页面构建后,需要在GameUIConfig.ts中进行配置:

// 界面唯一标识ID
export enum UIID {
    Loading = 1,		// 资源加载界面
    Window,					// 弹窗界面
    Netinstable,		// 加载与延时提示界面
    UI_MAIN,				// UI界面
}

/*
界面配置数据 UIConfig
export interface UIConfig {
    bundle?: string;			// 包名
    layer: LayerType;			// 页面类型
    prefab: string;				// 预制资源相对路径
}
*/
export var UIConfigData: { [key: number]: UIConfig } = {
  [UIID.Loading]: { layer: LayerType.UI, prefab: "common/prefab/loading", bundle: "resources"},
  [UIID.Netinstable]: { layer: LayerType.PopUp, prefab: "common/prefab/netinstable",bundle: "resources"},
  [UIID.Window]: { layer: LayerType.Dialog, prefab: "common/prefab/window",  bundle: "resources"},

  [UIID.UI_MAIN]: { layer: LayerType.UI, prefab: "game/prefab/uiMain", bundle: "resources"},
}

在配置完成以后,显示或隐藏页面的简单使用:

// 显示UI主页面
oops.gui.open(UIID.UI_MAIN);
// 关闭加载页面
oops.gui.remove(UIID.Loading);

LayerManager


LayerManager管理类是框架提供的界面管理类,在框架的Oops.ts中提供的入口:

// ../oops-plugin-framework/assets/core/Oop.ts
export class oops {
  static gui: LayerManager;
}

该管理类主要负责对不同页面的管理,提供的主要接口有:

参数或接口说明
root获取界面根节点
camera获取界面摄像机
game获取游戏界面根节点
guide获取新手引导
uiMap获取界面地图
setUIMap()设置界面地图配置
init()初始化所有UI配置
setConfig()根据uiId,设置UI配置
toast()Tip提示显示,支持是否显示多语言
open()根据uiId,同步打开某个页面或窗口
openAsync()根据uiId,异步打开某个页面或窗口
has()根据uiId, 检测是否存在某个页面或窗口
remove()根据uiId,移除某个页面或窗口
removeByNode()根据this框架添加的节点,移除某个页面或窗口
clear()清除所有窗口

看下LayerManager的构造函数实现:

constructor(root: Node) {
  this.root = root;
  this.camera = this.root.getComponentInChildren(Camera)!;
  // 不同界面类型构建节点,然后顺序添加到根节点中
  this.game = this.create_node(LayerType.Game);
  this.ui = new LayerUI(LayerType.UI);
  this.popup = new LayerPopUp(LayerType.PopUp);
  this.dialog = new LayerDialog(LayerType.Dialog);
  this.system = new LayerDialog(LayerType.System);
  this.notify = new LayerNotify(LayerType.Notify);
  this.guide = this.create_node(LayerType.Guide);
  // 注意下层级, LayerType.Game的最低,LayerType.Guide的最高
  root.addChild(this.game);
  root.addChild(this.ui);
  root.addChild(this.popup);
  root.addChild(this.dialog);
  root.addChild(this.system);
  root.addChild(this.notify);
  root.addChild(this.guide);
}

private create_node(name: string) {
  var node = new Node(name);
  node.layer = Layers.Enum.UI_2D;
  // 添加widget组件,设置上下左右对齐和对齐模式
  var w: Widget = node.addComponent(Widget);
  w.isAlignLeft = w.isAlignRight = w.isAlignTop = w.isAlignBottom = true;
  w.left = w.right = w.top = w.bottom = 0;
  w.alignMode = 2;
  w.enabled = true;
  return node;
}

LayerManager主要管理的页面是:

  • LayerUI 用于管理主页面UI层
  • LayerPopUp 用于管理PopUp弹窗
  • LayerDialog 用于管理Dialog模式窗口,System系统窗口
  • LayerNotify 用于管理Notify提示

继承结构如下:

主界面
游戏层
引导层
PopUp弹窗
Toast消息
Dialog窗口/System窗口
LayerUI
Node
Game
Guide
LayerPopUp
LayerNotify
LayerDialog

然后我们看下打开窗口的逻辑处理,有助于后面示例的理解:

/*
@func: 同步打开一个窗口
@param: uiId 窗口唯一标识符ID
@param: uiArgs 页面参数,可以通过回调对象的onAdded或onRemoved回调获取
@param: callbacks 回调对象
*/
open(uiId: number, uiArgs: any = null, callbacks?: UICallbacks): void {
  var config = this.configs[uiId];
  if (config == null) {
    warn(`打开编号为【${uiId}】的界面失败,配置信息不存在`);
    return;
  }

  switch (config.layer) {
    case LayerType.UI:
      this.ui.add(config, uiArgs, callbacks);
      break;
    case LayerType.PopUp:
      this.popup.add(config, uiArgs, callbacks);
      break;
    case LayerType.Dialog:
      this.dialog.add(config, uiArgs, callbacks);
      break;
    case LayerType.System:
      this.system.add(config, uiArgs, callbacks);
      break;
  }
}

打开的逻辑处理其实很简单,从UI配置中获取配置数据,然后通过add设置不同窗口的显示逻辑。


示例

简单的示例,在上面有说过。在项目开发中,如果切换页面可以这样:

// 关闭当前页面
oops.gui.remove(UIID.Loading);
// 显示新的页面
oops.gui.open(UIID.UI_MAIN);

这样的处理方式主要是为了避免: 页面资源较多,切换页面时导致黑屏情况的出现。

框架针对于这种情况,通过页面回调的方式做了处理,主要定义是: UICallbacks

// ../oops-plugin-framework/assets/core/gui/layer/Defines.ts
export interface UICallbacks {
  // 节点添加到层级以后的回调,参数为当前页面节点,传递参数
  onAdded?: (node: Node, params: any) => void,
  // 窗口节点destroy之后回调,参数为当前页面节点,传递参数
  onRemoved?: (node: Node | null, params: any) => void,
  // 页面在移除的时候,进行的调用,可用于隐藏动画的显示,参数为当前页面节点,回调
  // 注意:如果调用`this.node.destroy()`,该回调将直接忽略
  onBeforeRemove?: (node: Node, next: Function) => void
}

注:这个接口的定义在页面参数传递或动画播放中使用很频繁。

弹窗示例

在框架的弹窗中, 虽有PopUp,Dialog,System的几种类型,但他们是类似的

  • PopUp 打开以后,支持非窗口区域透点,支持打开多个不同配置的弹窗
  • Dialog 仅支持显示一个,非窗口区域不可透点
  • SystemDialog类似,作者dgflash增加这个处理的原因主要是为了区别窗口提示的不同类型,比如客户端自身和服务器的提示,方便问题的定位。

增加一个窗口的UI预制体,如下图所示:
请添加图片描述

GameUIConfig.ts中增加配置后, 添加示例:

public openWindow(event, customData: string) {
  let params = {
    title: "窗口标题",
    content: "这是一段描述",
  }
  let callBack: UICallbacks = {
    onAdded: (node: Node, params: any) => {
      console.log("onAdded获取传递的参数:", params)
    },
    onRemoved:(node: Node | null, params: any) => {
      console.log("onRemoved获取传递的参数:", params)     
    }
  }
  oops.gui.open(UIID.UI_POPUP, params, callBack);
}

如果想在指定的页面中获取传入的参数,可以这样:

@ccclass('UIPop')
export class UIPop extends Component {
  @property(Label) titleLabel: Label = null;
  @property(Label) descLabel: Label = null; 
  private _okFunc = null;

  // 增加onAdded的回调,获取参数
  onAdded(args: any) {
    if (args) {
      this._okFunc = args.okFunc || null;
      this.titleLabel.string = args.title || "";
      this.descLabel.string = args.content || "未知错误";
    }
  }

  onClose() {
    if (this._okFunc) {
      this._okFunc();
    }
    oops.gui.removeByNode(this.node);
  }
}

一般弹窗的出现是需要有显示或隐藏动画的,我们可以通过回调方法:

  • onAdded 增加显示动画
  • onBeforeRemove 增加隐藏动画

动画的显示可以通过tween缓动系统或CocosCreator的Animation组件进行添加:

public clickSystem(event, customData: string) {
    console.log(customData);
    let params = {
      title: `系统窗口`,
      content: "数据异常",
    }
    oops.gui.open(UIID.UI_SYSTEM, params, this.getPopCommonEffect());
}

// 弹窗动画
private getPopCommonEffect(callbacks?: PopViewParams) {
	let newCallbacks: PopViewParams = {
		// 节点添加动画
    onAdded: (node, params) => {
      node.setScale(0.1, 0.1, 0.1);
      tween(node)
        .to(0.2, { scale: new Vec3(1, 1, 1) })
        .start();
    },
    // 节点删除动画
    onBeforeRemove: (node, next) => {
      tween(node)
        .to(0.2, { scale: new Vec3(0.1, 0.1, 0.1) })
        .call(next)
        .start();
    },
	}

	if (callbacks) {
    if (callbacks && callbacks.onAdded) {
      let onAdded = callbacks.onAdded;
      callbacks.onAdded = (node: Node, params: any) => {
        onAdded(node, params);
        newCallbacks.onAdded(node, params);
      };
    }

    if (callbacks && callbacks.onBeforeRemove) {
      let onBeforeRemove = callbacks.onBeforeRemove;
      callbacks.onBeforeRemove = (node, params) => {
        onBeforeRemove(node, params);
        newCallbacks.onBeforeRemove(node, params);
      };
    }
    return callbacks;
  }
  return newCallbacks;
}

注:作者在oops-frameworkTipsManager.ts中增加了更多的窗口示例,推荐查看学习

Toast示例

提示内容的显示就相对简单了,主要代码如下:

private _tipIndex: number = 0;

public clickTip(event, customData: string) {
  this._tipIndex++;
  // 参数:内容,是否使用多语言默认false
  oops.gui.toast(`这是第${this._tipIndex}个提示`);
}

总结

在框架中对界面的显示和隐藏主要逻辑如下:

  1. 页面的构建,继承于Component即可,如果需要获取参数,就增加 onAdded 方法
  2. GameUIConfig.ts中设置 UIID的唯一标识符ID 和 UIConfig 配置
  3. 页面的调用,使用openopenAsync;提示的显示使用Toast

最后注意:

  1. 任何页面的显示,不建议重复调用
oops.gui.open(UIID.UI_LAYER, {param: "参数"});
oops.gui.open(UIID.UI_LAYER, {param: "参数"});

注:框架会告知路径为【game/prefab/uiLayer】的预制重复加载

  1. PopUp的弹窗支持显示多个,指的是不同配置的Pop弹窗,原因1

感谢作者dgflash的分享,作者CSDN博客: dgflash CSDN

最后,祝大家学习和生活愉快!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1282069.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

leetcode 201 数字范围按位与

leetcode 201 题目题解代码 题目 给你两个整数 left 和 right ,表示区间 [left, right] ,返回此区间内所有数字 按位与 的结果(包含 left、right 端点)。 具体示例如下: 题解 本题是一个在思维上的方法,不…

HarmonyOS4.0系列——03、声明式UI、链式编程、事件方法、以及自定义组件简单案例

HarmonyOS4.0系列——03、声明式UI、链式编程、事件方法、以及自定义组件简单案例 声明式 UI ArkTS以声明方式组合和扩展组件来描述应用程序的UI,同时还提供了基本的属性、事件和子组件配置方法,帮助开发者实现应用交互逻辑。 如果组件的接口定义没有包…

Git:分布式版本控制系统的崛起与演变

简介 Git是一个开源的分布式版本控制系统,旨在有效、高速地处理从很小到非常大的项目版本管理。它是由Linus Torvalds于2005年创建的,最初是为了服务于Linux内核开发的版本控制需求。Git通过强大的分支功能、高效的缓存机制以及可扩展的架构设计&#xf…

实验六 单脉冲触发中断实验(汇编与微机原理)

实验目的: 掌握可编程中断控制器8259一般的使用方法。 掌握8259初始化的编程方法及中断服务程序的编写方法,中断程序的调试方法。 实验内容: 用单脉冲按钮的正脉冲输出作为中断控制器8259的中断源产生中断请求,在中断服务程序…

启动微服务idea控制台配置及样式

启动微服务idea控制台配置及样式 1. view —> tool windows —> services 2.控制台样式,下载插件 Grep Console ,可在设置中设置颜色

element 弹窗在弹出后鼠标还可以点击页面其他元素

文章目录 需求分析需求 如下图所示,在点击弹出弹框后,支持 鼠标可点击弹框外的其他地方可拖拽弹框弹出弹出后不可有遮挡弹出样式可自定义 分析 官网:https://vxetable.cn/v4/#/table/start/install 安装 vxe-table 引入import {App, createApp }

全球大模型发展整体态势,暗流涌动下的机遇

原创 | 文 BFT机器人 (一)大模推动能“涌现”,打开AI术发展上限 人工智能大模型,是指通过在海量数据上依托强大算力资源进行训练后能完成大量不同下游任务的模型。 在技术层面上,大模型的实现采用“预训练指令微调人类反馈的强化学习”的训练…

3款技术宅下载神器you-get,DownKyi,Hitomi-Downloader

今天在B站看到一个无水印素材视频,就想着下载下来。原来我一直用硕鼠的,但今天硕鼠官网访问不了。python小工具比较多,搜索一下发现几款不错的下载小工具,推荐给大家。 一、准备工作 很多时候我们要做视频处理,或者视…

记录 | Mac微信双开

目的:在 mac 上微信双开 (1) 先打开并登录第一个微信; 2)访达 -> 应用程序 -> 微信(双指同时摁)-> 显示包内容; 3)依次打开以下⽂件夹 Contents -> MacOS -> 双击 WeChat 即可…

Redis 安装部署

文章目录 1、前言2、安装部署2.1、单机模式2.1.1、通过 yum 安装(不推荐,版本老旧)2.1.1、通过源码编译安装(推荐) 2.2、主从模式2.3、哨兵模式2.4、集群模式2.5、其他命令2.6、其他操作系统 3、使用3.1、Java 代码 —…

开源数据大屏系统介绍

睿思BI数据大屏系统现已开源,通过拖拽配置的方式构建大屏,支持零代码开发。并且包含大量大屏模版,方便用户快速创建大屏应用。 系统主要包括数据准备、大屏设计、权限管理3个部分内容。 1.数据准备 1.1 创建数据源:定义BI系统链…

基于HTML 实现的示波器-含完整源码

完整资料下载连接 基于HTML 实现的示波器-含jshtmlcss完整源码 改源码是在桌面 PC 上设计的,分辨率为 1920 x 1080 像素,但宽高像素比为 1.4 到 1.6 的任何分辨率都将产生良好的图像。它适用于以下浏览器的最新版本:Internet Explorer、Edge、…

如何利用企业软件著作权查询API提升知识产权管理效率

引言 在当今数字化时代,企业的知识产权管理变得愈发重要。其中,软件著作权作为企业重要的知识产权之一,其保护和管理对于企业的创新和竞争力至关重要。为了更高效地进行软件著作权管理,许多企业开始采用先进的技术手段&#xff0…

初识谷歌chrome插件

谷歌插件想必各位都用过,使用广泛的vue-tools想必大家都不陌生吧,这就是谷歌插件。与其说是谷歌插件,倒不如说是浏览器插件,只是谷歌浏览器用的比较普遍罢了。所以这里就用谷歌插件代称吧。 1.何为插件 先来看下比较官方的定义&a…

Spring 向页面传值以及接受页面传过来的参数的方式

一、从页面接收参数 Spring MVC接收请求提交的参数值的几种方法: 使用HttpServletRequest获取。 RequestMapping("/login.do") public String login(HttpServletRequest request){ String name request.getParameter("name") String pa…

JVM性能调优理论与实践

内存模型 方法区,堆是所有线程共有。 栈,本地计数器是线程私有。 方法区 保存class文件加载后的类信息,常量池数据等 1.8后叫metaspace 会OOM,如动态加载类文件时: java.lang.OutOfMemoryError: PermGen space 堆 最大的内存…

22款奔驰GLE450升级香氛负离子 车载香薰功能

相信大家都知道,奔驰自从研发出香氛负离子系统后,一直都受广大奔驰车主的追捧,香氛负离子不仅可以散发出清香淡雅的香气外,还可以对车内的空气进行过滤,使车内的有害气味通过负离子进行过滤,达到车内保持清…

prometheus|云原生|轻型日志收集系统loki+promtail的部署说明

一, 日志聚合的概念说明 日志------ 每一个程序,服务都应该有保留日志,日志的作用第一是记录程序运行的情况,在出错的时候能够记录错误情况,简单来说就是审计工作,例如nginx服务的日志,kuber…

3D旋转tab图

上图 代码 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>3D旋转tab图</title><style>* {margin: 0;padding: 0;}body {height: 100vh;background: linear-gradient(to top, #29323c, #…

CRM选型:避免盲目跟风,要选最适合自己的!

CRM系统品牌繁多&#xff0c;各有优劣。对CRM系统不够了解的企业该如何选到适合的CRM系统&#xff1f;针对这个问题&#xff0c;我们就来聊聊&#xff0c;如何判定CRM系统是否适合自身企业&#xff1f; 一、综合性 CRM系统应该具有很好的综合性能&#xff0c;能够管理客户的整…