经常遇到如下的需求
鼠标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
原文:http://www.cnblogs.com/zuibunan/p/3915291.html