Возможно, вам нужны именно эти решения для совместимости с клавиатурой H5.

JavaScript

предисловие

делал это недавно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 的 webview 不同表现

Следите за программной клавиатурой вверх и вниз

Встроенная выше клавиатура выдвигается и убирается в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сделать это.

软键盘弹起,IOS 和 Android 的 webview 不同表现

совместимыйIOS12 + V6.7.4+

если вы используетеIOS12а такжеV6.7.4+Версия браузера WeChat открывает вышеуказанную форму вводаdemo, вы будете удивлены, обнаружив, что после того, как клавиатура сложена, страница, первоначально поднятая при прокрутке, не возвращается в нижнее положение, что приводит к «пустому» положению, в котором клавиатура была первоначально поднята.

兼容 IOS12 + V6.7.4+

На самом деле это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Разница в производительности — это предпосылка с последующим прокручиванием элемента фокуса в видимую область с учетом различий в сторонних методах ввода и некоторых браузерах. Резюме определенно не является исчерпывающим, приветствую всех, кто меня поправит, конец~