Xamarin.UITest在三星设备上无法对Acr.UserDialogs弹窗输入文本
Xamarin.UITest 三星设备Acr.UserDialogs输入操作失效解决方案
问题表现
- 三星设备上对Acr.UserDialogs弹窗的输入框调用
app.ClearText()、app.EnterText()无响应,同逻辑在Pixel类原生系统设备上运行正常 - 尝试直接调用控件方法
app.Query(e => e.Id("custom").Invoke("setText", string.Empty))赋值无效
问题根因
该问题是两个因素叠加导致:
- 三星OneUI定制ROM对非系统原生弹窗的辅助功能事件做了过滤,Xamarin.UITest默认的控件定位、输入注入逻辑依赖系统辅助能力,在该场景下无法触发控件真实响应
- Acr.UserDialogs的输入框内部做了事件绑定封装,直接调用
setText方法不会触发内部的TextChanged监听,业务层无法识别到文本变更,UI层也不会刷新输入状态
可行方案
按优先级从高到低排列:
- 测试桩注入方案(兼容性100%)
在App的测试编译版本中,为Acr.UserDialogs的弹窗逻辑增加测试专用调用入口:暴露一个静态方法直接修改弹窗绑定的上下文属性值,UITest中通过app.Invoke()直接调用该方法完成文本赋值,完全跳过UI层的控件操作,不存在设备兼容性问题。
测试入口示例代码(加在App测试变体的DialogHelper类中,正式版本通过编译宏排除):
public static void SetPromptDialogText(string targetText) { if (Acr.UserDialogs.Instance.CurrentDialog is PromptDialog dialog) { dialog.ViewModel.Text = targetText; } }
UITest端调用代码:
app.Invoke("SetPromptDialogText", "需要输入的测试文本");
- 焦点触发+物理键事件注入方案(无需修改App代码)
不方便修改App代码时,可绕过默认的输入方法,通过真实事件注入完成操作:
// 定位输入框控件 var inputRect = app.Query(e => e.Id("custom")).First().Rect; // 点击输入框中心位置,触发三星ROM的真实输入焦点 app.TapCoordinates(inputRect.CenterX, inputRect.CenterY); // 等待焦点稳定 Thread.Sleep(200); // 发送删除键清空原有内容,替代app.ClearText() for (int i = 0; i < 60; i++) { app.PressKey(Keycode.Del); } // 通过adb输入流注入文本,替代app.EnterText() app.AdbShellInput("需要输入的测试文本");
注:使用该方案前需在三星设备的系统设置中关闭「自动填充服务」「输入法安全防护」开关,避免系统拦截输入事件。
- 关闭硬件加速临时方案
在测试初始化阶段对当前Activity关闭硬件加速,修复OneUI部分版本下辅助功能树和实际渲染控件不匹配的问题:
app.CurrentActivity.Invoke("setHardwareAccelerated", false);
执行该设置后,部分设备上原生的app.EnterText()、app.ClearText()方法可恢复正常。
避坑提示
- 不要直接对Acr.UserDialogs的输入框调用
setText方法,该操作不会触发控件内部的文本变更事件,即使UI上显示了文本,业务逻辑也无法读取到输入值 - 不要在弹窗刚弹出时立刻执行输入操作,三星设备弹窗渲染比原生系统慢100-300ms,需加固定等待或者通过
app.WaitForElement()确认输入框完全加载后再操作
内容的提问来源于stack exchange,提问作者Moshe Moadeb
相关产品推荐
相关产品推荐

