You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MAUI安卓端切换.xaml页面后JavaScript .focus()函数失效问题

问题原因
  1. WebView焦点未恢复:从ScanningPage返回MainPage时,MAUI的WebView组件可能尚未重新获取安卓系统的原生焦点,此时调用DOM元素的focus()无法触发键盘唤起。
  2. 渲染时机不匹配:硬编码的Task.Delay(600)无法精准适配页面切换后的渲染流程,可能在弹窗DOM元素未完全渲染或WebView状态未稳定时执行focus操作。
  3. 异步方法设计缺陷:ViewPopup使用async void类型,会导致状态更新与Blazor渲染周期不同步,无法保证弹窗渲染完成后再执行焦点逻辑。
解决办法

1. 修正页面导航逻辑,移除无效循环

修改MainPage.xaml.cs的BeginScan方法,无需循环等待页面返回,PushAsync完成后页面返回会自动继续执行后续代码:

public async Task<string> BeginScan()
{
    await Navigation.PushAsync(new ScanningPage());
    return ScanningPage.UserDesiresManualEntry ? string.Empty : "null";
}

2. 优化Blazor异步方法调用

修改Blazor代码中的TogglePage和ViewPopup,确保状态更新与渲染同步:

protected async Task TogglePage()
{
    var navMain = Microsoft.Maui.Controls.Application.Current.MainPage as NavigationPage;
    var mainPageRoot = navMain.RootPage as MainPage;
    if (mainPageRoot == null) return;

    var returnValue = await mainPageRoot.BeginScan();
    if (ScanningPage.UserDesiresManualEntry)
    {
        await ViewPopup();
        ScanningPage.UserDesiresManualEntry = false;
    }
}

private async Task ViewPopup()
{
    CanSeePopup = true;
    NeedsToRender = true;
    StateHasChanged(); // 立即触发组件渲染
    await Task.Yield(); // 让UI线程优先完成渲染操作
}

3. 确保WebView获得原生焦点后再执行DOM聚焦

修改OnAfterRenderAsync方法,先让WebView获取安卓系统焦点,再调用JS聚焦逻辑:

protected override async Task OnAfterRenderAsync(bool firstRender)
{
    if (NeedsToRender && CanSeePopup)
    {
        // 获取BlazorWebView实例,需在MainPage.xaml中给BlazorWebView设置x:Name="BlazorWebView"
        var webView = Microsoft.Maui.Controls.Application.Current.MainPage.FindByName<Microsoft.Maui.Controls.WebView>("BlazorWebView");
        webView?.Focus(); // 让WebView获得原生焦点

        await Task.Yield(); // 等待焦点状态稳定
        var result = await JSR.InvokeAsync<string>("focusOnElement", "textInput");
        TempInputValue = $"{NeedsToRender} {CanSeePopup} {result}";
        
        NeedsToRender = false;
        StateHasChanged();
    }
}

4. 增强JS聚焦逻辑,确保元素就绪

更新Blazor中的JS函数,等待元素可见后再执行聚焦,并添加文本选中操作(安卓部分机型需要此步骤唤起键盘):

<script>
    async function focusOnElement(elementId) {
        var element = document.getElementById(elementId);
        if (!element) return `${elementId} not found`;
        
        // 等待元素在DOM中可见
        while (element.offsetParent === null) {
            await new Promise(resolve => setTimeout(resolve, 50));
        }
        
        element.focus();
        element.setSelectionRange(0, element.value.length); // 选中文本,确保键盘唤起
        return `${elementId} ${document.activeElement.id}`;
    }
</script>

5. 补充BlazorWebView命名

在MainPage.xaml中给BlazorWebView组件添加x:Name属性,确保代码能找到实例:

<BlazorWebView x:Name="BlazorWebView" HostPage="wwwroot/index.html">
    <BlazorWebView.Routes>
        <Route Route="/" ComponentType="{x:Type local:Main}" />
    </BlazorWebView.Routes>
</BlazorWebView>

内容的提问来源于stack exchange,提问作者Frasher Gray

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 00:52:03