AIWROK软件支持悬浮窗自由定位和拖拽功能
AIWROK软件支持悬浮窗自由定位和拖拽功能//通过floatUI创建悬浮窗
//适用于ES5系统安卓 JavaScript引擎Rhino
//基于AIWROK软件安卓开发框架
//支持悬浮窗自由定位和拖拽功能
//🍎交流QQ群711841924群一,苹果内测群,528816639
if (!String.prototype.repeat) {
String.prototype.repeat = function(count) {
'use strict';
if (this == null) {
throw new TypeError('can\'t convert ' + this + ' to object');
}
var str = String(this);
count = +count;
if (count != count) {
count = 0;
}
if (count < 0) {
throw new RangeError('repeat count must be non-negative');
}
if (count == Infinity) {
throw new RangeError('repeat count must be less than infinity');
}
count = Math.floor(count);
if (str.length == 0 || count == 0) {
return '';
}
// 确保重复的字符串不会超出字符串长度限制
if (str.length * count >= 1 << 28) {
throw new RangeError('repeat count must not overflow maximum string size');
}
var rpt = '';
for (var i = 0; i < count; i++) {
rpt += str;
}
return rpt;
};
}
// ES5兼容的String.prototype.padStart polyfill
if (!String.prototype.padStart) {
String.prototype.padStart = function(targetLength, padString) {
targetLength = targetLength >> 0; // 转换为整数
padString = String((typeof padString !== 'undefined' ? padString : ' '));
if (this.length > targetLength) {
return String(this);
} else {
targetLength = targetLength - this.length;
if (targetLength > padString.length) {
padString += padString.repeat(targetLength / padString.length); // 截断或重复填充字符串
}
return padString.slice(0, targetLength) + String(this);
}
};
}
/*
安卓可移动侧栏日志吐司
功能:
1. 可拖拽移动的侧栏悬浮窗
2. 支持日志信息实时显示
3. 支持展开/收起功能
4. 支持自定义日志颜色
*/
// 定义侧栏日志悬浮窗构造函数
function 侧栏日志() {
this.screenHeight = 1920; // 默认屏幕高度
this.screenWidth = 1080;// 默认屏幕宽度
this.isExpanded = false;// 展开状态标志
this.logs = []; // 日志数组
this.maxLogs = 50; // 最大日志条数
this.dragging = false; // 拖拽状态标志
this.lastX = 0; // 上次触摸X坐标
this.lastY = 0; // 上次触摸Y坐标
}
// 创建侧栏日志悬浮窗
侧栏日志.prototype.create = function() {
try {
// 检查floatUI是否可用
if (typeof floatUI === 'undefined') {
printl("❌ 错误:未找到floatUI库");
return false;
}
// 创建floatUI实例
var fui = new floatUI();
// 获取实际屏幕尺寸
try {
if (context && context.getResources && context.getResources().getDisplayMetrics) {
var metrics = context.getResources().getDisplayMetrics();
this.screenHeight = metrics.heightPixels || 1920;
this.screenWidth = metrics.widthPixels || 1080;
printl("✅ 获取屏幕尺寸: " + this.screenWidth + "x" + this.screenHeight);
} else {
printl("⚠️ 无法获取屏幕尺寸,使用默认值");
this.screenHeight = 1920; // 默认屏幕高度
this.screenWidth = 1080;// 默认屏幕宽度
}
} catch(e) {
printl("⚠️ 获取屏幕尺寸失败,使用默认值: " + e);
this.screenHeight = 1920;
this.screenWidth = 1080;
}
// 定义侧边栏宽度和高度
var sidebarWidth = 100;// 更窄的侧边栏宽度
var sidebarMinWidth = 30; // 更窄的收起时最小宽度
var sidebarHeight = 100; // 固定小高度,不再依赖屏幕比例
// 加载XML布局
try {
fui.loadXML(`
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="${sidebarWidth}dp"
android:layout_height="${sidebarHeight}dp"
android:background="#CC000000"
android:orientation="vertical"
android:id="main_container">
<!-- 可拖动的标题栏 -->
<LinearLayout
android:id="title_bar"
android:layout_width="match_parent"
android:layout_height="35dp"
android:background="#666666"
android:orientation="horizontal"
android:gravity="center_vertical">
<!-- 拖动区域 -->
<View
android:layout_width="${sidebarMinWidth}dp"
android:layout_height="match_parent"
android:background="#444444"/>
<!-- 标题文字(仅在展开时可见) -->
<TextView
android:id="title_text"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:text="运行日志"
android:textColor="#FFFFFF"
android:gravity="center"
android:textSize="14sp"/>
<!-- 关闭按钮(仅在展开时可见) -->
<Button
android:id="close_button"
android:layout_width="30dp"
android:layout_height="30dp"
android:text="✕"
android:textColor="#FFFFFF"
android:background="#FF4444"
android:textSize="14sp"
android:padding="0dp"
android:gravity="center"/>
</LinearLayout>
<!-- 日志显示区域(仅在展开时可见) -->
<ScrollView
android:id="log_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#111111">
<TextView
android:id="log_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="#00FF00"
android:textSize="11sp"
android:padding="3dp"
android:lineSpacingExtra="1dp"/>
</ScrollView>
<!-- 展开/收起按钮 -->
<Button
android:id="toggle_button"
android:layout_width="match_parent"
android:layout_height="25dp"
android:text="≡"
android:textColor="#FFFFFF"
android:background="#555555"
android:textSize="16sp"/>
</LinearLayout>
`);
printl("✅ XML布局加载成功");
} catch (xmlError) {
printl("❌ XML布局加载失败: " + xmlError);
return false;
}
// 保存UI实例
this.ui = fui;
// 保存宽度设置供toggleExpand方法使用
this.sidebarWidth = sidebarWidth;
this.sidebarMinWidth = sidebarMinWidth;
// 获取UI元素
try {
this.titleBar = fui.findViewById("title_bar");
this.titleText = fui.findViewById("title_text");
this.logContainer = fui.findViewById("log_container");
this.logText = fui.findViewById("log_text");
this.toggleButton = fui.findViewById("toggle_button");
this.closeButton = fui.findViewById("close_button"); // 获取关闭按钮
this.mainContainer = fui.findViewById("main_container");
// 检查关键元素是否存在
var missingElements = [];
if (!this.titleBar) missingElements.push("titleBar");
if (!this.logText) missingElements.push("logText");
if (!this.toggleButton) missingElements.push("toggleButton");
if (!this.mainContainer) missingElements.push("mainContainer");
if (missingElements.length > 0) {
printl("⚠️ 缺失关键UI元素: " + missingElements.join(", "));
} else {
printl("✅ 所有UI元素获取成功");
}
} catch (findError) {
printl("❌ 获取UI元素失败: " + findError);
}
// 设置初始位置(屏幕左侧)
try {
this.setPos(0, (this.screenHeight - 100) / 2);
printl("✅ 初始位置设置成功");
} catch (posError) {
printl("❌ 设置初始位置失败: " + posError);
}
// 初始化事件
try {
this.initEvents();
printl("✅ 事件初始化成功");
} catch (eventError) {
printl("❌ 事件初始化失败: " + eventError);
}
// 显示初始化日志
this.log("✅ 侧栏日志已启动", "#00FF00");
return true;
} catch (e) {
printl("❌ 创建侧栏日志失败: " + e);
return false;
}
};
// 初始化事件
侧栏日志.prototype.initEvents = function() {
var self = this;
// 设置拖拽事件 - 添加更完善的错误处理
try {
if (typeof View !== 'undefined' && typeof MotionEvent !== 'undefined' && this.titleBar && this.titleBar.setOnTouchListener) {
this.titleBar.setOnTouchListener(new View.OnTouchListener({
onTouch: function(view, event) {
try {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
self.dragging = true;
self.lastX = event.getRawX();
self.lastY = event.getRawY();
break;
case MotionEvent.ACTION_MOVE:
if (self.dragging) {
var dx = event.getRawX() - self.lastX;
var dy = event.getRawY() - self.lastY;
// 获取当前位置
var currentX = view.getX();
var currentY = view.getY();
// 计算新位置(考虑整个容器的位置)
var newX = currentX + dx;
var newY = currentY + dy;
// 边界检查
if (newX < 0) newX = 0;
if (newY < 0) newY = 0;
if (newX > self.screenWidth - (self.isExpanded ? self.sidebarWidth : self.sidebarMinWidth))
newX = self.screenWidth - (self.isExpanded ? self.sidebarWidth : self.sidebarMinWidth);
if (newY > self.screenHeight - 100)
newY = self.screenHeight - 100;
// 设置新位置
self.setPos(newX, newY);
// 更新上次触摸位置
self.lastX = event.getRawX();
self.lastY = event.getRawY();
}
break;
case MotionEvent.ACTION_UP:
self.dragging = false;
break;
}
return true;
} catch (touchError) {
// 静默处理触摸事件错误,避免崩溃
return false;
}
}
}));
} else {
printl("⚠️ 无法设置拖拽事件,缺少必要组件");
}
} catch (touchSetupError) {
printl("❌ 设置拖拽事件失败: " + touchSetupError);
}
// 展开/收起按钮点击事件
try {
if (this.toggleButton && this.toggleButton.setOnClickListener) {
this.toggleButton.setOnClickListener(function() {
try {
self.toggleExpand();
} catch (toggleError) {
printl("❌ 执行展开/收起操作失败: " + toggleError);
}
});
}
} catch (toggleSetupError) {
printl("❌ 设置展开/收起事件失败: " + toggleSetupError);
}
// 关闭按钮点击事件
try {
if (this.closeButton && this.closeButton.setOnClickListener) {
this.closeButton.setOnClickListener(function() {
try {
self.close();
} catch (closeError) {
printl("❌ 执行关闭操作失败: " + closeError);
}
});
}
} catch (closeSetupError) {
printl("❌ 设置关闭事件失败: " + closeSetupError);
}
};
// 获取当前时间用于日志
侧栏日志.prototype.getCurrentTime = function() {
var now = new Date();
var hours = now.getHours().toString().padStart(2, '0');
var minutes = now.getMinutes().toString().padStart(2, '0');
var seconds = now.getSeconds().toString().padStart(2, '0');
return hours + ':' + minutes + ':' + seconds;
};
// 切换展开/收起状态
侧栏日志.prototype.toggleExpand = function() {
try {
var self = this;
// 记录当前状态变更(使用printl避免递归)
printl("[" + self.getCurrentTime() + "] " + (self.isExpanded ? "🔽 侧栏正在收起" : "🔼 侧栏正在展开"));
// 定义要设置的目标宽度 - 修复逻辑:当前展开时应该设置为收起宽度,当前收起时应该设置为展开宽度
var targetWidth = this.isExpanded ? this.sidebarMinWidth : this.sidebarWidth;
// 切换展开状态标志
this.isExpanded = !this.isExpanded;
// 确保在主线程中执行UI操作
var uiOperation = function() {
self.performToggleExpand(targetWidth);
};
// 尝试多种UI线程调度方案
var threadScheduled = false;
// 方案1: 使用context.runOnUiThread
try {
if (context && context.runOnUiThread) {
// 使用ES5兼容的方式创建Runnable对象
var runnable = {
run: function() {
try {
uiOperation();
} catch (e) {
printl("❌ UI线程执行失败: " + e);
}
}
};
context.runOnUiThread(runnable);
threadScheduled = true;
printl("✅ 使用context.runOnUiThread调度UI线程");
}
} catch (e) {
printl("❌ 方案1: context.runOnUiThread失败: " + e);
}
// 方案2: 使用View.post (如果有任何View对象可用)
if (!threadScheduled) {
try {
var viewToUse = self.mainContainer || self.titleBar || self.toggleButton;
if (viewToUse && viewToUse.post) {
viewToUse.post(function() {
try {
uiOperation();
} catch (e) {
printl("❌ View.post执行失败: " + e);
}
});
threadScheduled = true;
printl("✅ 使用View.post调度UI线程");
}
} catch (e) {
printl("❌ 方案2: View.post失败: " + e);
}
}
// 方案3: 尝试使用Handler (如果可用)
if (!threadScheduled) {
try {
if (typeof Handler !== 'undefined' && typeof Looper !== 'undefined' && Looper.getMainLooper) {
var handler = new Handler(Looper.getMainLooper());
handler.post(function() {
try {
uiOperation();
} catch (e) {
printl("❌ Handler执行失败: " + e);
}
});
threadScheduled = true;
printl("✅ 使用Handler调度UI线程");
}
} catch (e) {
printl("❌ 方案3: Handler失败: " + e);
}
}
// 方案4: 直接执行作为最后备选 (可能会失败但提供降级方案)
if (!threadScheduled) {
printl("⚠️ 所有线程调度方案失败,尝试直接执行UI操作");
try {
uiOperation();
} catch (directError) {
printl("❌ 直接执行UI操作失败: " + directError);
}
}
} catch (e) {
printl("❌ 切换展开状态失败: " + e);
}
};
// 执行UI操作的核心方法(应在主线程中调用)
侧栏日志.prototype.performToggleExpand = function(targetWidth) {
try {
var self = this;
// 切换UI元素可见性
if (!this.isExpanded) {
// 收起状态
if (this.titleText && typeof this.titleText.setVisibility === 'function') {
try {
this.titleText.setVisibility(View.GONE);
} catch (e) {
printl("❌ 设置titleText可见性失败: " + e);
}
}
if (this.logContainer && typeof this.logContainer.setVisibility === 'function') {
try {
this.logContainer.setVisibility(View.GONE);
} catch (e) {
printl("❌ 设置logContainer可见性失败: " + e);
}
}
if (this.closeButton && typeof this.closeButton.setVisibility === 'function') {
try {
this.closeButton.setVisibility(View.GONE); // 收起时隐藏关闭按钮
} catch (e) {
printl("❌ 设置closeButton可见性失败: " + e);
}
}
} else {
// 展开状态
if (this.titleText && typeof this.titleText.setVisibility === 'function') {
try {
this.titleText.setVisibility(View.VISIBLE);
} catch (e) {
printl("❌ 设置titleText可见性失败: " + e);
}
}
if (this.logContainer && typeof this.logContainer.setVisibility === 'function') {
try {
this.logContainer.setVisibility(View.VISIBLE);
} catch (e) {
printl("❌ 设置logContainer可见性失败: " + e);
}
}
if (this.closeButton && typeof this.closeButton.setVisibility === 'function') {
try {
this.closeButton.setVisibility(View.VISIBLE); // 展开时显示关闭按钮
} catch (e) {
printl("❌ 设置closeButton可见性失败: " + e);
}
}
}
// 尝试多种方法来设置宽度,增加更多的备选方案
var widthSetSuccessfully = false;
var errorMessages = [];
// 获取屏幕密度
var getDensity = function() {
try {
if (context && context.getResources && context.getResources().getDisplayMetrics) {
return context.getResources().getDisplayMetrics().density;
}
} catch (e) {
printl("⚠️ 获取屏幕密度失败: " + e);
}
return 3; // 默认密度
};
// 方法1: 尝试通过FloatUI对象的可能方法
try {
if (this.ui && typeof this.ui.setLayoutWidth === 'function') {
this.ui.setLayoutWidth(targetWidth);
widthSetSuccessfully = true;
printl("方法1: 使用setLayoutWidth设置宽度成功");
}
} catch (e) {
errorMessages.push("方法1: " + (e.message || String(e)));
}
// 方法2: 尝试通过LayoutParams设置宽度
if (!widthSetSuccessfully) {
try {
if (this.mainContainer && typeof this.mainContainer.getLayoutParams === 'function' &&
typeof this.mainContainer.setLayoutParams === 'function') {
var params = this.mainContainer.getLayoutParams();
if (params) {
// 尝试将dp转换为像素
var pixelWidth = Math.round(targetWidth * getDensity());
// 安全地设置宽度
try {
params.width = pixelWidth;
this.mainContainer.setLayoutParams(params);
widthSetSuccessfully = true;
printl("方法2: 使用LayoutParams设置宽度成功");
} catch (setParamsError) {
errorMessages.push("方法2: " + (setParamsError.message || String(setParamsError)));
}
}
}
} catch (e) {
errorMessages.push("方法2: " + (e.message || String(e)));
}
}
// 方法3: 尝试直接设置视图宽度
if (!widthSetSuccessfully) {
try {
if (this.mainContainer && typeof this.mainContainer.setWidth === 'function') {
// 使用已经计算好的像素宽度
var pixelWidth = Math.round(targetWidth * getDensity());
this.mainContainer.setWidth(pixelWidth);
widthSetSuccessfully = true;
printl("方法3: 使用setWidth设置宽度成功");
}
} catch (e) {
errorMessages.push("方法3: " + (e.message || String(e)));
}
}
// 方法4: 尝试修改XML布局参数
if (!widthSetSuccessfully) {
try {
if (this.ui && typeof this.ui.setLayoutParams === 'function') {
// 尝试获取并修改FloatUI的布局参数
var floatParams = (typeof this.ui.getLayoutParams === 'function') ? this.ui.getLayoutParams() : null;
if (floatParams) {
floatParams.width = Math.round(targetWidth * getDensity());
this.ui.setLayoutParams(floatParams);
widthSetSuccessfully = true;
printl("方法4: 使用FloatUI.setLayoutParams设置宽度成功");
}
}
} catch (e) {
errorMessages.push("方法4: " + (e.message || String(e)));
}
}
// 方法5: 尝试使用layout方法直接设置位置和大小
if (!widthSetSuccessfully) {
try {
if (this.mainContainer && typeof this.mainContainer.layout === 'function') {
var left = 0;
var top = 0;
try {
left = this.mainContainer.getLeft();
top = this.mainContainer.getTop();
} catch (positionError) {
// 使用默认位置
}
var pixelWidth = Math.round(targetWidth * getDensity());
var height = 0;
try {
height = this.mainContainer.getHeight();
} catch (heightError) {
height = 100; // 默认高度
}
this.mainContainer.layout(left, top, left + pixelWidth, top + height);
widthSetSuccessfully = true;
printl("方法5: 使用layout方法设置宽度成功");
}
} catch (e) {
errorMessages.push("方法5: " + (e.message || String(e)));
}
}
// 尝试UI刷新方法
if (widthSetSuccessfully) {
try {
if (this.ui && typeof this.ui.updateLayout === 'function') {
this.ui.updateLayout();
printl("UI布局已更新");
} else if (this.mainContainer && typeof this.mainContainer.requestLayout === 'function') {
this.mainContainer.requestLayout();
printl("请求重新布局");
} else if (this.mainContainer && typeof this.mainContainer.invalidate === 'function') {
this.mainContainer.invalidate();
printl("视图已刷新");
}
} catch (e) {
printl("刷新布局失败: " + e);
}
}
// 设置按钮文本
if (this.toggleButton && typeof this.toggleButton.setText === 'function') {
try {
this.toggleButton.setText("≡");
} catch (e) {
printl("❌ 设置按钮文本失败: " + e);
}
}
// 延迟100ms后记录状态更新,确保UI已更新
setTimeout(function() {
try {
if (widthSetSuccessfully) {
printl("✅ " + (self.isExpanded ? "侧栏已展开" : "侧栏已收起"));
} else {
// 只记录第一个错误信息,避免日志过多
var mainError = errorMessages.length > 0 ? errorMessages : "未知错误";
printl(mainError);
printl("⚠️ 侧栏" + (self.isExpanded ? "展开" : "收起") + "但宽度调整失败");
}
} catch (e) {
// 静默处理日志错误
}
}, 100);
return widthSetSuccessfully;
} catch (e) {
printl("❌ 执行切换展开/收起操作失败: " + e);
return false;
}
};
// 添加日志
侧栏日志.prototype.log = function(message, color) {
try {
// 生成时间戳
var now = new Date();
var timeStr = now.getHours().toString().padStart(2, '0') + ":" +
now.getMinutes().toString().padStart(2, '0') + ":" +
now.getSeconds().toString().padStart(2, '0');
// 格式化日志条目
var logEntry = "[" + timeStr + "] " + message;
// 添加到日志数组
this.logs.push({text: logEntry, color: color || "#00FF00"});
// 限制日志数量
if (this.logs.length > this.maxLogs) {
this.logs.shift(); // 移除最早的日志
}
// 更新显示
this.updateLogDisplay();
// 同时打印到控制台
printl(logEntry);
} catch (e) {
printl("❌ 添加日志失败: " + e);
}
};
// 更新日志显示
侧栏日志.prototype.updateLogDisplay = function() {
try {
var self = this;
var uiOperation = function() {
self.performUpdateLogDisplay();
};
// 尝试多种UI线程调度方案
var threadScheduled = false;
// 方案1: 使用context.runOnUiThread
try {
if (context && context.runOnUiThread) {
var runnable = {
run: function() {
try {
uiOperation();
} catch (e) {
printl("❌ UI线程执行日志更新失败: " + e);
}
}
};
context.runOnUiThread(runnable);
threadScheduled = true;
}
} catch (e) {
printl("❌ 方案1: context.runOnUiThread调度日志更新失败: " + e);
}
// 方案2: 使用View.post
if (!threadScheduled) {
try {
var viewToUse = self.logText || self.logContainer || self.mainContainer;
if (viewToUse && viewToUse.post) {
viewToUse.post(function() {
try {
uiOperation();
} catch (e) {
printl("❌ View.post执行日志更新失败: " + e);
}
});
threadScheduled = true;
}
} catch (e) {
printl("❌ 方案2: View.post调度日志更新失败: " + e);
}
}
// 方案3: 尝试使用Handler
if (!threadScheduled) {
try {
if (typeof Handler !== 'undefined' && typeof Looper !== 'undefined' && Looper.getMainLooper) {
var handler = new Handler(Looper.getMainLooper());
handler.post(function() {
try {
uiOperation();
} catch (e) {
printl("❌ Handler执行日志更新失败: " + e);
}
});
threadScheduled = true;
}
} catch (e) {
printl("❌ 方案3: Handler调度日志更新失败: " + e);
}
}
// 方案4: 直接执行作为最后备选
if (!threadScheduled) {
try {
uiOperation();
} catch (directError) {
printl("❌ 直接执行日志更新失败: " + directError);
}
}
} catch (e) {
printl("❌ 更新日志显示失败: " + e);
}
};
// 执行日志显示更新的核心方法(应在主线程中调用)
侧栏日志.prototype.performUpdateLogDisplay = function() {
try {
// 检查logText是否存在
if (!this.logText || typeof this.logText.setText !== 'function') {
printl("⚠️ 日志显示组件不可用");
return;
}
// 构建日志文本
var logText = "";
var useHtml = false;
// 尝试HTML格式
try {
if (typeof android.text.Html !== 'undefined' && typeof android.text.Html.fromHtml === 'function') {
var htmlText = "";
for (var i = 0; i < this.logs.length; i++) {
var log = this.logs;
var color = log.color || "#00FF00";
htmlText += "<font color=\"" + color + "\">" + log.text + "</font><br/>";
}
try {
var spanned = android.text.Html.fromHtml(htmlText);
this.logText.setText(spanned);
useHtml = true;
printl("✅ 日志使用HTML格式显示");
} catch (htmlError) {
printl("⚠️ HTML格式化失败,回退到纯文本: " + htmlError);
}
}
} catch (e) {
printl("⚠️ HTML支持不可用: " + e);
}
// 如果HTML格式失败,使用纯文本格式
if (!useHtml) {
for (var i = 0; i < this.logs.length; i++) {
logText += this.logs.text + "\n";
}
try {
this.logText.setText(logText);
printl("✅ 日志使用纯文本格式显示");
} catch (textError) {
printl("❌ 设置日志文本失败: " + textError);
}
}
// 尝试滚动到底部
var self = this;
try {
if (this.logContainer && typeof this.logContainer.post === 'function') {
this.logContainer.post(function() {
try {
if (self.logContainer && typeof self.logContainer.fullScroll === 'function') {
self.logContainer.fullScroll(android.widget.ScrollView.FOCUS_DOWN);
}
} catch (scrollError) {
// 静默处理滚动错误
}
});
} else if (this.logContainer && typeof this.logContainer.fullScroll === 'function') {
this.logContainer.fullScroll(android.widget.ScrollView.FOCUS_DOWN);
}
} catch (e) {
// 静默处理滚动错误
}
} catch (e) {
printl("❌ 执行日志显示更新失败: " + e);
}
};
// 设置悬浮窗位置
侧栏日志.prototype.setPos = function(x, y) {
try {
var self = this;
// 参数验证
if (typeof x !== 'number' || typeof y !== 'number') {
printl("❌ setPos参数错误: x和y必须是数字");
return false;
}
// 边界检查
var currentWidth = this.isExpanded ? this.sidebarWidth : this.sidebarMinWidth;
try {
if (context && context.getResources && context.getResources().getDisplayMetrics) {
var density = context.getResources().getDisplayMetrics().density;
currentWidth *= density;
}
} catch (e) {
currentWidth *= 3; // 使用默认密度倍数
}
if (x < 0) x = 0;
if (y < 0) y = 0;
if (x > this.screenWidth - currentWidth) x = this.screenWidth - currentWidth;
if (y > this.screenHeight - 100) y = this.screenHeight - 100;
// 使用printl避免递归调用
printl("🔄 设置悬浮窗位置: x=" + x + ", y=" + y);
// 定义UI操作函数
var uiOperation = function() {
self.performSetPos(x, y);
};
// 尝试多种UI线程调度方案
var threadScheduled = false;
// 方案1: 使用context.runOnUiThread
try {
if (context && context.runOnUiThread) {
var runnable = {
run: function() {
try {
uiOperation();
} catch (e) {
printl("❌ UI线程执行位置设置失败: " + e);
}
}
};
context.runOnUiThread(runnable);
threadScheduled = true;
printl("✅ 使用context.runOnUiThread调度位置设置");
}
} catch (e) {
printl("❌ 方案1: context.runOnUiThread调度位置设置失败: " + e);
}
// 方案2: 使用View.post
if (!threadScheduled) {
try {
var viewToUse = self.mainContainer || self.titleBar || self.toggleButton;
if (viewToUse && typeof viewToUse.post === 'function') {
viewToUse.post(function() {
try {
uiOperation();
} catch (e) {
printl("❌ View.post执行位置设置失败: " + e);
}
});
threadScheduled = true;
printl("✅ 使用View.post调度位置设置");
}
} catch (e) {
printl("❌ 方案2: View.post调度位置设置失败: " + e);
}
}
// 方案3: 尝试使用Handler
if (!threadScheduled) {
try {
if (typeof Handler !== 'undefined' && typeof Looper !== 'undefined' && Looper.getMainLooper) {
var handler = new Handler(Looper.getMainLooper());
handler.post(function() {
try {
uiOperation();
} catch (e) {
printl("❌ Handler执行位置设置失败: " + e);
}
});
threadScheduled = true;
printl("✅ 使用Handler调度位置设置");
}
} catch (e) {
printl("❌ 方案3: Handler调度位置设置失败: " + e);
}
}
// 方案4: 直接执行作为最后备选
if (!threadScheduled) {
printl("⚠️ 所有线程调度方案失败,尝试直接执行位置设置");
try {
uiOperation();
} catch (directError) {
printl("❌ 直接执行位置设置失败: " + directError);
}
}
return true;
} catch (e) {
printl("❌ 设置位置失败: " + e);
return false;
}
};
// 执行设置位置的核心方法(应在主线程中调用)
侧栏日志.prototype.performSetPos = function(x, y) {
try {
var posSetSuccess = false;
// 方案1: 尝试使用floatUI的setPos方法
try {
if (this.ui && this.ui.setPos) {
this.ui.setPos(x, y);
posSetSuccess = true;
printl("✅ 方案1: 使用floatUI.setPos设置位置成功");
}
} catch (e) {
printl("❌ 方案1: floatUI.setPos失败: " + e);
}
// 方案2: 尝试使用floatUI的setPosition方法
if (!posSetSuccess) {
try {
if (this.ui && this.ui.setPosition) {
this.ui.setPosition(x, y);
posSetSuccess = true;
printl("✅ 方案2: 使用floatUI.setPosition设置位置成功");
}
} catch (e) {
printl("❌ 方案2: floatUI.setPosition失败: " + e);
}
}
// 方案3: 尝试使用setX和setY方法(如果可用)
if (!posSetSuccess) {
try {
if (this.ui && typeof this.ui.setX === 'function' && typeof this.ui.setY === 'function') {
this.ui.setX(x);
this.ui.setY(y);
posSetSuccess = true;
printl("✅ 方案3: 使用ui.setX/setY设置位置成功");
}
} catch (e) {
printl("❌ 方案3: ui.setX/setY失败: " + e);
}
}
// 方案4: 尝试通过mainContainer设置位置
if (!posSetSuccess) {
try {
if (this.mainContainer && typeof this.mainContainer.setX === 'function' && typeof this.mainContainer.setY === 'function') {
this.mainContainer.setX(x);
this.mainContainer.setY(y);
posSetSuccess = true;
printl("✅ 方案4: 使用mainContainer.setX/setY设置位置成功");
}
} catch (e) {
printl("❌ 方案4: mainContainer.setX/setY失败: " + e);
}
}
// 方案5: 尝试通过直接访问mainContainer设置位置
if (!posSetSuccess) {
try {
if (this.mainContainer && typeof this.mainContainer.layout === 'function' && typeof this.mainContainer.getWidth === 'function' && typeof this.mainContainer.getHeight === 'function') {
this.mainContainer.layout(x, y, x + this.mainContainer.getWidth(), y + this.mainContainer.getHeight());
posSetSuccess = true;
printl("✅ 方案5: 使用layout方法设置位置成功");
}
} catch (e) {
printl("❌ 方案5: layout方法失败: " + e);
}
}
// 刷新UI确保位置更新生效
if (posSetSuccess) {
try {
// 尝试多种刷新方法
if (this.mainContainer) {
if (typeof this.mainContainer.invalidate === 'function') {
this.mainContainer.invalidate();
}
if (typeof this.mainContainer.requestLayout === 'function') {
this.mainContainer.requestLayout();
}
}
printl("✅ 位置设置刷新完成");
} catch (refreshError) {
printl("⚠️ 刷新位置时出错: " + refreshError);
}
} else {
printl("⚠️ 位置设置完成但可能未生效");
}
return posSetSuccess;
} catch (e) {
printl("❌ 执行位置设置失败: " + e);
return false;
}
};
// 清空日志
侧栏日志.prototype.clearLogs = function() {
try {
// 清空日志数组
this.logs = [];
// 清空日志显示
if (this.logText && this.logText.setText) {
try {
this.logText.setText("");
} catch (setTextError) {
printl("⚠️ 清空日志显示失败: " + setTextError);
}
}
// 记录清空操作
this.log("🗑️ 日志已清空", "#FF0000");
return true;
} catch (e) {
printl("❌ 清空日志失败: " + e);
return false;
}
};
// 关闭悬浮窗
侧栏日志.prototype.close = function() {
try {
var self = this;
// 使用printl避免递归调用
printl("🔄 正在关闭侧栏日志悬浮窗...");
// 定义UI操作函数
var uiOperation = function() {
self.performClose();
};
// 尝试多种UI线程调度方案
var threadScheduled = false;
// 方案1: 使用context.runOnUiThread
try {
if (context && context.runOnUiThread) {
var runnable = {
run: function() {
try {
uiOperation();
} catch (e) {
printl("❌ UI线程执行关闭操作失败: " + e);
}
}
};
context.runOnUiThread(runnable);
threadScheduled = true;
printl("✅ 使用context.runOnUiThread调度关闭操作");
}
} catch (e) {
printl("❌ 方案1: context.runOnUiThread调度关闭操作失败: " + e);
}
// 方案2: 使用View.post
if (!threadScheduled) {
try {
var viewToUse = self.mainContainer || self.titleBar || self.toggleButton;
if (viewToUse && typeof viewToUse.post === 'function') {
viewToUse.post(function() {
try {
uiOperation();
} catch (e) {
printl("❌ View.post执行关闭操作失败: " + e);
}
});
threadScheduled = true;
printl("✅ 使用View.post调度关闭操作");
}
} catch (e) {
printl("❌ 方案2: View.post调度关闭操作失败: " + e);
}
}
// 方案3: 尝试使用Handler
if (!threadScheduled) {
try {
if (typeof Handler !== 'undefined' && typeof Looper !== 'undefined' && Looper.getMainLooper) {
var handler = new Handler(Looper.getMainLooper());
handler.post(function() {
try {
uiOperation();
} catch (e) {
printl("❌ Handler执行关闭操作失败: " + e);
}
});
threadScheduled = true;
printl("✅ 使用Handler调度关闭操作");
}
} catch (e) {
printl("❌ 方案3: Handler调度关闭操作失败: " + e);
}
}
// 方案4: 直接执行作为最后备选
if (!threadScheduled) {
printl("⚠️ 所有线程调度方案失败,尝试直接执行关闭操作");
try {
uiOperation();
} catch (directError) {
printl("❌ 直接执行关闭操作失败: " + directError);
}
}
} catch (e) {
printl("❌ 关闭侧栏日志悬浮窗失败: " + e);
}
};
// 执行关闭操作的核心方法(应在主线程中调用)
侧栏日志.prototype.performClose = function() {
try {
printl("🔄 执行悬浮窗关闭操作...");
// 尝试多种关闭方案
var closeSuccess = false;
// 方案1: 尝试使用close方法
try {
if (this.ui && typeof this.ui.close === 'function') {
this.ui.close();
closeSuccess = true;
printl("✅ 方案1: 使用ui.close()成功关闭");
}
} catch (e) {
printl("❌ 方案1: 使用ui.close()关闭失败: " + e);
}
// 方案2: 尝试使用destroy方法
if (!closeSuccess) {
try {
if (this.ui && typeof this.ui.destroy === 'function') {
this.ui.destroy();
closeSuccess = true;
printl("✅ 方案2: 使用ui.destroy()成功关闭");
}
} catch (e) {
printl("❌ 方案2: 使用ui.destroy()关闭失败: " + e);
}
}
// 方案3: 尝试从父容器移除
if (!closeSuccess) {
try {
if (this.mainContainer && typeof this.mainContainer.getParent === 'function') {
var parent = this.mainContainer.getParent();
if (parent && typeof parent.removeView === 'function') {
parent.removeView(this.mainContainer);
closeSuccess = true;
printl("✅ 方案3: 从父容器移除成功");
}
}
} catch (e) {
printl("❌ 方案3: 从父容器移除失败: " + e);
}
}
// 方案4: 尝试隐藏视图
if (!closeSuccess) {
try {
if (this.mainContainer && typeof this.mainContainer.setVisibility === 'function') {
this.mainContainer.setVisibility(View.GONE);
closeSuccess = true;
printl("✅ 方案4: 隐藏视图成功");
}
} catch (e) {
printl("❌ 方案4: 隐藏视图失败: " + e);
}
}
// 清理资源
try {
// 清除事件监听器
if (this.titleBar && typeof this.titleBar.setOnTouchListener === 'function') {
this.titleBar.setOnTouchListener(null);
}
if (this.toggleButton && typeof this.toggleButton.setOnClickListener === 'function') {
this.toggleButton.setOnClickListener(null);
}
if (this.closeButton && typeof this.closeButton.setOnClickListener === 'function') {
this.closeButton.setOnClickListener(null);
}
// 清除引用,帮助垃圾回收
this.ui = null;
this.mainContainer = null;
this.titleBar = null;
this.toggleButton = null;
this.closeButton = null;
this.titleText = null;
this.logContainer = null;
this.logText = null;
this.logs = null;
printl("✅ 资源清理完成");
} catch (cleanupError) {
printl("⚠️ 资源清理时出错: " + cleanupError);
}
// 更新状态
sidebarLogger = null;
// 记录关闭结果
if (closeSuccess) {
printl("✅ 侧栏日志悬浮窗已成功关闭");
} else {
printl("⚠️ 侧栏日志悬浮窗尝试关闭,但可能未完全成功");
}
return closeSuccess;
} catch (e) {
printl("❌ 执行关闭操作失败: " + e);
return false;
}
};
// 创建并启动侧栏日志悬浮窗
var sidebarLogger = null;
// 版本信息
const SIDEBAR_LOGGER_VERSION = "1.2.0";
// 初始化悬浮窗
function initSidebarLogger(options) {
try {
// 防止重复初始化
if (sidebarLogger) {
printl("⚠️ 侧栏日志已经初始化,无需重复创建");
return sidebarLogger;
}
// 合并默认选项和用户选项
options = options || {};
// 环境检查
if (typeof floatUI === 'undefined') {
printl("❌ 错误:未找到floatUI库,请确保在AIWROK环境中运行!");
return null;
}
// 打印启动信息
printl("====================================");
printl("🔄 侧栏日志悬浮窗初始化中...");
printl("📱 版本: " + SIDEBAR_LOGGER_VERSION);
printl("====================================");
// 创建悬浮窗实例
sidebarLogger = new 侧栏日志();
// 创建悬浮窗
if (sidebarLogger.create()) {
printl("✅ 侧栏日志悬浮窗已创建成功!");
// 添加欢迎日志
sidebarLogger.log("🎉 欢迎使用侧栏日志工具", "#00FFFF");
sidebarLogger.log("📱 版本: " + SIDEBAR_LOGGER_VERSION, "#00FFFF");
sidebarLogger.log("💡 点击≡按钮展开/收起侧栏", "#FFFF00");
sidebarLogger.log("🔄 拖动标题栏可移动悬浮窗", "#FFFF00");
sidebarLogger.log("🗑️ 右上角关闭按钮可关闭悬浮窗", "#FFFF00");
sidebarLogger.log("💡 可使用sidebarLogger.log()添加自定义日志", "#00FF00");
// 自动展开悬浮窗,让用户看到关闭按钮
try {
setTimeout(function() {
if (sidebarLogger && typeof sidebarLogger.toggleExpand === 'function') {
sidebarLogger.toggleExpand();
}
}, 500);
} catch (autoExpandError) {
printl("⚠️ 自动展开失败: " + autoExpandError);
}
return sidebarLogger;
} else {
printl("❌ 侧栏日志悬浮窗创建失败!");
sidebarLogger = null;
return null;
}
} catch (e) {
printl("❌ 初始化侧栏日志失败: " + e);
sidebarLogger = null;
return null;
}
}
// 安全获取侧栏日志实例
function getSidebarLogger() {
return sidebarLogger;
}
// 安全地记录日志(即使悬浮窗未初始化也不会报错)
function safeLog(message, color) {
if (sidebarLogger && typeof sidebarLogger.log === 'function') {
try {
sidebarLogger.log(message, color);
return true;
} catch (e) {
printl("⚠️ 记录日志失败: " + e);
}
}
// 降级到console.log
printl(message || "");
return false;
}
// 启动悬浮窗
try {
// 延迟初始化,确保环境准备就绪
setTimeout(function() {
initSidebarLogger();
}, 100);
} catch (startupError) {
printl("❌ 启动悬浮窗失败: " + startupError);
// 作为最后的备选,尝试直接初始化
try {
initSidebarLogger();
} catch (finalError) {
printl("❌ 直接初始化也失败: " + finalError);
}
}
页:
[1]