mail 曾经最牛B的方法;

本文详细介绍了游戏客户端中邮件系统的实现细节,包括模块初始化、UI布局加载、事件监听及响应等。通过具体代码展示了如何处理邮件加载、滚动加载更多邮件、邮件打开与删除等功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

-----------------------------------------------------
-- Module Mail
-- Dialog视图模板
-----------------------------------------------------
module( "Mail",package.seeall )
setmetatable(Mail,{__index = dialog_t})


---------------------------实例变量--------------------------
local instance = nil
local NUM_PER_PAGE_0 = 10 --初始化时加载的个数
local NUM_PER_PAGE = 5 --滑到底后加载的新页数
local MAX_GIFT_NUM = 4 --最多奖励MAX_GIFT_NUM个奖品
local LOAD_INTERVAL = 0.5 -- 加载一个新的item的时间间隔
local MARGIN = 0 


----------------------------实例的创建与销毁-------------------------                索引用 iXyz 形式 , i = index 
function getInstance()
    instance = instance or new()
    return instance
end


function destroyInstance()
    if instance then
        instance:dispose()
        instance = nil
    end
end


-----------------------------------------------------
function new()
    local this = {}
    setmetatable(this,{__index = Mail})
    this:init()
    return this
end


------------------------------实例的UI初始化-----------------------
function init(self)
    dialog_t.init(self)


    self._name = "Mail"
    self._layout = Global.getInstance():loadUI("", self._name)


    self._core:addChild(self._layout)


    self:initRegister()
end


-------------------------------实例UI对象的初始化与绑定----------------------
function controlRegister(self)


--    self.xxxx = Global.getInstance():getUINodeLoopByName(self._layout, "xxxx")
--
--    self.xxxx_list = Global.getInstance():getUINodeLoopByName(self._layout, "xxxx_list")
--    self.xxxx_list:setBounceEnabled(true)
--    self.xxxx_list:setItemsMargin(4.0)
--    self.xxxx_list:setItemModel(Global.getInstance():loadUI("", "xxxx_item"))
--
--    Global.getInstance():UIEventRegister("ended", self._name, self.xxxx, "btnxxxx")


    self.lsv_main = Global.getInstance():getUINodeLoopByName(self._layout, "ListView_1")
    self.lsv_main:setItemsMargin(MARGIN)
    --self.lsv_main:setBounceEnabled(true) 
    
    self.lsv_main:addScrollViewEventListener(ListScrollViewEvent)
    self.inner = self.lsv_main:getInnerContainer()
      local itemLayer = Global.getInstance():loadUI("", "MailCell")
      local itemModel = Global.getInstance():getUINodeLoopByName(itemLayer, "pnl_main")
      self.lsv_main:setItemModel(itemModel)
      self.item_width = itemModel:getContentSize().width
      self.item_height = itemModel:getContentSize().height
    self.btn_delete = Global.getInstance():getUINodeLoopByName(self._layout, "Button_2")
    self.btn_deleteAll = Global.getInstance():getUINodeLoopByName(self._layout, "Button_3")
    self.btn_back = Global.getInstance():getUINodeLoopByName(self._layout, "Button_12")
    self.txt_title = Global.getInstance():getUINodeLoopByName(self._layout, "Text_4")
    self.txt_content = Global.getInstance():getUINodeLoopByName(self._layout, "Text_5")
    self.img_1 = Global.getInstance():getUINodeLoopByName(self._layout, "Image_9")
    self.img_2 = Global.getInstance():getUINodeLoopByName(self._layout, "Image_10")
    self.img_3 = Global.getInstance():getUINodeLoopByName(self._layout, "Image_11")
    self.btn_get = Global.getInstance():getUINodeLoopByName(self._layout, "Button_5")
    
    --注册一堆事件
    Global.getInstance():UIListEventRegister("ended", self._name, self.lsv_main, "ClickMailItem")    
    Global.getInstance():UIEventRegister("ended", self._name, self.btn_delete, "Btn_delete")
    Global.getInstance():UIEventRegister("ended", self._name, self.btn_deleteAll, "Btn_deleteAll")
    Global.getInstance():UIEventRegister("ended", self._name, self.btn_back, "Btn_back")
    Global.getInstance():UIEventRegister("ended", self._name, self.btn_get, "Btn_get")
    
    
    local function load()
        self:load_next_items_0(1)
    end
    local function onTouchBegan(touch, event)
        self.delY = 0 
        return true
    end
    local function onTouchMoved(touch, event)
        self.delY = touch:getLocation().y - touch:getPreviousLocation().y
        if self.delY < 0 then       --加载新item时,弹性消失
            if self.handle ~= nil then
                self:unschedule('handle')
            end
        elseif self.delY > 0 then --防止原地点击卡
            if self.now_count ~= #self.data and self.handle == nil then
                self.handle = self:scheduleInfinite(load, LOAD_INTERVAL)
            end 
        end
    end
    local function onTouchEnded(touch, event) 
        
    end


    self.listener1 = cc.EventListenerTouchOneByOne:create()
    self.listener1:registerScriptHandler(onTouchBegan,cc.Handler.EVENT_TOUCH_BEGAN )
    self.listener1:registerScriptHandler(onTouchMoved,cc.Handler.EVENT_TOUCH_MOVED )
    self.listener1:registerScriptHandler(onTouchEnded,cc.Handler.EVENT_TOUCH_ENDED )
    cc.Director:getInstance():getEventDispatcher():addEventListenerWithFixedPriority(self.listener1, -1)
    
    --没有默认打开邮件,因为邮件有打开状态,需要玩家点击
    self:SetContentVisible(false)
    if GlobalData.mailNotDeleteSum == 0 then
        self.btn_deleteAll:setTouchEnabled(false)
    end
    
end


----------------------------消息注册-------------------------
function messageRegister(self)
-- self.listener11 = Global.getInstance():UIMessageRegister("xxxx", self._name)
end


-----------------------------消息清除------------------------
function messageUnRegister(self)
-- Global.getInstance():UIMessageUnRegister(self.listener11)
end


------------------------------消息触发回调-----------------------
function onMessage(self, name, data)
    if "xxxx" == name then


    elseif "" == name then


    end
end


---------------------------通知注册--------------------------
function noticeRegister(self)
-- self.notice = Global.getInstance():UINoticeRegister("xxxx", self._name)
end


----------------------------通知清除-------------------------
function noticeUnRegister(self)
-- Global.getInstance():UINoticeUnRegister(self.notice)
end


-----------------------------通知触发回调------------------------
function onNotice(self, name, data)
    if "xxxx" == name then


    elseif "" == name then


    end
end


-----------------------------初始化------------------------
function initRegister(self)
    self:controlRegister()
    self:messageRegister()
    self:noticeRegister()
end


function releaseRegister( self )
    self:messageUnRegister()
    self:noticeUnRegister()
end


-----------------------------场景开始载入回调------------------------
function onEnter(self)
    print(self._name .. " => " .. "onEnter")


    self.now_count = 0 --current num
    self.data = UserData.player.mails
    table.sort(self.data,MailCpr)
    self.config = Configs.M("Mail"):get()
    self.can_load = true
    local function load()
        self:load_next_items_0(1) --非setPosition方式
    end
    self.handle = self:scheduleInfinite(load, LOAD_INTERVAL)
    self:load_next_items(NUM_PER_PAGE_0) --setPosition方式
end


------------------------------场景清除回调-----------------------
function onExit(self)
    print(self._name .. " => " .. "onExit")
    if self.handle ~= nil then
        self:unschedule('handle')
    end
    if self.handle_can_load ~= nil then
        self:unschedule('handle_can_load')
    end
    if self.handle_inner_pos ~= nil then
        self:unschedule('handle_inner_pos')
    end
    if self.listener1 ~= nil then --有内置的self.listener!
        cc.Director:getInstance():getEventDispatcher():removeEventListener(self.listener1)
        self.listener1 = nil
    end
end


-------------------------------实例销毁----------------------
function dispose(self)
    self:releaseRegister()
    if self._core then
        self._core:removeFromParent(true)
        self._core = nil
    end
    dialog_t.dispose(self)
end


--------------------------------UI刷新---------------------
function refreshUI(self)


end
function refreshData(self)


end
-----------------------------------------------------




function ListScrollViewEvent(sender, evenType)
    local self = getInstance()
    local function set_can_load()
        self.can_load = true 
        self.inner:setPosition(self.x_record, self.y_record)
    end
--    local function set_inner_pos()
--        self.inner:setPosition(self.x_record, self.y_record)
--    end
    if evenType == ccui.ScrollviewEventType.scrollToBottom then
        print("BOTTOM")
        if self.now_count~= #self.data and self.can_load then
            self.can_load = false
            self.lsv_main:jumpToBottom()
            self.handle_can_load = self:scheduleOnce(set_can_load, 0, 'handle_can_load') --scheduler.lua在main里
            --self.handle_inner_pos = self:scheduleOnce(set_inner_pos, 0, 'handle_inner_pos')
            self:load_next_items(NUM_PER_PAGE) --setPosition方式
        end
    elseif evenType ==  ccui.ScrollviewEventType.scrollToTop then 
        print("TOP" )
    end
end


function load_next_items_0(self, num) --非setPosition的自然方式
    local bound = math.min(#self.data, self.now_count + num)
    local start = self.now_count + 1
    self.now_count = bound
    for i = start, bound do
        self.lsv_main:pushBackDefaultItem() 
        local item = self.lsv_main:getItem( i - 1)
        local item_name = Global.getInstance():getUINodeLoopByName(item, "Text_1")
        item_name:setString(self.data[i].id)
    end
    if self.now_count == #self.data then
        if self.handle ~= nil then
            self:unschedule('handle')
        end
    end
end


function load_next_items(self, num) --初始加载用setPosition设置inner位置,接着动态加载则只能自然加载,不能用setPosition
print("load_next_items____" .. self.now_count)
    local bound = math.min(#self.data, self.now_count + num)
    local start = self.now_count + 1
    self.now_count = bound
    local inner_delY = 0
    for i = start, bound do
        self.lsv_main:pushBackDefaultItem()  --系统不会立即更新self.inner的position
        inner_delY = inner_delY - (self.item_height + MARGIN)
        local item = self.lsv_main:getItem( i - 1)
        local item_name = Global.getInstance():getUINodeLoopByName(item, "Text_1")
        item_name:setString(self.data[i].id)
    end
    local y = self.inner:getPositionY()
    self.inner:setPosition(0, y + inner_delY)
    self.x_record, self.y_record = self.inner:getPosition()
    if self.now_count == #self.data then
        if self.handle ~= nil then
            self:unschedule('handle')
        end
    end
end




function btnXXXX(self, sender, param)
    
end




--打开一个邮件做好没那么简单,1:只用在第一次打开发送消息, 2:如果发消息网络出错怎么办
function ClickMailItem(self,sender, eventType)


    --如果第一次打开邮件发生异常,self.iFoc 要还原;第 >1 次 打开邮件不用发消息,不会发生异常
    local j = sender:getCurSelectedIndex()  --focus of now selected item. 
    local item = self.lsv_main:getItem(j)
    --用i临时代替 self.iDat, 万一第一次代开邮件返回异常则self.iDat不受影响
    local i = j + 1
    --如果当前邮件没打开过,就向服务器发次消息
    if self.data[i].isNotOpen == 1 then -- i(self.iDat)是data中索引, iConf是config中索引
        --如果服务器未返回等类似异常则不进行任何操作
        Requests.getInstance():send("Mail_Open",{id = self.data[i].id},function (data) 
            self.data[i].isNotOpen = 0
            self.iFoc = j
            self.iDat = i  
            self:ClickMailItem2()
        end)
    else
        self.iFoc = j
        self.iDat = i  
       self:ClickMailItem2()
    end
end
--上面 ClickMailItem中有两处相同的设置UI
function ClickMailItem2(self )
print("clickmailitem2 enter") 
    self.iConf = MailCode2Index[tostring(self.data[self.iDat].code)] -- config 中的第iConf项
    --设置右边内容 ,  选中一个item后所有内容的显示无需服务器数据(正常)返回,向服务器发数据仅为了设置 isNotOpen
    local content = self.config[self.iConf].content
    self.txt_content:setString(content) -- for test
    self:SetContentVisible(true)
--    for j = 1, MAX_GIFT_NUM do
--        if self.data['code' .. j] == nil then
--            self["img_" .. j]:setVisible(false)
--        else
--        -- self.img_1 ..
--        --奖品设置 ,self.config[iConf].   code , num ,再对应到goods表
--        --self["img_" .. j]:setVisible(true)
--        end
--    end
end




--注意:  self.data[i].isNotOpen = -1 表示已经删除了
function Btn_delete(self, sender, param)-- 这里的sender是btn 不是lsv
    -- 发消息
    print("btn_delete enter ".. self.iDat)
    Requests.getInstance():send("Mail_Delete",{id = self.data[self.iDat].id},function (data) 
        print("Btn_delete back")
        self:SetContentVisible(false)
        self.lsv_main:removeItem (self.iFoc)
        -- 不知道有没有listview 长度的 api
        --更新GlobalData里的数据和 self.data里的数据
        --self.data[self.iDat].isNotOpen = -1
        GlobalData.mailNotDeleteSum = GlobalData.mailNotDeleteSum - 1
        if GlobalData.mailNotDeleteSum == 0 then 
            self.btn_deleteAll:setTouchEnabled(false) -- btn_deleteAll 不能点
        end
        if self.config[self.iConf][code1] ~= nil and self.data[self.iDat].isNotGot == 1 then --无论邮件打没打开都可能没领取奖励
            GlobalData.mailNotGotSum = GlobalData.mailNotGotSum - 1
        end
        --最后remove 掉
        table.remove(self.data,self.iDat)
        
        self.now_count = self.now_count - 1  --注意
    end)
end


function Btn_deleteAll(self, sender, param)
    print("Delete___ALL")
    if GlobalData.mailNotGotSum ~= 0 then
    -- 这里首先要弹出“是否删除全部” 提示框  ,以下注释内容在提示框确定后运行
    --发消息    
    else
        Requests.getInstance():send("Mail_DeleteAll",{ x = 0 },function (data) -- x = 0 是随便传递的,否则不能发送只有MessageId的信息 
            self:SetContentVisible(false)
            self.btn_deleteAll:setTouchEnabled(false)
              self.lsv_main:removeAllChildren()
              --把self.data里的设置就行, GlobalData里的可以不用管
              for i = 1, #self.data do -- 每次删第一处元素
                    table.remove(self.data,1)
              end
        end)
    end
    GlobalData.mailNotGotSum = 0 -- 再次进来要考这个判断btn_deleteAll的状态
end


function Btn_back(self, sender, param)
    Dialogs.getInstance():closeDialog(self._name);
end


function Btn_get(self, sender, param)
    --btn设置下状态,发消息
    Requests.getInstance():send("Mail_Got",{id = self.data[self.iDat].id},function (data) 
        --领取按钮变化
    end)
end


function SetContentVisible(self , b) --  b = true or false
    self.txt_title:setVisible(b)
    self.txt_content:setVisible(b)
    self.img_1:setVisible(b)
    self.img_2:setVisible(b)
    self.img_3:setVisible(b)
    self.btn_get:setVisible(b)
    self.btn_delete:setTouchEnabled(b)
    
    self.btn_get:setTouchEnabled(b) -- 如果邮件content看不了,delete btn 也是不能点的 , deleteAll btn单独考虑
    
end






--每次进来都要排序
function MailCpr(a , b)
    if a.isNotOpen == b.isNotOpen then
        return a.receiveTime > b.receiveTime
    else
        return a.isNotOpen > b.isNotOpen
    end
end
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值