騰訊 AlloyTeam:移動端輸入框填坑系列(一)

騰訊雲加社群發表於2017-05-09

作者:yana@alloyteam

輸入在移動端是一個很常用的功能,那麼輸入框必然是一個很重要的部分。然而,移動端輸入框總會遇到各種各樣的問題,無論是樣式還是ios和android兩端體驗不一致都是很讓我們頭疼的問題,那麼如何使移動web的輸入框體驗更貼近原生也成了一個需要我們多多思考和研究的問題。

一、文字輸入限制問題

我們拿最多可輸入16個字為例。當輸入字數(注意,不是字元長度)超過16字時,會觸發tips提示,並且不能繼續輸入。
辦法一:
textarea可以使用maxlength進行輸入字數限制。
但是這個辦法只能單純的限制length,有時並不能真正的結局問題。
辦法二:
在將第二個辦法之前先來講講下面的幾種情況:
1、非直接的文字輸入
什麼叫做非直接的文字輸入呢?

騰訊 AlloyTeam:移動端輸入框填坑系列(一)
Alt text

當輸入漢字時必然會是非直接輸入,需要我們點選才能正式輸入。
當我們字數限制為16個字,需要實時檢查是否到16字。輸入文字時,當有非直接的文字輸入時,監聽keydown事件和input事件都會直接觸發判斷字數邏輯,會截斷我們正在輸入的文字。
解決辦法:
監聽compositionend(當直接的文字輸入時觸發)這時,當沒選中中文的時候不會進行字數判斷。
``

    $('#input').on('compositionend', function(e) {
        var len = $(this).val().length;
        if (len > 16) {
            // 提示超過16字
        }
    });複製程式碼

2、emoji表情的輸入
當輸入emoji的時候,但是,當輸入emoji表情的時候,js中判斷emoji表情的length為2,因此emoji正常應該最多隻能輸入8個,但是ios端卻把emoji的length算為1,可以輸入16個emoji。這樣就導致了兩端的體驗不同。因此需要在js中來進行字數限制。
再加上漢字輸入問題,那麼就加入一個標記位,來判斷是否是直接的文字輸入。然後監聽input,限制字數,當超過字數限制的時候,把前16個字截斷顯示出來就ok了。
``

var cpLock;
$('#input').on('compositionstart', function(e) {
    cpLock = true;
});
$('#input').on('compositionend', function(e) {
    cpLock = false;
});
$('#input').on('input', function(e) {
    if (!cpLock) {
        if (e.target.value.length - 17 >=0) {
            var txt = $(e.target).val().substring(0, 16);
            $(e.target).val(txt);
            // 超過16字提示
        }
    }
});複製程式碼

二、textarea置底展示問題

ios中的輸入體驗永遠伴隨著一個問題,就是當喚起鍵盤後,整個頁面會被鍵盤壓縮,也就是說頁面的高度變小,並且所有的fixed全部變為了absolute。
android效果:

騰訊 AlloyTeam:移動端輸入框填坑系列(一)

騰訊 AlloyTeam:移動端輸入框填坑系列(一)

騰訊 AlloyTeam:移動端輸入框填坑系列(一)

騰訊 AlloyTeam:移動端輸入框填坑系列(一)

使用fixed定位
可見android中喚起鍵盤是覆蓋在頁面上,不會壓縮頁面
在ios上的效果:

騰訊 AlloyTeam:移動端輸入框填坑系列(一)

騰訊 AlloyTeam:移動端輸入框填坑系列(一)

騰訊 AlloyTeam:移動端輸入框填坑系列(一)

騰訊 AlloyTeam:移動端輸入框填坑系列(一)

那麼如果我們需要將輸入框固定在螢幕下方,而當鍵盤被喚起同時輸入框固定在鍵盤上方(如下圖樣式)該如何解決呢?

騰訊 AlloyTeam:移動端輸入框填坑系列(一)

騰訊 AlloyTeam:移動端輸入框填坑系列(一)

首先我們來看下ios的表現

騰訊 AlloyTeam:移動端輸入框填坑系列(一)

可以看出,鍵盤會將頁面頂上去。那麼如果希望可以將輸入框和鍵盤完全貼合,我們可以使用div模擬一個假的輸入框,使用定位將真正的輸入框隱藏掉,當點選假的輸入框的時候,將真正的輸入框定位到鍵盤上方,並且手動獲取輸入框焦點。

在實現過程中需要注意下面幾個問題:
1、真正的輸入框的位置計算
首先記錄無鍵盤時的window.innerHeight,當鍵盤彈出後再獲取當前的window.innerHeight,兩者的差值即為鍵盤的高度,那麼定位真輸入框自然就很容易了
2、在ios下手動獲取焦點不可以用click事件,需要使用tap事件才可以手動觸發
``

    $('#fake-input').on($.os.ios?'tap' : 'click', function() {
        initHeight = window.innerHeight;
        $('#input').focus();
    });複製程式碼

3、當鍵盤收起的時候我們需要將真輸入框再次隱藏掉,除了使用失去焦點(blur)方法,還有什麼方法可以判斷鍵盤是否收起呢?
這裡可以使用setInterval監聽,噹噹前window.innerHeight和整屏高度相等的時候判斷為鍵盤收起。
注意:鍵盤彈起需要一點時間,所以計算當前螢幕高度也需要使用setInterval
4、因為textarea中的文字不能置底顯示,當輸入超過一行textarea需要自動調整高度,因此將scrollHeight賦值給textarea的height。當刪除文字的時候需要height也有變化,因此每次input都先將height置0,然後再賦值。
``

    $('#textarea').css('height', 0);
    $('#textarea').css('height', $('#textarea')[0].scrollHeight);複製程式碼

未完待續...

相關閱讀
踩坑記:當 JavaScript 遇上 UINT64
移動端tryjs異常捕獲
【騰訊TMQ】從0到1:打造移動端H5效能測試平臺


此文已由作者授權騰訊雲技術社群釋出,轉載請註明文章出處
原文連結:www.qcloud.com/community/a…
獲取更多騰訊海量技術實踐乾貨,歡迎大家前往騰訊雲技術社群

相關文章