최근 H5 채팅 프로젝트를 진행하면서 가장 큰 함정 중 하나에 직면했습니다. 입력 상자에 포커스가 걸리고 소프트 키보드가 팝업되며 입력 상자가 입력 방법에 흡착(또는 얹혀)되어야 합니다. 상자. 요구 사항은 매우 명확하고 단순해 보이지만 실제로는 그렇지 않습니다. 일부 모델을 실험한 결과 주로 다음과 같은 문제가 있음을 발견했습니다.
위에서 언급한 문제에 대한 해결책을 하나씩 살펴보겠습니다.
소프트 키보드의 팝업 및 철회 상태 가져오기소프트 키보드가 위인지 아래인지 아는 것이 중요하며, 이를 토대로 후속 호환성 처리가 이루어져야 합니다. 그러나 H5는 소프트 키보드의 기본 이벤트를 직접 모니터링하지 않으며 소프트 키보드를 표시하거나 축소하여 페이지의 다른 측면의 성능을 간접적으로 모니터링할 수만 있습니다. 게다가 IOS와 안드로이드의 성능도 다릅니다.
IOS 소프트 키보드 팝업 성능iOS에서는 입력 상자(input, textarea 또는 rich text)에 포커스가 가해졌을 때 키보드가 팝업되거나 페이지(webview)가 압축되지 않거나 높이(height)가 변하지 않지만 페이지(webview)가 다음과 같이 됩니다. 전체가 위로 스크롤됩니다. 그리고 최대 스크롤 높이(scrollTop)는 소프트 키보드 높이입니다.
Android 소프트 키보드 팝업 성능마찬가지로 Android에서는 입력 상자가 포커스를 받고 키보드가 팝업되지만 페이지(웹뷰)의 높이가 변경됩니다. 일반적으로 높이는 시각적 영역의 높이(원래 높이에서 소프트 키보드의 높이를 뺀 값)입니다. ), 단, 페이지 콘텐츠가 확장형이기 때문에 스크롤이 가능하지만 WebView 자체는 스크롤할 수 없습니다.
IOS 소프트 키보드 축소 성능소프트 키보드의 철회 버튼이나 입력 상자 외부의 페이지 영역이 트리거되면 입력 상자가 초점을 잃고 소프트 키보드가 축소됩니다.
Android 소프트 키보드 축소 성능입력 상자 외부 영역이 트리거되면 입력 상자가 초점을 잃고 소프트 키보드가 수납됩니다. 그러나 키보드의 철회 버튼이 실행되면 입력 상자는 초점을 잃지 않으며 소프트 키보드도 철회됩니다.
소프트 키보드의 팝업 및 축소를 모니터링합니다.IOS 및 Android에서 위의 다양한 키보드 팝업 및 축소 성능을 기반으로 다음 처리를 개별적으로 수행하여 소프트 키보드의 팝업 및 축소를 모니터링할 수 있습니다.
// 장치 유형 판단 var JudgeDeviceType = function () { var ua = window.navigator.userAgent.toLocaleLowerCase() var isIOS = /iphone|ipad|ipod/.test(ua) var isAndroid = /android/.test ( ua); return { isIOS: isIOS, isAndroid: isAndroid }}()// 입력 상자의 소프트 키보드 팝업 및 축소 이벤트 기능을 듣습니다. listeningKeybord($input) { if (judgeDeviceType.isIOS) { // IOS 키보드 팝업: IOS 및 Android 입력 상자가 포커스를 받고 키보드가 팝업됩니다. $input.addEventListener('focus', function () { console.log(' IOS 키보드 팝업! '); // IOS 키보드 팝업 후 동작}, false) // IOS 키보드 수납: IOS 입력 상자 외부를 클릭하거나 철회 버튼을 클릭하면 입력 상자가 포커스를 잃고 키보드가 철회됩니다. $input.addEventListener('blur', () => { console.log('IOS 키보드가 철회되었습니다!') ; // IOS 키보드를 접은 후의 동작 }) } // Andriod 키보드가 접히거나 접히면 페이지 높이가 변경되며, 이를 기준으로 키보드가 접힙니다. if (judgeDeviceType.isAndroid) { var OriginHeight = document.documentElement.clientHeight || document.body.clientHeight; window.addEventListener('resize', function () { var resizeHeight = document.documentElement.clientHeight || document.body.clientHeight; if (originHeight < resizeHeight) { console.log('Android 키보드를 치웠습니다!'); // Android 키보드를 치운 후의 작업} else { console.log('안드로이드 키보드가 뜹니다! '); // Android 키보드 팝업 후 작업} OriginHeight = resizeHeight; }, false) }}var $inputs = document.querySelectorAll('.input');for (var i = 0; i < $inputs.length; i++) { listeningKeybord($inputs[i]);}소프트 키보드를 띄울 때 입력 상자는 항상 보이는 영역으로 스크롤됩니다.
때로는 입력 항목이 많은 입력 양식을 만들 수도 있습니다. 입력 상자가 포커스를 받고 소프트 키보드가 나타납니다. 입력창이 페이지 하단에 위치할 경우, IOS에서는 웹뷰 전체가 일정 거리만큼 롤업되어 포커스가 맞춰진 입력창이 자동으로 보이는 영역에 위치하게 되지만, 안드로이드에서는 그렇지 않습니다. . 현재 초점이 맞춰진 요소를 가시 영역으로 스크롤하지 않고 페이지 높이만 변경합니다.
위 내용은 IOS 및 Android 키보드의 팝업 및 축소를 모니터링하도록 구현되었으므로 여기서는 Android 키보드가 팝업된 후 포커스 요소를 시각적 영역으로 스크롤(scrollIntoView())하기만 하면 됩니다. 효과를 보려면 여기를 클릭하세요.
// 포커스 요소를 가져오고 표시 영역으로 스크롤 function activeElementScrollIntoView(activeElement, Delay) { var editable = activeElement.getAttribute('contenteditable') // 가져오기 후에 입력 상자, 텍스트 영역 또는 서식 있는 텍스트가 표시 영역으로 스크롤되지 않습니다. 포커스 영역 if (activeElement.tagName == 'INPUT' || activeElement.tagName == 'TEXTAREA' || editable === '' || editable) { setTimeout(function () { activeElement.scrollIntoView(); }, Delay) }}// ...// activeElementScrollIntoView($input, 1000);// ... Android 키보드가 나타난 후 작동순수한 숫자 소프트 키보드를 연상시키다
위의 양식 입력 상자에는 전화번호를 입력해야 합니다. 이와 유사하게 숫자 소프트 키보드가 나타납니다. 여기서는 소프트 키보드 호환성에 대해 설명하겠습니다. 더 나은 해결책은 다음과 같습니다.
<p>휴대폰번호를 입력하세요</p><input type=tel novalidate=novalidate Pattern=[0-9]* class=input>
IOS12 및 V6.7.4+ 버전의 WeChat 브라우저를 사용하여 위의 양식 입력 데모를 열면 키보드를 집어넣은 후 원래 위로 스크롤했던 페이지가 아래쪽 위치로 돌아가지 않는 것을 보고 놀랄 것입니다. 바운스할 원래 키보드가 시작 위치가 비어 있습니다.
실제로 이는 iOS의 Apple 버그이며 Xcode10과 함께 패키지된 모든 IOS12 장치에 나타납니다. WeChat은 공식적으로 해결책을 제시했습니다. 소프트 키보드를 닫은 후 페이지(webview)를 창 아래쪽 위치(clientHeight 위치)로 다시 스크롤하면 됩니다. 위의 수정된 양식 입력 데모는 여기를 클릭할 수 있습니다.
console.log('IOS 키보드가 치워졌습니다!');// WeChat 브라우저 버전 6.7.4+IOS12에서는 키보드를 치운 후 보기가 위로 밀렸지만 아래로 밀리지 않은 것을 표시합니다. var wechatInfo = window.navigator.userAgent .match( /MicroMessenger//([/d/.]+)/i);if (!wechatInfo) return;var wechatVersion = wechatInfo[1];var 버전 = (navigator.appVersion).match(/OS (/d+)_(/d+)_?(/d+)?/);if (+wechatVersion.replace(//./g, '') >= 674 && +version[1] >= 12) { window.scrollTo(0, Math.max(document.body.clientHeight, document.documentElement.clientHeight));}타사 입력 방법과 호환 가능
이상으로 사실 H5 채팅 입력창의 문제점은 절반 이상 해결되었습니다. 다음으로 채팅 입력창의 기본 HTML 구조를 살펴보겠습니다.
<div class=chat__content> <div> <p>채팅 내용 일부 1</p> </div> <!--채팅 내용 수천줄 생략--></div><div class=input__content> <div class =input contenteditable=true></div> <버튼>보내기</button></div>
스타일
/* 일부 스타일 생략 */.chat__content { height: calc(100% - 40px); margin-bottom: 40px;overflow-x:hidden;}.input__content {display: flex: 40px; position: 절대; 왼쪽: 0; 아래쪽: 0; align-items: center;}/* 일부 스타일 생략
매우 간단합니다. 입력 영역은 절대적으로 위치합니다. 위의 양식 입력 데모 방법에 따르면 대부분의 Android 브라우저는 괜찮지만 테스트는 IOS에서 이루어졌습니다. 기본 입력 방법 및 타사 입력 방법(예: Sogou 입력 방법)의 경우 입력 상자가 완전히 차단됩니다. QQ 브라우저 또는 WeChat 브라우저에서는 타사 입력 방법을 사용하면 입력 상자가 절반으로 차단됩니다. Baidu 브라우저를 사용하면 타사 입력 방법을 사용하면 입력 상자가 차단됩니다. 또한 완전히 가려집니다. 효과를 보려면 해당 브라우저에서 여기를 방문하세요.
UC 브라우저에서는 소프트 키보드가 팝업된 후 브라우저 위의 제목 표시줄 높이가 높이가 감소하는 지연 동적 효과를 가져서 웹뷰가 약간 아래로 스크롤되고 하단 입력 상자가 비-스크롤로 스크롤됩니다. 보이는 영역.
타사 입력방식의 경우 입력방식 패널 팝업 후 높이 계산이 잘못되어 웹뷰의 초기 스크롤 위치가 잘못된 것으로 추측됩니다. 실제로 이 두 가지 점은 웹뷰가 제자리에서 스크롤되지 않기 때문에 발생합니다. 소프트 키보드가 나타난 후 포커스 요소를 다시 표시 영역으로 스크롤하여 WebView가 제자리로 돌아가도록 할 수 있습니다.
console.log('안드로이드 키보드가 떴어요!');activeElementScrollIntoView($input, 1000);Android Xiaomi 브라우저와 호환되는 해킹 솔루션
Android의 Xiaomi 브라우저에서 위의 솔루션을 적용한 후 채팅 입력 상자가 여전히 단단히 차단되어 있고 scrollIntoView()가 여전히 움직이지 않는 것을 발견했습니다. 그래서 실제로는 소프트 키보드가 아래쪽으로 스크롤되었기 때문인 것으로 추측되며, 소프트 키보드가 팝업될 때 페이지 높이가 시각적 영역의 높이보다 더 커지기 때문에 페이지 높이를 강제로 늘릴 수만 있습니다. 소프트 키보드가 팝업되어 입력 상자가 표시됩니다. 위 내용을 바탕으로 타사 입력 방법과 호환되므로 효과를 보려면 여기를 클릭하세요.
// Andriod 키보드 축소: Andriod 키보드가 팝업되거나 축소될 때 페이지 높이가 변경됩니다. 이를 기반으로 키보드 축소가 알려져 있습니다. if (judgeDeviceType.isAndroid) { var OriginHeight = document.documentElement.clientHeight || body.clientHeight ; window.addEventListener('resize', function () { var resizeHeight = document.documentElement.clientHeight || document.body.clientHeight; if (originHeight < resizeHeight) { console.log('Android 키보드가 닫혔습니다!') // Xiaomi 브라우저의 입력 방법에 의해 입력 상자가 여전히 차단되는 문제 수정 if (judgeDeviceType.isMiuiBrowser ) { document.body.style.marginBottom = '0px'; } } else { console.log('Android 키보드가 나타납니다!') // Xiaomi 브라우저의 입력 방법에 의해 입력 상자가 여전히 차단되는 문제 수정 if (judgeDeviceType.isMiuiBrowser) { document.body.style.marginBottom = '40px' } activeElementScrollIntoView($input, 1000); }, 거짓 )}요약
H5 엔드에는 갈 길이 멀고 함정도 많기 때문에 계속해서 노력해야 합니다. IOS와 Android의 소프트 키보드 팝업 페이지 간의 성능 차이를 이해하는 것이 전제 조건입니다. 두 번째 단계는 포커스 요소를 보이는 영역으로 스크롤하는 것입니다. 동시에 타사 입력 방법과 일부 브라우저의 차이점도 있습니다. 고려해야합니다.
위 내용은 이 기사의 전체 내용입니다. 모든 분들의 학습에 도움이 되기를 바랍니다. 또한 모든 분들이 VeVb Wulin Network를 지지해 주시길 바랍니다.