Android - html input loses focus when soft keyboar

2019-01-25 06:05发布

问题:

I've written a web-page login form in ASP.net.

Using a Nexus 4, stock Android 4.2.1, native Chrome browser - when I click on the <input> fields, the soft keyboard appears and then the field immediately loses focus. I have to click the <input> field again with the keyboard already open to actually enter text.

This doesn't happen in Chrome on a desktop.

I have the following login form in an ASP user control:

<asp:Login ID="login_form" runat="server" OnLoginError="OnFail" OnLoggedIn="OnLoggedIn" RenderOuterTable="false" RememberMeSet="True">
    <LayoutTemplate>

        <asp:Panel runat="server" DefaultButton="LoginButton" CssClass="members-login">
            <fieldset>
                <label for="UserName">Username</label>
                <asp:TextBox ID="username" placeholder="e.g. joebloggs12" runat="server"></asp:TextBox>

                <label for="Password">Password</label>
                <asp:TextBox ID="password" runat="server" placeholder="e.g. 1234" TextMode="Password"></asp:TextBox>

                <label id="RememberMe">Remember me</label>
                <asp:CheckBox ID="RememberMe" runat="server" />

                <asp:Button CssClass="button" ID="LoginButton" runat="server" CommandName="Login" Text="SUBMIT" />
            </fieldset>
        </asp:Panel>         
    </LayoutTemplate>
</asp:Login>

which appears to the browser like this:

<div class="members-login" onkeypress="javascript:return WebForm_FireDefaultButton(event, &#39;ContentPlaceHolderDefault_contentBody_masterContent_login_form_LoginButton&#39;)">

    <fieldset>
        <label for="UserName">Username</label>
        <input name="ctl00$ctl00$ctl00$ContentPlaceHolderDefault$contentBody$masterContent$login_form$username" type="text" id="ContentPlaceHolderDefault_contentBody_masterContent_login_form_username" placeholder="e.g. joebloggs12" />

        <label for="Password">Password</label>
        <input name="ctl00$ctl00$ctl00$ContentPlaceHolderDefault$contentBody$masterContent$login_form$password" type="password" id="ContentPlaceHolderDefault_contentBody_masterContent_login_form_password" placeholder="e.g. 1234" />

        <label id="RememberMe">Remember me</label>
        <input id="ContentPlaceHolderDefault_contentBody_masterContent_login_form_RememberMe" type="checkbox" name="ctl00$ctl00$ctl00$ContentPlaceHolderDefault$contentBody$masterContent$login_form$RememberMe" checked="checked" />

        <input type="submit" name="ctl00$ctl00$ctl00$ContentPlaceHolderDefault$contentBody$masterContent$login_form$LoginButton" value="SUBMIT" id="ContentPlaceHolderDefault_contentBody_masterContent_login_form_LoginButton" class="button" />
    </fieldset>
</div>  

My suspicion is that the ViewState is stealing focus somehow. But I tried event.stopPropogation() which didn't help.


Temporary fix

For now I've settled for a hacky fix, forcing focus back onto the <input> element 700 milliseconds after a click:

jQuery('input').bind('click',function(evt) {
    var focusClosure = (function(inputElem) {return function() {console.log(inputElem.focus());}}($(evt.target)));
    window.setTimeout(focusClosure, 700);
});

回答1:

I discovered this is nothing to do with ASP.net or ViewState.

When the Android keyboard appears, the browser window is resized - triggering the resize event.

I was running something similar to the following:

// Move the navigation on resize
$(window).bind('resize', function() {
    if(maxWidth <= 710px) {
        $('.nav').after($('.main-content'));
    }
});

This moved the navigation in the DOM. I guess this redraws the DOM and so causes anything in the DOM to lose focus. I stopped this from happening on resize - making it only happen on initial page load instead.



回答2:

I had a similar problem, my approach to prevent resize to execute if input is in focus solved the problem:

$(window).bind('resize', function() {
    if ($("input").is(":focus")) {
        // input is in focus, don't do nothing or input loses focus and keyboard dissapears
    } else {
        // do whatever you should do if resize happens
    }
});


回答3:

I have find other solution

First you have to create a function

function getFocus(campo){
    $(window).bind('resize', function() {
        if(windowWidth <= 1025) {
            $(campo).focus();
        }
    }); 

}   

and when you click in an input you call the function

$('input').click(function(){
    getFocus(this); 
});

This works for me



回答4:

Requires jQuery

I've been having this problem myself, and ended up using this solution. It might be useful to someone else. In my case, the resizing made it so that the searchbar lost focus.

// Makes it so that click events are fired on a mobile device.
$('#searchbar').each(function(){
    this.onclick = function() {}
});

// Runs an interval 10 times with a 50ms delay. Forces focus.
$("#searchbar").click(function() {
    var i = 0;
    var interval = window.setInterval(function(){
        if(i > 10) {
            clearInterval(interval);
        }
        $("#searchbar").focus();
        i++;
    }, 50);
});


回答5:

For those who face this issue in WordPress, insert the following code into the header.

<script type="text/javascript">
 jQuery(function($) {
 $(window).bind('resize', function() {
 if ($("input").is(":focus")) {
 var focusClosure = (function(inputElem) {return function() 
 {console.log(inputElem.focus());}}($(evt.target)));
window.setTimeout(focusClosure, 700);
 } else {
    // Other resize functions
}
}); 
});
</script>


回答6:

I had custom code in my $(window).resize(..) that I wanted to keep, and I wanted to restrict this workaround to only the specific use case being impacted (Android mobile only, Text Input or TextArea focus), so I came up with this:

function isAndroidTextInputFocus() {
    var userAgent = navigator.userAgent.toLowerCase();
    var isAndroid = userAgent.indexOf("android") != -1;

    var result = (isAndroid && 
             ($("input[type=text]").is(":focus") || $("textarea").is(":focus"))     
           );

    return result;
}

and then I tweaked my $(window).resize(..) like this:

$(window).resize(function(e) {
    if (!isAndroidTextInputFocus()) {       
        // ... Proceed with my custom Window Resize logic
    }
});