Lua设计模式
3006字约10分钟
2024-10-30
实用
柯里化
function curry(func, num_args)
num_args = num_args or debug.getinfo(func, "u").nparams
if num_args < 2 then return func end
local function helper(argtrace, n)
if n < 1 then
return func(unpack(flatten(argtrace)))
else
return function (...)
return helper({argtrace, ...}, n - select("#", ...))
end
end
end
return helper({}, num_args)
end
function flatten(t)
local ret = {}
for _, v in ipairs(t) do
if type(v) == 'table' then
for _, fv in ipairs(flatten(v)) do
ret[#ret + 1] = fv
end
else
ret[#ret + 1] = v
end
end
return ret
end
命名参数
Lua 的函数调用 传递实参的时候允许 采用表传递
rename{old="temp.lua", new="temp1.lua"}
function rename (arg)
return os.rename(arg.old, arg.new)
end
迭代器设计
-- 迭代器设计
do
function ListIter(t)
local i = 0
local n = #t
return function()
i = i + 1
if i <= n then return t[i] end
end
end
Itmes = { 1, 2, 3, 4, 5 }
for item in ListIter(Itmes) do
print(item)
end
end
元表操作
Lua 的元表操作
操作重载
- 加法:
- 元表中
__add
方法可以重新定义两个表相加的行为。 - 例如,你可以定义两个表的加法为将两个表的所有元素合并成一个新表。
- 代码示例:
local mt = { __add = function(a, b) local result = {} for k, v in pairs(a) do result[k] = v end for k, v in pairs(b) do result[k] = v end return result end } local table1 = { a = 1, b = 2 } local table2 = { c = 3, d = 4 } setmetatable(table1, mt) local combined_table = table1 + table2 -- 会将两个表合并 print(combined_table.a, combined_table.b, combined_table.c, combined_table.d) -- 输出: 1 2 3 4
- 元表中
- 乘法:
- 元表中
__mul
方法可以重新定义表与数字相乘的行为。 - 例如,你可以定义表与数字相乘为将表中所有元素都乘以该数字。
- 代码示例:
local mt = { __mul = function(a, b) local result = {} for k, v in pairs(a) do result[k] = v * b end return result end } local table1 = { a = 1, b = 2 } setmetatable(table1, mt) local multiplied_table = table1 * 2 -- 将 table1 中的元素都乘以 2 print(multiplied_table.a, multiplied_table.b) -- 输出: 2 4
- 元表中
- 字符串连接:
- 元表中
__concat
方法可以重新定义表与字符串连接的行为。 - 例如,你可以定义表与字符串连接为将表中的所有元素以字符串形式连接起来。
- 代码示例:
local mt = { __concat = function(a, b) local str = "" for k, v in pairs(a) do str = str .. tostring(v) end return str .. b end } local table1 = { 1, 2, 3 } setmetatable(table1, mt) print(table1 .. "Hello") -- 输出: 123Hello
- 元表中
- 比较:
- 元表中
__lt
,__le
,__eq
,__ge
,__gt
方法可以重新定义表的比较行为。 - 例如,你可以定义两个表的比较基于它们的某个属性的值。
- 代码示例:
local mt = { __lt = function(a, b) return a.value < b.value end } local table1 = { value = 1 } local table2 = { value = 2 } setmetatable(table1, mt) setmetatable(table2, mt) print(table1 < table2) -- 输出: true
- 元表中
访问控制
- 只读:
- 元表中
__newindex
方法可以设置只读属性。 - 将
__newindex
设置为 nil,任何对该表元素的赋值操作都会失败。 - 代码示例:
local mt = { __newindex = nil } -- 设置为 nil 表示只读 local table1 = { a = 1, b = 2 } setmetatable(table1, mt) table1.a = 3 -- 赋值操作将会失败,不会修改 table1 print(table1.a) -- 输出: 1
- 元表中
- 特定访问权限:
- 你可以将
__newindex
方法设置为一个函数,来控制对表的赋值操作。 - 在函数中,你可以根据需要设置访问权限。
- 代码示例:
local mt = { __newindex = function(t, k, v) if k == "secret" then error("You don't have access to this data") else rawset(t, k, v) end end } local table1 = { a = 1, secret = "Hidden Value" } setmetatable(table1, mt) table1.a = 3 -- 可以修改 table1.secret = "New Value" -- 会报错 print(table1.secret) -- 输出: Hidden Value (因为修改失败)
- 你可以将
自定义索引
- 使用字符串作为键:
- 元表中
__index
方法可以重新定义访问表元素的方式。 - 你可以使用字符串作为键来访问表元素,而不是传统的数字索引。
- 代码示例:
local mt = { __index = function(t, k) if k == "name" then return "John Doe" elseif k == "age" then return 30 end end } local table1 = {} setmetatable(table1, mt) print(table1.name) -- 输出: John Doe print(table1.age) -- 输出: 30
- 元表中
- 使用函数作为键:
- 你可以将函数作为键来访问表元素,这样可以实现更灵活的访问逻辑。
- 在
__index
方法中,你可以根据函数参数来返回不同的值。 - 代码示例:
local mt = { __index = function(t, key) if type(key) == "function" then return key(t) else return rawget(t, key) end end } local table1 = { name = "John Doe" } setmetatable(table1, mt) local get_name = function(t) return t.name end print(table1[get_name]) -- 输出: John Doe
垃圾回收控制
- 元表中
__gc
方法可以用来定义在表被垃圾回收时执行的操作。 - 例如,你可以使用
__gc
方法来释放表所占用的资源,或进行其他必要的清理工作。 - 代码示例:
local mt = { __gc = function(t) print("Table " .. tostring(t) .. " is being garbage collected.") end } local table1 = { a = 1, b = 2 } setmetatable(table1, mt) table1 = nil -- 将 table1 设置为 nil,以便触发垃圾回收 -- 当 Lua 进行垃圾回收时,会执行 __gc 方法,打印信息
希望这个解释能帮助你更好地理解 Lua 中元表的应用。如果你还有其他问题,请随时提问!
全局表载入-1
-- 创建ktool表
local ktool = {}
-- 系统功能
ktool.System = {
GetStoragePath = function()
return Environment.getExternalStorageDirectory().toString()
end,
GetScreenWidth = function()
return activity.getWidth()
end,
GetScreenHeight = function()
return activity.getHeight()
end,
GetPackageName = function()
return activity.getPackageName()
end,
GetNowTime = function()
return os.date("%Y-%m-%d %H:%M:%S")
end
}
-- 文件操作
ktool.File = {
FileExists = function(id)
import ""
return File(id).exists()
end
}
-- 控件操作
ktool.View = {
Nconceal = function(id)
id.setVisibility(0)
end,
Conceal = function(id)
id.setVisibility(8)
end,
RedidView = function(view, InsideColor, radiu)
local drawable = GradientDrawable()
drawable.setShape(GradientDrawable.RECTANGLE)
drawable.setColor(InsideColor)
drawable.setCornerRadii({ radiu, radiu, radiu, radiu, radiu, radiu, radiu, radiu })
view.setBackgroundDrawable(drawable)
end,
RedidViewTwo = function(view, InsideColor, radiu)
local drawable = GradientDrawable()
drawable.setShape(GradientDrawable.RECTANGLE)
drawable.setColor(InsideColor)
drawable.setCornerRadii({ radiu, radiu, 0, radiu, 0, radiu, radiu, radiu })
view.setBackgroundDrawable(drawable)
end
}
-- 数据缓存
ktool.Cache = {
SaveCacheData = function(filname, title, str)
local sp = activity.getSharedPreferences(filname, Context.MODE_PRIVATE)
local sped = sp.edit()
sped.putString(title, str)
sped.commit()
end,
GetCacheData = function(filname, title)
local sp = activity.getSharedPreferences(filname, Context.MODE_PRIVATE)
return sp.getString(title, "")
end,
UseHook = {
read = function(key)
return ktool.Cache.GetCacheData("tmp", key)
end,
save = function(key, value)
ktool.Cache.SaveCacheData("tmp", key, value)
end
}
}
-- 网络操作
ktool.Network = {
OpenWIFI = function()
local wifi = activity.Context.getSystemService(Context.WIFI_SERVICE)
wifi.setWifiEnabled(true)
end,
CloseWIFI = function()
local wifi = activity.Context.getSystemService(Context.WIFI_SERVICE)
wifi.setWifiEnabled(false)
end,
CloseNetWork = function()
local wifi = activity.Context.getSystemService(Context.WIFI_SERVICE)
wifi.disconnect()
end
}
-- 页面跳转
ktool.Navigation = {
SkipPage = function(viewPath)
local skipPath = activity.getLuaDir()
if not string.find(viewPath, "[.]") then
skipPath = skipPath .. "/" .. viewPath
else
local parts = {}
for part in string.gmatch(viewPath, "[^%.]+") do
table.insert(parts, part)
end
local newPath = table.concat(parts, "/")
skipPath = skipPath .. "/" .. newPath
end
activity.newActivity(skipPath, android.R.anim.fade_in, android.R.anim.fade_out)
end,
GoToPage = function(na)
activity.newActivity(na)
end,
GoToMainPage = function()
activity.newActivity("main")
end
}
-- 注册到全局表
_G.ktool = ktool
全局表载入-2
-- 工具模块的实现
local ktool = {
__beforeMount = false
}
ktool.__index = ktool
-- 单例存储
local instance
function ktool:loadBaseModule()
require "import"
import "android.app.*"
import "android.os.*"
import 'android.view.*'
-- 窗口
import 'android.widget.*'
import 'android.widget.LinearLayout'
import 'android.widget.ImageView'
import 'android.widget.Space'
-- 动画
import "android.animation.ObjectAnimator"
import "android.animation.ArgbEvaluator"
import "android.view.animation.Animation"
import "android.view.animation.RotateAnimation"
import "android.view.animation.AlphaAnimation"
import "android.view.animation.TranslateAnimation"
-- 上下文
import "android.net.Uri"
import 'android.content.Intent'
import "android.content.Context"
import "android.content.res.ColorStateList"
-- 设计
import 'android.graphics.*'
import "android.graphics.RectF"
import "android.graphics.Paint"
import 'android.graphics.Typeface'
import "android.graphics.drawable.Drawable"
import 'android.graphics.drawable.ClipDrawable'
import 'android.graphics.drawable.LayerDrawable'
import "android.graphics.drawable.ShapeDrawable"
import "android.graphics.drawable.ColorDrawable"
import "android.graphics.drawable.GradientDrawable"
import 'android.graphics.drawable.StateListDrawable'
import "android.graphics.drawable.shapes.RoundRectShape"
-- 文本输入
import 'android.text.InputType'
import "android.text.Spannable"
import "android.text.SpannableString"
import "android.text.style.ForegroundColorSpan"
-- 自定义类库
import "cjson"
import "java.io.File"
import "java.net.URLEncoder"
import "android.graphics.PixelFormat"
import "android.content.Context"
import "android.provider.Settings"
import "java.io.FileInputStream"
import "android.graphics.BitmapFactory"
import "android.graphics.drawable.BitmapDrawable"
end
-- 埋点记录函数
function ktool:trackEvent(event, data)
local logData = {
event = event,
data = data or {}
}
print("Tracking event:", logData.event)
for k, v in pairs(logData.data) do
print(" ", k, ":", v)
end
end
function ktool:onBeforeMount(func)
self.__beforeMount = true
ktool:trackEvent("onBeforeMount")
local defaulter = function(...)
import "layout"
activity.setTitle('ktool v1.0')
activity.setContentView(loadlayout("layout"))
end
if func ~= nil then
defaulter = func()
end
xpcall(defaulter, function(err)
VivoNotify("挂载前失败: " .. tostring(err))
end)
end
-- 挂载
function ktool:onMounted(func)
if self.__beforeMount then
func()
self.__beforeMount = false
ktool:trackEvent("user mounted")
else
self:onBeforeMount()
func()
self.__beforeMount = false
ktool:trackEvent("default mounted")
end
ktool:trackEvent("onMounted")
end
-- 创建单例
function ktool:new()
if not instance then
instance = setmetatable({}, ktool)
instance:initModules()
instance:loadBaseModule()
self:trackEvent("ktool_instanceCreated")
end
return instance
end
-- 初始化各子模块
function ktool:initModules()
-- 设备管理模块
self.device = {
GetStoragePath = function()
return Environment.getExternalStorageDirectory().toString()
end,
GetScreenWidth = function()
return activity.getWidth()
end,
GetScreenHeight = function()
return activity.getHeight()
end,
GetPackageName = function()
return activity.getPackageName()
end,
GetNowTime = function()
return os.date("%Y-%m-%d %H:%M:%S")
end,
-- 设置屏幕旋转为自动旋转模式
SetAutoRotateMode = function()
activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR)
end,
-- 设置屏幕旋转为横屏模式
SetLandscapeMode = function()
activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE)
end,
-- 设置屏幕旋转为竖屏模式
SetPortraitMode = function()
activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT)
end,
-- 请求悬浮窗权限
RequestOverlayPermission = function()
local intent = Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION)
intent.setData(Uri.parse("package:" .. activity.getPackageName()))
activity.startActivityForResult(intent, 100)
end
}
-- 网络管理模块
self.network = {
-- 打开 WIFI
OpenWIFI = function()
local wifi = activity.Context.getSystemService(Context.WIFI_SERVICE)
wifi.setWifiEnabled(true)
end,
-- 关闭 WIFI
CloseWIFI = function()
local wifi = activity.Context.getSystemService(Context.WIFI_SERVICE)
wifi.setWifiEnabled(false)
end,
-- 获取 WIFI 昵称
GetWIFISSID = function()
return activity.Context.getSystemService(Context.WIFI_SERVICE).getConnectionInfo().getSSID()
end,
-- 断开 WIFI
CloseNetWork = function()
local wifi = activity.Context.getSystemService(Context.WIFI_SERVICE)
wifi.disconnect()
end
}
-- 文件与缓存模块
self.fileCache = {
-- 文件是否存在
FileExists = function(id)
return File(id).exists()
end,
-- 存入缓存数据
SaveCacheData = function(filname, title, str)
local sp = activity.getSharedPreferences(filname, Context.MODE_PRIVATE)
local sped = sp.edit()
sped.putString(title, str)
sped.commit()
end,
-- 获取缓存数据
GetCacheData = function(filname, title)
local sp = activity.getSharedPreferences(filname, Context.MODE_PRIVATE)
return sp.getString(title, "")
end,
-- 存储到系统路径 => SaveStoragePathLocal("res", "config.json")
SaveStoragePathLocal = function(...)
local args = { ... }
local saveDir = GetStoragePath()
if #args ~= 0 then
for _, value in ipairs(args) do
saveDir = saveDir .. "/" .. value
end
end
return saveDir
end
}
-- 页面与视图控制模块
self.pageView = {
-- 路径跳转
SkipPage = function(viewPath)
local skipPath = activity.getLuaDir()
if not string.find(viewPath, "[.]") then
skipPath = skipPath .. "/" .. viewPath
else
local parts = {}
for part in string.gmatch(viewPath, "[^%.]+") do
table.insert(parts, part)
end
local newPath = table.concat(parts, "/")
skipPath = skipPath .. "/" .. newPath
end
activity.newActivity(skipPath, android.R.anim.fade_in, android.R.anim.fade_out)
end,
-- 重载页面
ResetPage = function()
activity.recreate()
end,
-- 导入主页面
LoadIndexPage = function(view)
activity.setContentView(loadlayout(view))
end,
-- 显示控件
Nconceal = function(id)
id.setVisibility(0)
end,
-- 隐藏控件
Conceal = function(id)
id.setVisibility(8)
end,
-- 删除控件
RemoveView = function(a, b)
return (a).removeView(b)
end,
-- 布局内插入布局
LayAddView = function(view, lay)
view.addView(loadlayout(lay))
end,
-- 使弹出的输入法不影响布局
LayoutNotAffect = function()
activity.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN)
end,
-- 控件圆角
RadiuView = function(view, InsideColor, radiu)
local drawable = GradientDrawable()
drawable.setShape(GradientDrawable.RECTANGLE)
drawable.setColor(InsideColor)
drawable.setCornerRadii({ radiu, radiu, radiu, radiu, radiu, radiu, radiu, radiu });
view.setBackgroundDrawable(drawable)
end,
-- 控件圆角 2
RadiuViewTwo = function(view, InsideColor, radiu)
local drawable = GradientDrawable()
drawable.setShape(GradientDrawable.RECTANGLE)
drawable.setColor(InsideColor)
drawable.setCornerRadii({ radiu, radiu, 0, radiu, 0, radiu, radiu, radiu });
view.setBackgroundDrawable(drawable)
end
}
-- 剪贴板模块
self.clipboard = {
GetClipboard = function()
return activity.getSystemService(Context.CLIPBOARD_SERVICE).getText()
end,
InputClipboard = function(text)
activity.getSystemService(Context.CLIPBOARD_SERVICE).setText(text)
end
}
-- 应用管理模块
self.appManager = {
-- 打开应用程序
OpenApp = function(packageName)
local manager = activity.getPackageManager()
local open = manager.getLaunchIntentForPackage(packageName)
activity.startActivity(open)
end,
-- 安装程序
InstallApp = function(packageName)
local intent = Intent(Intent.ACTION_VIEW)
intent.setDataAndType(Uri.parse("file://" .. packageName), "application/vnd.android.package-archive")
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
activity.startActivity(intent)
end,
-- 卸载应用
RemoveApp = function(packageName)
local uri = Uri.parse("package:" .. packageName)
local intent = Intent(Intent.ACTION_DELETE, uri)
activity.startActivity(intent)
end
}
-- 其他模块
self.other = {
-- 联系QQ
FollowQQ = function(qqNumber)
local url = "mqqwpa://im/chat?chat_type=wpa&uin=" .. qqNumber
activity.startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(url)))
end,
-- 加群
FollowGroup = function(groupNumber)
local url = "mqqapi://card/show_pslcard?src_type=internal&version=1&uin=" .. groupNumber ..
"&card_type=group&source=qrcode"
activity.startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(url)))
end,
-- 像素转换
DpToPx = function(dpValue)
local scale = activity.getResources().getDisplayMetrics().scaledDensity
return dpValue * scale + 0.5
end,
-- 函数将字符串转换为Unicode编码
StringToUnicode = function(str)
return URLEncoder.encode(str, "UTF-8")
end,
CreateEditTextStyle = function()
local shape = GradientDrawable()
shape.setShape(GradientDrawable.RECTANGLE)
shape.setColor(0xffffffff)
local focusedShape = GradientDrawable()
focusedShape.setShape(GradientDrawable.RECTANGLE)
focusedShape.setColor(0xffffffff)
focusedShape.setStroke(2, 0xff000000)
local states = StateListDrawable()
states.addState({ android.R.attr.state_focused }, focusedShape)
states.addState({}, shape)
return states
end,
-- 获取图片BitmapDrawable
GetImageDrawable = function(img_path)
-- 打开文件输入流 读取图像文件
local image_stream = FileInputStream(img_path)
-- 使用BitmapFactory解码图像流 生成Bitmap对象
local bitmap = BitmapFactory.decodeStream(image_stream)
-- 使用Bitmap对象创建一个BitmapDrawable对象并返回
return BitmapDrawable(activity.getResources(), bitmap)
end
}
end
-- 设置元表,使得 ktool['module'] 可以直接访问
setmetatable(ktool, {
__index = function(_, key)
return ktool:new()[key]
end
})
-- 悬浮窗
ShowXFC = function(flag)
flag.count = 1
wmManager = activity.getSystemService(Context.WINDOW_SERVICE) --获取窗口管理器
HasFocus = false --是否有焦点
wmParams = WindowManager.LayoutParams() --对象
if tonumber(Build.VERSION.SDK) >= 26 then
wmParams.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY --安卓8以上悬浮窗打开方式
else
wmParams.type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT --安卓8以下的悬浮窗打开方式
end
wmParams.format = PixelFormat.RGBA_8888 --设置背景
wmParams.flags = WindowManager.LayoutParams().FLAG_NOT_FOCUSABLE --焦点设置
wmParams.gravity = Gravity.LEFT| Gravity.TOP --重力设置
wmParams.x = activity.getWidth() / 6
wmParams.y = activity.getHeight() / 5
wmParams.width = WindowManager.LayoutParams.WRAP_CONTENT
wmParams.height = WindowManager.LayoutParams.WRAP_CONTENT
if Build.VERSION.SDK_INT >= Build.VERSION_CODES.M and ! Settings.canDrawOverlays(this) then
UpNotify("请授予悬浮窗权限^_^")
local intent = Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION)
intent.setData(Uri.parse("package:" .. activity.getPackageName()));
activity.startActivityForResult(intent, 100)
os.exit()
else
xfc = loadlayout({
LinearLayout,
layout_width = "fill",
layout_height = "fill",
{
CircleImageView,
src = activity.getLuaDir() .. "/LuaLogo.png",
layout_width = "50dp",
layout_height = "50dp",
id = "Logo",
},
})
cfc = loadlayout({
LinearLayout,
orientation = "vertical",
layout_height = "fill",
layout_width = "fill",
id = "Windows",
{
CardView,
layout_gravity = "center",
layout_width = "230dp",
layout_height = "170dp",
backgroundColor = '0xfff0fcff', --背景颜色
alpha = 0.85, --控件透明度
{
FrameLayout,
layout_marginTop = "45dp",
layout_height = "fill",
layout_width = "fill",
{
TextView,
id = "xcfText",
textSize = "14sp",
layout_gravity = "center",
},
},
{
FrameLayout,
layout_height = "40dp",
layout_width = "fill",
{
AbsoluteLayout,
layout_gravity = "right",
layout_height = "40dp",
layout_width = "40dp",
{
Button,
text = "X",
id = "Close",
},
},
{
AbsoluteLayout,
layout_gravity = "center",
layout_height = "40dp",
layout_width = "80dp",
{
TextView,
text = "电力小助手",
gravity = "center",
layout_width = "fill",
layout_height = "fill",
},
},
{
AbsoluteLayout,
layout_gravity = "left",
layout_height = "40dp",
layout_width = "40dp",
{
Button,
text = "—",
id = "Min",
alpha = 0.7, --控件透明度
},
},
},
},
}) --cfc
end
wmManager.addView(xfc, wmParams)
function 放大()
--放大cfc代码
wmManager.addView(cfc, wmParams)
wmManager.removeView(xfc)
end
function Close.onClick()
--退出cfc代码
wmManager.removeView(cfc)
flag.count = 0
end
function Min.onClick()
--隐藏cfc代码
wmManager.removeView(cfc)
wmManager.addView(xfc, wmParams)
end
function Logo.OnTouchListener(v, event)
--这个图标移动代码
if event.getAction() == MotionEvent.ACTION_DOWN then
firstX = event.getRawX()
firstY = event.getRawY()
wmX = wmParams.x
wmY = wmParams.y
elseif event.getAction() == MotionEvent.ACTION_MOVE then
wmParams.x = wmX + (event.getRawX() - firstX)
wmParams.y = wmY + (event.getRawY() - firstY)
wmManager.updateViewLayout(xfc, wmParams)
elseif event.getAction() == MotionEvent.ACTION_UP then
end
return false
end
function Logo.onLongClick()
UpNotify("QQ:1614355756")
end
function Logo.onClick()
放大()
end
function Windows.OnTouchListener(v, event) --这个图标移动代码
if event.getAction() == MotionEvent.ACTION_DOWN then
firstX = event.getRawX()
firstY = event.getRawY()
wmX = wmParams.x
wmY = wmParams.y
elseif event.getAction() == MotionEvent.ACTION_MOVE then
wmParams.x = wmX + (event.getRawX() - firstX)
wmParams.y = wmY + (event.getRawY() - firstY)
wmManager.updateViewLayout(cfc, wmParams)
elseif event.getAction() == MotionEvent.ACTION_UP then
end
return false
end
function CircleButton(view, InsideColor, radiu)
import "android.graphics.drawable.GradientDrawable"
local drawable = GradientDrawable()
drawable.setShape(GradientDrawable.RECTANGLE)
drawable.setColor(InsideColor)
drawable.setCornerRadii({ radiu, radiu, radiu, radiu, radiu, radiu, radiu, radiu });
view.setBackgroundDrawable(drawable)
end
-- CircleButton(Windows, 0xffff461f, 45)
CircleButton(Close, 0xffff461f, 70)
CircleButton(Min, 0xff50616d, 20)
xcfText.setText("暂时未获取到数据^_^")
end
_G.ktool = ktool
_G.ShowXFC = ShowXFC