admin 发布的文章

-- 匹配 数字.数字 或 数字.数字.数字 纯版本号
function checkVer(ver)
  return string.match(ver,"^%d+%.%d+$") or string.match(ver,"^%d+%.%d+%.%d+$")
end

function 水珠动画(view,time)
  time = time or 110
  import "android.animation.ObjectAnimator"
  ObjectAnimator().ofFloat(view,"scaleX",{1.2,.8,1.1,.9,1}).setDuration(time).start()
  ObjectAnimator().ofFloat(view,"scaleY",{1.2,.8,1.1,.9,1}).setDuration(time).start()
end

看什么看

import "android.graphics.*"

layout = {
  FrameLayout,
  layout_width="fill",
  layout_height="fill",
  {
    View,
    id="dview",
    layout_width="fill",
    layout_height="fill",
  },
  {
    CardView,
    id="targetCard",
    layout_width="300dp",
    layout_height="150dp",
    layout_gravity="center",
    cardBackgroundColor=0xFF333333,
    cardElevation="8dp",
    radius="15dp",
    
  },
}

activity.setContentView(loadlayout(layout))

-- 物理常量与容器
local rains = {} -- 下落中的雨滴
local splashes = {} -- 飞溅中的粒子
local GRAVITY = 1.5 -- 重力加速度
local MAX_RAIN = 150 -- 最大雨滴密度

-- 初始化一个雨滴
function createRain(w)
  return {
    x = math.random(0, w),
    y = math.random(-500, 0),
    speed = math.random(15, 30),--雨滴速度
    len = math.random(50, 100),--雨丝长度
    alpha = math.random(100, 200)--雨丝透明的
  }
end

-- 初始化飞溅粒子
function createSplash(x, y)
  for i=1, 5 do
    table.insert(splashes, {
      x = x,
      y = y,
      -- 使用整数随机后再除法,获取带小数的速度
      vx = math.random(-60, 60) / 10, -- 相当于 -6.0 到 6.0
      vy = math.random(-120, -40) / 10, -- 相当于 -12.0 到 -4.0
      life = 1.0,
      decay = math.random(50, 100) / 1000 -- 修复后的行:0.05 到 0.1
    })
  end
end


-- 创建 LuaDrawable
local drawable = LuaDrawable(function(canvas, paint, view)
  paint.setAntiAlias(true)
  local w = canvas.getWidth()
  local h = canvas.getHeight()

  -- 获取 CardView 在屏幕上的区域用于碰撞检测
  local cardLoc = int[2]
  targetCard.getLocationOnScreen(cardLoc)
  local viewLoc = int[2]
  dview.getLocationOnScreen(viewLoc)

  -- 计算相对坐标
  local relX = cardLoc[0] - viewLoc[0]
  local relY = cardLoc[1] - viewLoc[1]
  local cardRect = Rect(relX, relY, relX + targetCard.getWidth(), relY + targetCard.getHeight())

  -- 绘制背景
  canvas.drawColor(0xFF111111)

  -- 1. 处理雨滴逻辑
  if #rains < MAX_RAIN then
    table.insert(rains, createRain(w))
  end

  paint.setStrokeWidth(5)--雨丝粗细
  for i=#rains, 1, -1 do
    local r = rains[i]
    r.y = r.y + r.speed

    -- 碰撞检测:判断是否碰到 CardView 顶部
    local hitCard = r.x > cardRect.left and r.x < cardRect.right and r.y >= cardRect.top and r.y <= cardRect.top + r.speed

    if hitCard or r.y > h then
      if hitCard then createSplash(r.x, cardRect.top) end
      table.remove(rains, i) -- 移除雨滴
     else
      -- 绘制雨丝
      paint.setColor(0xFFFFFFFF)
      paint.setAlpha(r.alpha)
      canvas.drawLine(r.x, r.y, r.x, r.y + r.len, paint)
    end
  end

  -- 2. 处理飞溅粒子逻辑
  paint.setStyle(Paint.Style.FILL)
  for i=#splashes, 1, -1 do
    local s = splashes[i]
    s.x = s.x + s.vx
    s.y = s.y + s.vy
    s.vy = s.vy + GRAVITY -- 受重力影响下落
    s.life = s.life - s.decay

    if s.life <= 0 then
      table.remove(splashes, i)
     else
      paint.setColor(0xFFFFFFFF)
      paint.setAlpha(math.floor(s.life * 255))
      canvas.drawCircle(s.x, s.y, 4, paint) -- 绘制水滴点
    end
  end

  -- 强制重绘,形成动画
  view.invalidateSelf()
end)

dview.setBackground(drawable)

函数

require "import"
import "android.graphics.Paint"
import "cjson"
import "cx"

local apiSecret = ""


function isEmail(email)
  if not email then return false end
  -- 去除首尾空格
  local str = email:gsub("^%s+", ""):gsub("%s+$", "")
  -- 最稳严格正则:支持纯数字账号、163/qq/企业邮箱
  local pat = "^[0-9a-zA-Z._-]+@[0-9a-zA-Z_-]+%.[a-zA-Z0-9._-]+$"
  -- local pat = [[\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*]]
  -- 强行拦截非法畸形
  if str:find("%.%.") -- 连续两点
    or str:find("@$") -- @结尾
    or str:find("^@") -- @开头
    or str:find("@%.") -- @后面直接点
    then
    return false
  end

  return str:match(pat) != nil
end


function sign(tbl)
  import "java.util.UUID"
  if type(tbl) != "table" then
    return nil;
  end
  tbl["timestamp"] = os.time()
  tbl["nonce"] = UUID.randomUUID().toString()
  local keys = {}
  for k, v in pairs(tbl) do
    if type(k) == "string" and k != "" and v != nil and v != "" then
      table.insert(keys, k)
    end
  end
  table.sort(keys, function(a, b)
    return a < b
  end)
  -- 3. 按排序结果拼接
  local strList = {}
  for _, k in ipairs(keys) do
    -- 再次确保值有效(防呆设计,防止中途值被改变)
    local v = tbl[k]
    if v != nil and v != "" then
      table.insert(strList, k .. "=" .. tostring(v))
    end
  end
  local md5Str = table.concat(strList, "&")
  tbl["sign"] = string.md5(md5Str .. "&apiSecret=".. apiSecret):lower()
  local str = {}
  for k, v in pairs(tbl) do
    table.insert(str, k .. "=" .. v)
  end
  return table.concat(str,"&")
end

function 复制(text)
  import "android.content.*"
  activity.getSystemService(Context.CLIPBOARD_SERVICE).setText(text)
end
function 卡片(边框厚度,边框颜色,背景颜色,圆角度)
  import "android.graphics.drawable.GradientDrawable"
  drawable=GradientDrawable()
  drawable.setShape(GradientDrawable.RECTANGLE)
  drawable.setStroke(边框厚度,tonumber(边框颜色))--边框厚度和背景颜色
  drawable.setColor(tonumber(背景颜色))--背景颜色
  drawable.setCornerRadius(圆角度)--圆角
  return drawable
end

function tw(message)
  local toasts={
    CardView;
    id="toastb",
    CardElevation="2dp";
    radius="10px";
    background="#C6000000";
    alpha=1,
    {
      TextView;
      layout_margin="30";
      TextColor="#ffffffff",
      layout_gravity="center";
      text="hello";
      textSize = "12sp",
      id="内容",
      layout_marginRight="15dp",
      layout_marginLeft="15dp",
    };
  };
  message=tostring(message)
  local context=activity.getApplicationContext();
  local duration=Toast.LENGTH_SHORT;
  local toast=Toast.makeText(context,"",duration)--.setGravity(Gravity.CENTER,0,0);
  toast.setView(loadlayout(toasts))--自定义布局
  内容.Text=message
  toast.show()
end


--写入文件
function 写文件(path, content)
  import "java.io.File"
  local f=File(tostring(File(tostring(path)).getParentFile())).mkdirs()
  io.open(tostring(path),"w"):write(tostring(content)):close()
end

--文件或文件夹是否存在
function 文件是否存在(path)
  local f=io.open(path,'r')
  if f~=nil then io.close(f) return true else return false end
end

--读取文件内容
function 读文件(path)
  local file=io.input(path)
  local str=io.read("*a")
  io.close()
  return tostring(str)
end

--删除文件或文件夹
function 删文件(path)
  local sc = os.execute("rm -r "..path)
  if sc then
    tw("成功")
   else
    tw("失败")
  end
end

--调用系统浏览器打开网页
function 浏览器打开网页(url)
  import "android.content.Intent"
  import "android.net.Uri"
  tw("如果网页无法打开,请刷新网页!")
  local viewIntent = Intent("android.intent.action.VIEW",Uri.parse(url))
  activity.startActivity(viewIntent)
end

function 圆角(view,InsideColor,radiu)
  import "android.graphics.drawable.GradientDrawable"
  drawable = GradientDrawable()
  drawable.setShape(GradientDrawable.RECTANGLE)
  drawable.setColor(InsideColor)
  drawable.setCornerRadii({radiu,radiu,radiu,radiu,radiu,radiu,radiu,radiu});
  view.setBackgroundDrawable(drawable)
end

function 加载框()
  import "android.app.AlertDialog"
  import "android.graphics.drawable.GradientDrawable"
  import "android.graphics.drawable.AnimationDrawable"
  import "android.graphics.PorterDuff"
  import "android.graphics.PorterDuffColorFilter"
  -- 遮罩
  local mask = GradientDrawable()
  mask.setColor(0x00000000)
  mask.setCornerRadius(0)

  local lay = {
    LinearLayout,
    background = mask,
    gravity="center",

    {
      LinearLayout,
      layout_width = "55dp",
      layout_height = "55dp",
      gravity="center",
      id="bb",
      orientation = "vertical",
      -- 加载圈
      {
        ProgressBar,
        layout_width = "20dp",
        layout_height = "20dp",

        id="pb",
      }
    }
  }

  local builder = AlertDialog.Builder(this)
  builder.setView(loadlayout(lay))
  local mode = PorterDuff.Mode.SRC_IN
  local filter = PorterDuffColorFilter(0xFFFFFFFF, mode)
  pb.getIndeterminateDrawable().setColorFilter(filter)
  local dialog = builder.create()
  local win = dialog.getWindow()
  win.setLayout(-1, -1) -- 全屏
  win.setBackgroundDrawable(mask)
  --win.setDimAmount(0) -- 取消系统自带阴影
  圆角(bb,0x98000000, 360)
  dialog.setCancelable(false)
  dialog.setCanceledOnTouchOutside(false)
  dialog.show()
  return dialog
end


function 登录信息(_info)
  local 路径 = "/sdcard/aus/info"
  if _info != nil then
    写文件(路径,_info)
  end
  if !文件是否存在(路径) then
    return nil
  end
  local suc, data = xpcall(function()
    import "cjson"
    return cjson.decode(读文件(路径))
  end, function()end)
  if suc then
    return data
  end
  return nil
end