天天看點

cocos creator主程入門教程(二)—— 彈窗管理

五邑隐俠,本名關健昌,10年遊戲生涯,現隐居五邑。本系列文章以TypeScript為介紹語言。

我們已經知道怎樣制作、加載、顯示界面。但cocos沒有提供一個彈窗管理子產品,對于一個多人合作的項目,沒有統一的管理,界面層級容易混亂。作為主程,在項目開始就應該處理好這些問題,将彈窗劃分為不同的層次,不同類型的資訊顯示在不同的層中。下面将講解怎樣設計彈窗堆棧。

一般地,從下向上,我會将彈窗劃分為以下層:

1)内容層,展示遊戲相關的資訊界面。

2)tips層,顯示提示性資訊界面,例如獲得物品的浮窗、網絡異常的提示。

3)新手引導層,主要顯示新手引導的手指、新手提示文本框等。

4)alert層,主要顯示系統級的資訊、錯誤,例如斷網、被踢下線。

5)loading層,顯示加載動畫。

cocos creator主程入門教程(二)—— 彈窗管理

具體怎樣實作?彈窗通常有統一的動畫,是以定義一個界面邏輯的基類ViewCtrl,定義一些通用的屬性和方法。每個層中可能同時存在多個界面,我把每個層做成組ViewGroup。再寫一個類PopupCtrl,對界面分層,并對外提供程式設計接口。

先來說說ViewCtrl這個類,繼承自cc.Component,這樣我們寫的ViewCtrl子類就可以挂載到prefab的節點上。定義兩個boolean屬性:hasMask、touchOutClose,用于控制是否有灰色半透明遮罩,和是否點選彈窗外關閉。後面在介紹ViewGroup時會介紹怎樣實作這兩個功能。

cc.Component本身有onEnable,onDisable兩個生命周期方法,但我們希望同屏不出現太多彈窗,彈出新彈窗時隐藏上一個彈窗,這會導緻這兩個方法頻繁調用。對于打開界面時的重新整理,在界面放到堆棧時回調更合适。同理對重用的界面的重置,在界面移出堆棧時回調重置。可以在ViewCtrl定義onAddToStack和onRemoveFromStack兩個生命周期方法,在ViewGroup裡在合适的時機觸發,後面會介紹。再添加兩個方法,onPlayShowAni,onPlayHideAni,在這裡可以實作統一的彈窗動畫。子類的特殊顯示和關閉動畫由子類重寫這兩個方法實作。這兩個方法也由ViewGroup在合适的時機觸發。

/**
 * auth: 關健昌
 * date: 2018-11-17
 * desc: 界面基類
 * modify:
 */

const {ccclass, property} = cc._decorator;

@ccclass
export default class ViewCtrl extends cc.Component {

    @property
    hasMask: boolean = true;

    @property
    touchOutClose: boolean = false;

    public onAddToStack(): void {
     }

     public onRemoveFromStack(): void {
     }

     public onPlayShowAni(): void {
     }

     public onPlayHideAni(): void {
     }
}      

接下來是ViewGroup這個類,它代表一個彈窗層,也繼承自cc.Component,它的node可以添加到PopupCtrl的node上進而展示這個彈窗層。它應該有自己的maskLayer、blockLayer,用于顯示灰色半透明遮罩,和屏蔽下層界面的觸屏事件。當然,像tips層,我們不希望屏蔽下層界面的觸屏事件,可以提供接口來控制這兩個layer是否生效。

ViewGroup最重要的作用是管理一層的彈窗。是以它應該有一個Array<ViewCtrl>類型的viewArr屬性。基本的操作包括:

/**
 * auth: 關健昌
 * date: 2018-11-17
 * desc: 界面組
 * modify:
 */


export default class ViewGroup extends cc.Component {

     private maskLayer: cc.Node = null;
     private blockLayer: cc.Node = null;
     private viewArr: Array<ViewCtrl> = [];

     public pushView(ctrl: ViewCtrl, hideOld: boolean): void {
     }

     public popView(cleanup: boolean): void {
     }

     public insertView(ctrl: ViewCtrl): void {
     }

     public removeView(ctrl: ViewCtrl): void {
     }

     public pushViews(ctrls: Array<ViewCtrl>, hideOld: boolean): void {
     }

     public removeAllViews(cleanup: boolean): void {
     }

     public lastView(): ViewCtrl {
     }

     public getViewByName(name: string): ViewCtrl {
     }

     public getViewCount(): number {
     }

     public isEmpty(): boolean {
     }
}      

其中pushView、insertView、pushViews會将對應ViewCtrl放入viewArr,并觸發ViewCtrl.onAddToStack。通過ViewGroup.node.addChild将ViewCtrl.node添加為子節點将對應界面顯示出來。具體是否要添加到界面要看是否在hideOld的界面下面。pushViews主要是為自動彈窗設計的,例如登入後自動顯示公告、簽到等,關閉一個自動打開下一個。

popView、removeView、removeAllViews通過ViewCtrl.node.removeFromParent将ViewCtrl.node移出界面,同時将ViewCtrl移出viewArr,并觸發ViewCtrl.onRemoveFromStack。pushView、popView還會觸發onPlayShowAni,onPlayHideAni這兩個生命周期方法。

現在來說說PopupCtrl這個類,它也繼承自cc.Component,可以直接挂載到prefab的節點上,在介紹遊戲入口時我們給Canvas添加了popupLayer子節點,通過添加元件将PopupCtrl挂上去。PopupCtrl要實作分層,它有Array<ViewGroup>類型的groupArr屬性。在onLoaded生命周期方法裡按彈窗層順序,通過PopupCtrl.addChild添加對應的彈窗層。PopupCtrl提供跟ViewGroup類似的接口,不同的是PopupCtrl的pushView、insertView、pushViews提供layer參數,用于指定彈窗添加的層。

enum PopupLayer {
    CONTENT = 0,
    TIPS,
    GUIDE,
    ALERT,
    LOADING
}      

彈窗管理先說到這裡,下一篇我們将介紹下怎樣做資源加載管理。

繼續閱讀