Проблема в том, что поле ввода реакции блокируется клавиатурой мобильного телефона под Android

внешний интерфейс JavaScript Android React.js

Обзор проблемы

Сегодня столкнулся с проблемой, на телефоне Android, когда я хотел нажать для ввода "названия магазина", выскакивала программная клавиатура телефона и просто блокировала поле ввода, даже если бы я ее блокировал, ключ был в том, что страница могла нельзя провести пальцем вверх, и все окно телефона было заблокировано.Нажим составляет около половины оригинала;

    

потом

Потом я нашел некоторые решения, но они не очень применимы, или это немного хлопотно, поэтому его нужно интегрировать, Сначала я думаю об эффекте, которого хочу добиться

желаемый эффект

    

Как показано на рисунке, когда появляется клавиатура мобильного телефона, страницу можно свободно прокручивать, а поле ввода, сфокусированное в данный момент, выравнивается по красной линии, так что оно находится точно посередине остального окна по вертикали, так что поле ввода не будет отображаться заблокированным. , вы не можете видеть, что вы ввели;

Первый шаг — сделать экран маленьким, чтобы содержимое страницы можно было прокручивать.

Как показано на рисунке ниже, черный прямоугольник представляет собой экран, а синий прямоугольник представляет собой размер страницы.При нажатии на экран содержимое страницы должно сохранять исходную высоту:  

Принцип реализации, когда заходит страница, я получаю высоту окна и устанавливаю минимальную высоту для самого внешнего div, чтобы даже при уменьшении окна страница сохраняла исходную высоту и ее можно было прокручивать:

      let initWindowHeight=window.innerHeight
      let wrapDiv=document.getElementsByClassName('animated-router-forward-enter-done')[0]
      wrapDiv.style.minHeight =initWindowHeight+'px'

Второй шаг, прокрутите до красной строки

(Дополнение 2018/9/3: Что касается второго шага, в области комментариев есть более простой метод реализации)
Поскольку мы не можем напрямую знать, когда появляется программная клавиатура, но высота окна будет уменьшаться при выходе программной клавиатуры, поэтому мы можем судить о том, появляется ли программная клавиатура, прослушивая событие изменения размера окна. высота окна браузера внезапно сжимается более чем на 25%, тогда мы думаем, что программная клавиатура выходит, и тогда мы получаем расстояние сфокусированного ввода от верха страницы, и вычисляем расстояние от красной линии. что расстояние равно 60, тогда мы прокручиваем страницу вверх на 60, а ввод находится как раз на красной линии. ;

  window.onresize=function(){ 
        if(initWindowHeight-window.innerHeight>initWindowHeight/4&&document.querySelectorAll(':focus').length>0){
           //offset是封装好的一个获取元素距离页面顶部滚动距离的方法
           if(offset(document.querySelectorAll(':focus')[0]).top>initWindowHeight/4){
             document.body.scrollTop=offset(document.querySelectorAll(':focus')[0]).top-initWindowHeight/4
           }
        }else if(window.innerHeight-initWindowHeight<20){
            document.body.scrollTop=0
        }
        
    };

полный код

Поскольку для вызова может быть несколько страниц, я поместил код в отдельный файл js:

function pageInputScroll() {
    
    let initWindowHeight=window.innerHeight
    setTimeout(() => {
      let wrapDiv=document.getElementsByClassName('animated-router-forward-enter-done')[0]
      //console.log(wrapDiv.style)
      wrapDiv.style.minHeight =initWindowHeight+'px'
         
     }, 500);
     //由于我们不能直接知道软键盘什么时候出来,不过软键盘出来的时候窗口高度会缩小,所以我们可以通过监听窗口大小变化事件来判断软键盘是否弹出
    window.onresize=function(){ //如果浏览器窗口高度缩小25%以上,就认为是软键盘出来了
        if(initWindowHeight-window.innerHeight>initWindowHeight/4&&document.querySelectorAll(':focus').length>0){
           if(offset(document.querySelectorAll(':focus')[0]).top>initWindowHeight/4){
             document.body.scrollTop=offset(document.querySelectorAll(':focus')[0]).top-initWindowHeight/4
           }
        }else if(window.innerHeight-initWindowHeight<20){
            document.body.scrollTop=0
        }
        
    };
}
function offset(element) {
    var offest = {
        top: 0,
        left: 0
    };
 
    var _position;
 
    getOffset(element, true);
 
    return offest;
 
    // 递归获取 offset, 可以考虑使用 getBoundingClientRect
    function getOffset(node, init) {
        // 非Element 终止递归
        if (node.nodeType !== 1) {
            return;
        }
        _position = window.getComputedStyle(node)['position'];
 
        // position=static: 继续递归父节点
        if (typeof(init) === 'undefined' && _position === 'static') {
            getOffset(node.parentNode);
            return;
        }
        offest.top = node.offsetTop + offest.top - node.scrollTop;
        offest.left = node.offsetLeft + offest.left - node.scrollLeft;
 
        // position = fixed: 获取值后退出递归
        if (_position === 'fixed') {
            return;
        }
 
        getOffset(node.parentNode);
    }
}

export {pageInputScroll};

Введите js на страницу реакции и вызовите:

  import {pageInputScroll} from '../../util/pageInputScroll'
  ......
  componentDidMount(){
       pageInputScroll()
   }

Если вы просто хотите использовать его под Android, вы можете добавить суждение:

  if(/Android/i.test(navigator.userAgent)){
      pageInputScroll()
  }

Эффект анимации

Я имитирую эффект, достигнутый Google Chrome на стороне ПК:

Примечание

Метод offset() — это метод использования js для реализации offset(), аналогичный jquery, см.:Нативный js реализует метод смещения

  

  

рекомендовать:Небольшая программа, которая может сканировать штрих-коды продуктов для обзоров продуктов.

Добро пожаловать, чтобы отсканировать код, чтобы испытать: