鍵盤優雅彈出與ios光標亂飄解決方案


前言

在移動開發中,會遇到這樣的情況,比如說有一個輸入框在最底部的時候,我們彈起輸入框,輸入框不會在輸入鍵盤上。
說明白簡單點就是,輸入框被鍵盤擋住了。而且在原生中,輸入框應該正好在輸入鍵盤上,但是h5 沒有這種體驗,那么我們需要自己實現。
再次用圖說明情況。
情況一:

鍵盤擋住了,輸入框。

情況二:

紅色代表有滾動條,輸入框,沒有正好卡在下面,用戶體驗不好,同樣輸入的時候不能滑動體驗也不好。

開工

正確情況:

要做的其實就是兩步:

第一步,動態改變可滑動的高度,就是在輸入的時候可以通過滑動看到下面藍色的部分:

第二部,需要修改滾動距離:

也就是需要滾動多少,輸入框才剛好在鍵盤下。那這個怎么移動呢?我們該如何滾動才能完成呢?

計算滾動的距離,其實就是計算輸入框移動的距離。
這個問題就簡單了,分兩種情況,其實就一種哈。
假如輸入框在上面:

就是我們滑動塊的底部到頂部的距離-輸入框底部到頂部的距離

加入輸入框在鍵盤下面:

就不畫了,也是我們滑動塊的底部到頂部的距離-輸入框底部到頂部的距離,只不過我們得到的是負數,正好我們對應了我們滑動的方向。

好的,現在我們要做的就是實現這兩步。

如何修改鍵盤彈起的高度?

我們只要知道鍵盤的高度和屏幕的高度即可。

屏幕高度,我們不需要去知道,因為需要修改樣式,直接100vh-鍵盤高度即可。

鍵盤的高度如下:

window.addEventListener("keyboardWillShow", this.keyboardShowCallback);

在keyboardShowCallback有個參數是e:

public keyboardShowCallback = (e) => {
e.keyboardHeight;// 取得鍵盤的高度
})

在這里,因為我的滑動塊是全屏的,那么我可以這樣:

public keyboardShowCallback = (e) => {
//page 是我當前頁面的滑動塊,100vh就是屏幕高度
page.setAttribute('style', 'height:calc(100vh - ' + e.keyboardHeight + 'px) !important;z-index:150;');
})

那么如何獲取當前正在輸入的輸入框,只要獲取當前焦點的位置 document.activeElement:

var rect = document.activeElement.getBoundingClientRect();

通過getBoundingClientRect 獲取到輸入框各個位置到屏幕的距離:

我們需要的是輸入框的底部,那么就是: rect.bottom;

那么我們計算滑動距離就是:

scrolldiv//表示可滑動的元素

var scrolldivrect = scrolldiv.getBoundingClientRect();

var addScrollTop = rect.bottom - scrolldivrect.bottom;

scrolldiv.scrollTop = scrolldiv.scrollTop + addScrollTop;

接下來就是鍵盤收起來的時候恢復:

// 監聽鍵盤隱藏
window.addEventListener("keyboardWillHide", this.keyboardHideCallback);
//恢復事件
page.setAttribute('style', 'height: 100vh !important;z-index:120;');

在這里,其實就已經實現效果了,那么這時候會在一些平台上遇到一些問題。

遇到的問題

ios 光標亂飄

造成原因,是因為我們設置滑動了,在低版本如ipad mini3上會出現光標和輸入框不對應。

那么這個時候,我繼續輸入,或者我點一下其他地方光標又正常了。

這時候給了我線索,我需要重繪這個input 就行。那么如何重新繪制呢?我們無法操作啊。但是我們知道如果改變某些樣式是會觸發重繪過程,具體查看標准。

code 如下:

var activeElement = document.activeElement; //取得focus的dom元素
setTimeout(function () {
if (activeElement) {
  if (activeElement.nodeName == "TEXTAREA" || activeElement.nodeName == 'INPUT') { //如果是input或textarea
	if ((Object)(activeElement).style.textShadow === '') {
	  (Object)(activeElement).style.textShadow = 'rgba(0,0,0,0) 0 0 0'; //改變某個不可見樣式,觸發dom重繪
	} else {
	  (Object)(activeElement).style.textShadow = '';
	}
  }
}
}, 0);

收起鍵盤出現白屏,在低版本上連續彈起鍵盤白屏無消失

這個問題得回到設計的根源上。

在我們收起鍵盤的時候,我們就會讓紅色部分為100%;
鍵盤收齊向下,然后紅色向下,如果鍵盤收起速度,大於紅色向下增大的速度,就會出現一點白,然后消失。

怎么解決呢?

紅色部分是我們滾動的部分,藍色是content,這時候讓content設置為100%vh,這時候馬上可視區域就會馬上重繪。
在keyboardHideCallback 中

var num = Math.random() * 99;
ionContent.setAttribute('style', 'height: 100vh !important;z-index:' + num + '');

當然,然后要在keyboardShowCallback 中設置為100%,如何不設置回去,鍵盤彈起就會擋住輸入框:

var num = Math.random() * 99;
ionContent.setAttribute('style', 'height: 100% !important;z-index:' + num + '');

總結

如果要兼容一些低版本,需要主動觸發去讓一些區域刷新,這些可以解決大部分白屏問題,或者其他疑難雜症(如光標漂移)。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM