首页 > 代码库 > 使用xlue实现tips

使用xlue实现tips

经常遇到如下的需求

鼠标hover到目标对象一定时间后,弹出tips或者窗口;

鼠标离开目标对象一定时间后,隐藏tips或者窗口;

鼠标从目标对象移动到弹出的窗口上,这种状况下不隐藏窗口;

 

考虑到这种需求,绘制如下的状态图:

未命名图片

如上图所示,将tips的状态分为hide,showing,show,hiding,enter 五个状态;

hide: tips没有显示

showing: 准备显示tips

show: 显示tips

hiding: 准备隐藏tips

enter: 鼠标进入了tips控件,这种状况下仍然显示 tips

 

使用上面的状态图,清晰地描述了tips可能存在的各种状态,并确定了驱动事件有哪些。理清了思路。

hide状态时:hover到目标控件会进入 showing 状态;

showing 状态时:离开目标控件会返回到 hide 状态;

进入 showing 状态后,开启一个timer,当timer结束后,如果仍然是 showing 状态,则转到 show 状态并显示tips

show 状态时:离开目标控件会进入hiding状态;

hiding 状态时:hover到目标控件会返回到 show 状态;

进入 hiding 状态后,开启一个timer,当timer结束后,如果仍然是 hiding 状态,则转到 hide 状态并隐藏tips

鼠标从目标控件移动到tips上,会使得状态从 show 转到 hiding 转到 enter, 此时tips仍然显示,当离开tips控件后,状态又转移回 hiding ,此时开启一个timer,timer结束后,同样根据是否仍然是 hiding 状态来隐藏tips

 

编程实现:

function AddWindowTip(tippedObj, text, callback)    local function showTipsFunc(tippedObj, x, y)        -- 创建tips窗口        local hostwndId = "TipsHelper.TipsHostWnd.Instance." .. tippedObj:GetID()        local objtreeId = "TipsHelper.TipsTree.Instance." .. tippedObj:GetID()        local hostwndTemplateId = "TipsWndTemplate"        local objtreeTemplateId = "TipsTreeTemplate"        local hostwndManager = XLGetObject("Xunlei.UIEngine.HostWndManager")        local hostwnd = hostwndManager:GetHostWnd(hostwndId)        if hostwnd then            local objtree = hostwnd:GetBindUIObjectTree()            if objtree then                hostwnd:UnbindUIObjectTree()                local objtreeManager = XLGetObject("Xunlei.UIEngine.TreeManager")                objtreeManager:DestroyTree(objtree)            end            hostwndManager:RemoveHostWnd(hostwndId)        end        local templateManager = XLGetObject("Xunlei.UIEngine.TemplateManager")        local wndTemplate = templateManager:GetTemplate(hostwndTemplateId, "HostWndTemplate")        if not wndTemplate then            return        end        local hostwnd = wndTemplate:CreateInstance(hostwndId)        if not hostwnd then            return        end        local objtreeTemplate = templateManager:GetTemplate(objtreeTemplateId, "ObjectTreeTemplate")        local objtree = objtreeTemplate:CreateInstance(objtreeId)        if not objtree then            return        end        hostwnd:BindUIObjectTree(objtree)        hostwnd:Create()        -- 设定text        local rootObj = objtree:GetRootObject()        local textObj = objtree:GetUIObject("text")        textObj:SetText(text)        local width, height = textObj:GetTextExtent()        textObj:SetObjPos(4,3,width,height)        width,height = width + 8, height + 6        rootObj:SetObjPos(0,0,width+8,height+6)                -- 移动窗口位置        local tippedOwner = tippedObj:GetOwner()        local tippedHostWnd = tippedOwner:GetBindHostWnd()        local l,t,r,b = tippedObj:GetObjPos()        local left = l+(r-l-width)/2        local top = b        left,top = tippedHostWnd:HostWndPtToScreenPt(left,top)        hostwnd:Move(left,top,width,height)                return rootObj    end    local function hideTipsFunc(tippedObj)        -- 销毁tips窗口        local hostwndId = "TipsHelper.TipsHostWnd.Instance." .. tippedObj:GetID()        local hostwndManager = XLGetObject("Xunlei.UIEngine.HostWndManager")        local hostwnd = hostwndManager:GetHostWnd(hostwndId)        if not hostwnd then            return        end                local objtree = hostwnd:GetBindUIObjectTree()        if objtree then            hostwnd:UnbindUIObjectTree()            local objtreeManager = XLGetObject("Xunlei.UIEngine.TreeManager")            objtreeManager:DestroyTree(objtree)        end        hostwndManager:RemoveHostWnd(hostwndId)                return true    end        -- state: tip 的状态, hide隐藏,showing正在显示,show显示,hiding正在隐藏,enter进入tips中    local state = "hide"    -- 使用状态控制 tips 在各个状态间转换    tippedObj:AttachListener("OnMouseMove", true, function(obj, x, y, flags)        if state == "hide" then            state = "showing"            local timerMgr = XLGetObject("Xunlei.UIEngine.TimerManager")            timerMgr:SetOnceTimer(function()                if state == "showing" then                    local tipsObj = showTipsFunc(obj, x, y)                    if tipsObj then                        state = "show"                                                --[[ 这段代码,使得移动到弹出的窗口上时,窗口不会被隐藏                        tipsObj:AttachListener("OnMouseMove", true, function()                            if state == "hiding" then                                state = "enter"                            end                        end)                        tipsObj:AttachListener("OnMouseLeave", true, function()                            if state == "enter" then                                state = "hiding"                                local timerMgr = XLGetObject("Xunlei.UIEngine.TimerManager")                                timerMgr:SetOnceTimer(function()                                    if state == "hiding" then                                        if hideTipsFunc(obj) then                                            state = "hide"                                            if callback and type(callback) == "function" then                                                callback(tippedObj, false)                                            end                                        end                                    end                                end, 300)                            end                        end)                        --]]                                                if callback and type(callback) == "function" then                            callback(obj, true)                        end                    end                end            end, 300)        elseif state == "hiding" then            state = "show"        end    end)    tippedObj:AttachListener("OnMouseLeave", true, function(obj, x, y, flags)        if state == "show" then            state = "hiding"            local timerMgr = XLGetObject("Xunlei.UIEngine.TimerManager")            timerMgr:SetOnceTimer(function()                if state == "hiding" then                    if hideTipsFunc(obj) then                        state = "hide"                        if callback and type(callback) == "function" then                            callback(tippedObj, false)                        end                    end                end            end, 300)        elseif state == "showing" then            state = "hide"        end    end)    end