牙叔教程 简单易懂
效果展示
缘起
群里有人问, 放大镜怎么写
环境
Autojs版本: 9.0.5
Android版本: 8.0.0
软件可能还有些许bug, 介意就别看了, 百度找别的教程去
思路
你将学到以下知识点
- 文件分层, 比如将绘制图片文字等绘制类文件放同一个文件夹
- 配置集中, 比如把布局大小, 放大镜间距, 截图延时配置集中放一起
- 自定义view, 比如放大镜的圆环阴影
- 控件在屏幕中的绝对坐标
- 画圆环, 画十字架, 画字
- 使用缓存值, 因为ui限制16ms刷新, 能少计算, 就少计算
- 裁剪画布
- 保存以及还原画布状态
- 绘制居中的文字
- 转换任意单位为px
- 底部三大金刚高度
- 把变量放进ui作用域
- 判断颜色明度, 比如浅色背景黑色文字, 深色背景白色文字
- 控件设置渐变背景
- 控件设置透明度
- 设置动画监听, 比如控件透明动画结束之后, 再截图
- 停止其他脚本
- 悬浮窗和截图权限的申请
- 脚本广播通信
- 悬浮窗一闪而过的规避方法
难点
- 悬浮窗移动到边边角角后, 显示图片的计算.
思路: 悬浮窗计算悬浮窗, 图片计算图片的, 各管个的, 只要每个都是正确的, 那么结果就是正确的
代码讲解
1. 主逻辑
let init = require("./init"); let showFloatingWindows = require("./showFloatingWindows"); // 判断悬浮窗和截图权限, 没有就退出 init(); showFloatingWindows(); let intervalId = setInterval(() => {}, 1000); events.broadcast.on("退出悬浮窗", function (value) { if (value) { clearInterval(intervalId); setTimeout(function () {}, 1000); } });
2. 权限判断
module.exports = function () { engines.all().map((ScriptEngine) => { if (engines.myEngine().toString() !== ScriptEngine.toString()) { ScriptEngine.forceStop(); } }); if (!$floaty.checkPermission()) { // 没有悬浮窗权限,提示用户并跳转请求 toastLog("本脚本需要悬浮窗权限来显示悬浮窗,请在随后的界面中允许并重新运行本脚本。"); $floaty.requestPermission(); exit(); } else { console.log("已有悬浮窗权限"); } // 请求截图 if (!requestScreenCapture()) { toastLog("请求截图失败"); exit(); } else { console.log("已有截图权限"); } };
3. 悬浮窗布局
let window = $floaty.rawWindow( <frame id="parentF" alpha="0.0"> <custom-view ... ></custom-view> <horizontal gravity="bottom"> <card cardCornerRadius="{{buttonViewRadiusWithUnit}}" cardElevation="0px"> <img ... ></img> </card> <View w="{{blankViewSizeWithUnit}}"></View> <card cardCornerRadius="{{buttonViewRadiusWithUnit}}" cardElevation="0px"> <img ... ></img> </card> </horizontal> </frame> );
4. 悬浮窗点击事件
window.record.click(function () { let data = window.customView.updateData(); toastLog("颜色已经记录\n" + data); setClip(data); }); window.quit.click(function () { toastLog("退出拾色器"); window.close(); events.broadcast.emit("退出悬浮窗", true); });
5. 显示悬浮窗
ui.post(function () { let windowWidth = window.getWidth(); let windowHeight = window.getHeight(); let x = dw / 2 - windowWidth / 2; let y = dh / 2 - windowHeight / 2; window.setPosition(x, y); setTimeout(function () { window.parentF.setAlpha(1); window.customView.updateRingColor("#ff0000"); window.customView.refresh(); setOnTouchListener(window, dw, dh, windowWidth, windowHeight); }, 300); });
6. 放大镜onDraw
onDraw: function (canvas) { this.ringColor = getColor(this); paintOfTheOuterCircle.setShader(radialGradientOfTheOuterCircle); drawCircle(canvas, this); if (this.img) { drawImg(canvas, this); drawInfo(canvas, this); } drawCross(canvas, this); },
7. 绘制十字架
canvas.drawRect(strokeRectFLeft, strokePaint); canvas.drawRect(fillRectFLeft, fillPaint); canvas.drawRect(strokeRectFRight, strokePaint); canvas.drawRect(fillRectFRight, fillPaint); canvas.drawRect(strokeRectFTop, strokePaint); canvas.drawRect(fillRectFTop, fillPaint); canvas.drawRect(strokeRectFBottom, strokePaint); canvas.drawRect(fillRectFBottom, fillPaint);
8. 绘制圆环
canvas.drawCircle(view.centerX, view.centerY, view.radiusOfTheOuterCircle, view.paintOfTheOuterCircle);
9. 绘制图片
canvas.drawARGB(255, 0, 0, 255); canvas.drawBitmap(bitmap, srcRect, destRect, paintOfImg);
10. 及时释放图片资源
updateImg: function (img) { let oldImg = this.img; let oldBitmap = this.bitmap; ui.post(function () { oldBitmap && oldBitmap.recycle(); oldImg && oldImg.recycle(); }, 100); this.img = img.clone(); this.bitmap = this.img.getBitmap(); },
名人名言
思路是最重要的, 其他的百度, bing, stackoverflow, 安卓文档, autojs文档, 最后才是群里问问
--- 牙叔教程
声明
部分内容来自网络
本教程仅用于学习, 禁止用于其他用途