предисловие
делал это недавноH5
Элементы чата наступили на одну из больших ям: поле ввода получает фокус, виртуальная клавиатура всплывает, а поле ввода должно быть адсорбировано (или перекрыто) в поле метода ввода. Требования очень четкие и вроде бы простые, но это не так. Из экспериментов на некоторых моделях установлено, что в основном возникают следующие проблемы:
- существует
Android
а такжеIOS
, узнайте, что существует разница между всплывающим и убранным состояниями программной клавиатуры и страницей.webview
вести себя иначе. - существует
IOS12
Включено, версия WeChatv6.7.4
и выше поле ввода получает фокус, клавиатура всплывает, страница (webview
) для прокрутки вверх в целом.Когда клавиатура сложена, она не возвращается в исходное положение, в результате чего остается пустое место, где изначально располагалась клавиатура. - существует
IOS
При использовании стороннего метода ввода происходит отклонение в расчете высоты, из-за чего некоторые методы ввода всплывают и блокируют часть поля ввода. - Используя некоторые навыки работы в некоторых браузерах, все еще есть поля ввода, заблокированные методом ввода.
Давайте рассмотрим решения по одному для вышеупомянутых проблем.
Получить состояние программной клавиатуры вверх и вниз
Очень важно знать, поднимается или убирается виртуальная клавиатура, и последующая обработка совместимости должна основываться на этом предположении. Однако,H5
Он не отслеживает напрямую исходные события программной клавиатуры, его можно только отбрасывать или убирать через программную клавиатуру, что запускает косвенный мониторинг других аспектов страницы и спасает страну за счет кривой. И вIOS
а такжеAndroid
Производительность не та.
IOS
Производительность всплывающих окон с мягкой клавиатурой
существуетIOS
На, введите поле (input
,textarea
или форматированный текст) получает фокус, появляется всплывающая клавиатура, страница (webview
) не сжат, либо высота (height
) не изменился, только страница (webview
) прокручивается вверх целиком, а максимальная высота прокрутки (scrollTop
) — высота программной клавиатуры.
Android
Производительность всплывающих окон с мягкой клавиатурой
Точно так же вAndroid
, поле ввода получает фокус, клавиатура всплывает, но страница (webview
) Высота изменится.Вообще говоря, высота - это высота видимой области (исходная высота минус высота программной клавиатуры), за исключением того, что прокрутка может происходить из-за растянутого содержимого страницы.webview
Не могу прокрутить сам.
IOS
Мягкая производительность при сворачивании клавиатуры
При нажатии кнопки «свернуть» на программной клавиатуре клавиатура или область страницы за пределами поля ввода теряет фокус, и программная клавиатура сворачивается.
Android
Мягкая производительность при сворачивании клавиатуры
Когда срабатывает область, отличная от поля ввода, поле ввода теряет фокус и программная клавиатура закрывается. Однако при нажатии кнопки закрытия на клавиатуре поле ввода не теряет фокус, и виртуальная клавиатура также закрывается.
Следите за программной клавиатурой вверх и вниз
Встроенная выше клавиатура выдвигается и убирается вIOS
а такжеAndroid
В разных представлениях мы можем отдельно выполнить следующую обработку для отслеживания всплывающих окон и убирания программной клавиатуры:
- существует
IOS
Вкл., следите за полем вводаfocus
Событие, чтобы узнать мягкую клавиатуру, чтобы отскочить, прослушать поле вводаblur
Программная клавиатура уведомления о событии убрана. - существует
Android
вкл., мониторwebview
Высота изменится, а высота станет меньше, чтобы знать, что программная клавиатура выскакивает, иначе программная клавиатура убирается.
// 判断设备类型
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
}
}()
// 监听输入框的软键盘弹起和收起事件
function listenKeybord($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 键盘收起: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 键盘弹起啦!');
// Android 键盘弹起后操作
}
originHeight = resizeHeight;
}, false)
}
}
var $inputs = document.querySelectorAll('.input');
for (var i = 0; i < $inputs.length; i++) {
listenKeybord($inputs[i]);
}
Всплывающая экранная клавиатура всегда прокручивает поле ввода до видимой области
Иногда мы создаем форму ввода со многими элементами ввода, поле ввода получает фокус, и всплывает экранная клавиатура. Когда поле ввода находится в нижней части страницы, вIOS
вверх, будетwebview
Прокрутите вверх на определенное расстояние в целом, чтобы поле ввода, получающее фокус, автоматически находилось в видимой области, а вAndroid
Это не так, он просто изменяет высоту страницы без прокрутки текущего сфокусированного элемента в область просмотра.
Так как выше уже реализован мониторингIOS
а такжеAndroid
Клавиатура выскакивает вверх и вниз, здесь, прямо вAndroid
После появления клавиатуры прокрутите выделенный элемент (scrollIntoView()
) в видимую область. Чтобы увидеть эффект, вы можете нажатьздесь.
// 获取到焦点元素滚动到可视区
function activeElementScrollIntoView(activeElement, delay) {
var editable = activeElement.getAttribute('contenteditable')
// 输入框、textarea或富文本获取焦点后没有将该元素滚动到可视区
if (activeElement.tagName == 'INPUT' || activeElement.tagName == 'TEXTAREA' || editable === '' || editable) {
setTimeout(function () {
activeElement.scrollIntoView();
}, delay)
}
}
// ...
// Android 键盘弹起后操作
activeElementScrollIntoView($input, 1000);
// ...
Вызвать чистую цифровую мягкую клавиатуру
В приведенном выше поле ввода формы требуется ввести номер телефона.Подобно этому, появится цифровая программная клавиатура.Поскольку сказано, что программная клавиатура совместима, она будет вставлена сюда. Лучшее решение выглядит следующим образом:
<p>请输入手机号</p>
<input type="tel" novalidate="novalidate" pattern="[0-9]*" class="input">
-
type="tel"
, ДаHTML5
Атрибут , указывающий, что поле ввода является номером телефона, вAndroid
а такжеIOS
Исполнение аналогичное, будет цифровая клавиатура, но будут и буквы, которые немного избыточны. -
pattern="[0-9]"
,pattern
Используется для проверки содержимого входных данных формы, обычноHTML5
изtype
свойства, такие какemail
,tel
,number
,data
Добрый,url
Подождите, в нем уже есть простая функция проверки формата данных, плюсpattern
Проверка передней части более проста и эффективна.IOS
, Только[0-9]\*
Только после этого вы можете вызвать цифровую клавиатуру Jiugongge,\d
неверный,Android 4.4
Ниже (включая ядро X5) оба вызывают цифровую клавиатуру. -
novalidate="novalidate"
,novalidate
Атрибут указывает, что форма не проверяется при отправке из-заpattern
чек об оплатесовместимостьНехорошо, вы не можете позволить ему проверить, просто пусть он вызовет чистую цифровую клавиатуру, проверка выполняетсяjs
сделать это.
совместимыйIOS12
+ V6.7.4+
если вы используетеIOS12
а такжеV6.7.4+
Версия браузера WeChat открывает вышеуказанную форму вводаdemo
, вы будете удивлены, обнаружив, что после того, как клавиатура сложена, страница, первоначально поднятая при прокрутке, не возвращается в нижнее положение, что приводит к «пустому» положению, в котором клавиатура была первоначально поднята.
На самом деле этоApple
существуетIOS
изbug
, появится во всехXcode10
упакованныйIOS12
на устройстве. Официальный представитель WeChat далрешение, просто поместите страницу (webview
), чтобы вернуться в самый низ окна (clientHeight
Место нахождения). Исправлен ввод формы вышеdemo
может тыкатьздесь
console.log('IOS 键盘收起啦!');
// IOS 键盘收起后操作
// 微信浏览器版本6.7.4+IOS12会出现键盘收起后,视图被顶上去了没有下来
var wechatInfo = window.navigator.userAgent.match(/MicroMessenger\/([\d\.]+)/i);
if (!wechatInfo) return;
var wechatVersion = wechatInfo[1];
var version = (navigator.appVersion).match(/OS (\d+)_(\d+)_?(\d+)?/);
if (+wechatVersion.replace(/\./g, '') >= 674 && +version[1] >= 12) {
setTimeout(function () {
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>发送</button>
</div>
стиль
/* 省略一些样式 */
.chat__content {
height: calc(100% - 40px);
margin-bottom: 40px;
overflow-y: auto;
overflow-x: hidden;
}
.input__content {
display: flex;
height: 40px;
position: absolute;
left: 0;
right: 0;
bottom: 0;
align-items: center;
}
/* 省略一些样式 */
Это очень просто, нужно разделить область содержимого и область ввода, область ввода абсолютно позиционирована и вводиться в соответствии с приведенной выше формой.demo
подход, действительно, самыйAndroid
Браузер в порядке, но тестIOS
начальство,UC
Когда браузер взаимодействует с собственным методом ввода и сторонним методом ввода (например, методом ввода Sogou), поле ввода будет полностью заблокировано;QQ
Канал браузера или микробраузера со сторонним методом ввода, поле ввода наполовину закрыто, поле браузера Baidu, приспособленное для третьего метода ввода, будет полностью закрыто. Посмотреть результаты можно с помощью соответствующего браузераздесь.
существуетUC
В браузере после появления экранной клавиатуры высота строки заголовка над браузером будет иметь уменьшенный динамический эффект задержки высоты, что вызоветwebview
Прокрутив немного вниз, нижнее поле ввода прокрутилось до невизуальной области.
Для стороннего метода ввода само предположение связано с неправильным расчетом высоты после всплывающей панели метода ввода, что приводит кwebview
Начальное позиционирование прокрутки неверно. На самом деле обаwebview
Прокрутка вызвана неадекватностью. После разрешения всплывает программная клавиатура, позволяя элементам фокуса снова свернуть в область просмотра, заставляяwebview
Свернуть на место.
console.log('Android 键盘弹起啦!');
// Android 键盘弹起后操作
activeElementScrollIntoView($input, 1000);
совместимыйAndroid
Браузер СяомиHack
строить планы
существуетAndroid
В браузере Xiaomi версии 1 примените вышеуказанное решение и обнаружите, что поле ввода чата по-прежнему полностью заблокировано.scrollIntoView()
Еще неподвижен. Так что догадайтесь, на самом деле он прокручен до конца, всплывает программная клавиатура, а высота страницы больше, чем высота видимой области.Таким образом, только после того, как программная клавиатура всплывает, высота страницы можно принудительно увеличить, чтобы можно было отобразить поле ввода. Таким образом, приведенное выше совместимо со сторонними методами ввода, и вы можете щелкнуть, чтобы просмотреть эффект.здесь
// Andriod 键盘收起: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 键盘收起后操作
// 修复小米浏览器下,输入框依旧被输入法遮挡问题
if (judgeDeviceType.isMiuiBrowser) {
document.body.style.marginBottom = '0px';
}
} else {
console.log('Android 键盘弹起啦!');
// Android 键盘弹起后操作
// 修复小米浏览器下,输入框依旧被输入法遮挡问题
if (judgeDeviceType.isMiuiBrowser) {
document.body.style.marginBottom = '40px';
}
activeElementScrollIntoView($input, 1000);
}
originHeight = resizeHeight;
}, false)
}
Суммировать
H5
Впереди долгий путь и много ям, и нужно продолжать попытки. Подробнее о всплывающей странице программной клавиатуры см.IOS
а такжеAndroid
Разница в производительности — это предпосылка с последующим прокручиванием элемента фокуса в видимую область с учетом различий в сторонних методах ввода и некоторых браузерах. Резюме определенно не является исчерпывающим, приветствую всех, кто меня поправит, конец~