Отключение функции выключения Android-хром

Я создал небольшое веб-приложение HTML5 для своей компании.

Это приложение отображает список элементов, и все работает нормально.

Приложение в основном используется на телефонах Android и Chrome в качестве браузера. Кроме того, сайт сохраняется на главном экране, поэтому Android управляет всем приложением (с помощью WebView, я думаю,).

Chrome Beta (и я также думаю, что Android System WebView) добавила функцию "pull down to refresh" (См. эту ссылку, например).

Это удобная функция, но мне было интересно, можно ли ее отключить с помощью метатега (или javascript), потому что обновление может быть легко вызвано пользователем во время навигации по списку, и все приложение перезагружается.

Также это функция, не требуемая приложением.

Я знаю, что эта функция по-прежнему доступна только в бета-версии Chrome, но у меня есть ощущение, что она тоже приземляется на стабильное приложение.

Спасибо!

Изменить: я удалил бета-версию Chrome, и ссылка, прикрепленная к главному экрану, теперь открывается стабильным Chrome. Таким образом, привязанные ссылки начинаются с Chrome, а не с веб-просмотром.

Изменить: сегодня (2015-03-19) переход к обновлению достиг стабильного хрома.

Изменить: из ответа @Evyn Я следую этой ссылке и получил этот код javascript/jquery, который работает.

var lastTouchY = 0;
var preventPullToRefresh = false;

$('body').on('touchstart', function (e) {
    if (e.originalEvent.touches.length != 1) { return; }
    lastTouchY = e.originalEvent.touches[0].clientY;
    preventPullToRefresh = window.pageYOffset == 0;
});

$('body').on('touchmove', function (e) {
    var touchY = e.originalEvent.touches[0].clientY;
    var touchYDelta = touchY - lastTouchY;
    lastTouchY = touchY;
    if (preventPullToRefresh) {
        // To suppress pull-to-refresh it is sufficient to preventDefault the first overscrolling touchmove.
        preventPullToRefresh = false;
        if (touchYDelta > 0) {
            e.preventDefault();
            return;
        }
    }
});

Ответ 1

Действие по умолчанию для эффекта pull-to-refresh можно эффективно предотвратить, выполнив одно из следующих действий:

  1. preventDefault некоторых частей последовательности касаний, включая любое из следующего (в порядке от наиболее разрушительного до наименее разрушительного):
    • а. Весь сенсорный поток (не идеальный).
    • б. Все верхние сверхскоростные сенсорные движения.
    • с. Первый верхний перебегающий сенсорный ход.
    • д. Первое касание с верхней прокруткой только тогда, когда 1) начальное касание произошло, когда смещение прокрутки страницы y было равно нулю, и 2) касание переместило бы верхнюю прокрутку.
  2. Применение " touch-action: none " к элементам, нацеленным на прикосновение, где это уместно, отключение действий по умолчанию (в том числе pull-to-refresh) последовательности касаний.
  3. Применяя " overflow-y: hidden " к элементу body, используя div для прокручиваемого содержимого, если это необходимо.
  4. Отключение эффекта локально с помощью chrome://flags/#disable-pull-to-refresh-effect).

Узнать больше

Ответ 2

Простое решение для 2019+

Chrome 63 (выпущен 5 декабря 2017 года) добавил свойство css, чтобы помочь именно с этим. Прочтите это руководство от Google, чтобы получить представление о том, как с ним справиться.

Вот их TL: DR

Свойство CSS overscroll-поведения позволяет разработчикам переопределять поведение прокрутки переполнения браузера по умолчанию при достижении верха/низа контента. Варианты использования включают в себя отключение функции "pull-to-refresh" на мобильном устройстве, устранение эффектов свечения при избыточной прокрутке и резиновой полосы, а также предотвращение прокрутки содержимого страницы, если оно находится ниже модального/наложения.

Чтобы все заработало, все, что вам нужно добавить, это в вашем CSS:

body {
  overscroll-behavior: contain;
}

На данный момент он также поддерживается только Chrome, Edge и Firefox, но я уверен, что Safari добавит его в ближайшее время, так как они, похоже, полностью совместимы с работниками сферы обслуживания и будущим PWA.

Ответ 3

В настоящий момент вы можете отключить эту функцию только с помощью chrome://flags/#disable-pull-to-refresh-effect - открыть прямо с вашего устройства.

Вы можете попытаться поймать события touchmove, но шансы очень тонкие, чтобы достичь приемлемого результата.

Ответ 4

Я использую MooTools, и я создал класс для отключения обновления на целевом элементе, но суть его (родной JS):

var target = window; // this can be any scrollable element
var last_y = 0;
target.addEventListener('touchmove', function(e){
    var scrolly = target.pageYOffset || target.scrollTop || 0;
    var direction = e.changedTouches[0].pageY > last_y ? 1 : -1;
    if(direction>0 && scrolly===0){
        e.preventDefault();
    }
    last_y = e.changedTouches[0].pageY;
});

Все, что мы делаем, это найти направление y сенсорной кнопки, и если мы движемся вниз по экрану, а целевой свиток - 0, мы остановим это событие. Таким образом, обновление не обновляется.

Это означает, что мы стреляем в каждое "движение", которое может быть дорогостоящим, но это лучшее решение, которое я нашел до сих пор...

Ответ 5

AngularJS

Я успешно отключил его с помощью этой директивы AngularJS:

//Prevents "pull to reload" behaviour in Chrome. Assign to child scrollable elements.
angular.module('hereApp.directive').directive('noPullToReload', function() {
    'use strict';

    return {
        link: function(scope, element) {
            var initialY = null,
                previousY = null,
                bindScrollEvent = function(e){
                    previousY = initialY = e.touches[0].clientY;

                    // Pull to reload won't be activated if the element is not initially at scrollTop === 0
                    if(element[0].scrollTop <= 0){
                        element.on("touchmove", blockScroll);
                    }
                },
                blockScroll = function(e){
                    if(previousY && previousY < e.touches[0].clientY){ //Scrolling up
                        e.preventDefault();
                    }
                    else if(initialY >= e.touches[0].clientY){ //Scrolling down
                        //As soon as you scroll down, there is no risk of pulling to reload
                        element.off("touchmove", blockScroll);
                    }
                    previousY = e.touches[0].clientY;
                },
                unbindScrollEvent = function(e){
                    element.off("touchmove", blockScroll);
                };
            element.on("touchstart", bindScrollEvent);
            element.on("touchend", unbindScrollEvent);
        }
    };
});

Безопасно останавливать просмотр, как только пользователь прокручивается вниз, так как притяжение к обновлению не имеет шансов быть вызванным.

Аналогично, если scrolltop > 0, событие не будет запущено. В моей реализации я привязываю событие touchmove к touchstart, только если scrollTop <= 0. Я отсоединяю его, как только пользователь прокручивается вниз (initialY >= e.touches[0].clientY). Если пользователь прокручивается (previousY < e.touches[0].clientY), я вызываю preventDefault().

Это избавляет нас от просмотра событий прокрутки без необходимости, но блокирует перекрестную проверку.

JQuery

Если вы используете jQuery, это непроверенный эквивалент. element является элементом jQuery:

var initialY = null,
    previousY = null,
    bindScrollEvent = function(e){
        previousY = initialY = e.touches[0].clientY;

        // Pull to reload won't be activated if the element is not initially at scrollTop === 0
        if(element[0].scrollTop <= 0){
            element.on("touchmove", blockScroll);
        }
    },
    blockScroll = function(e){
        if(previousY && previousY < e.touches[0].clientY){ //Scrolling up
            e.preventDefault();
        }
        else if(initialY >= e.touches[0].clientY){ //Scrolling down
            //As soon as you scroll down, there is no risk of pulling to reload
            element.off("touchmove");
        }
        previousY = e.touches[0].clientY;
    },
    unbindScrollEvent = function(e){
        element.off("touchmove");
    };
element.on("touchstart", bindScrollEvent);
element.on("touchend", unbindScrollEvent);

Естественно, то же самое можно достичь и с чистым JS.

Ответ 6

После многих часов попыток это решение работает для меня

$("html").css({
    "touch-action": "pan-down"
});

Ответ 7

Простой Javascript

Я реализовал с использованием стандартного javascript. Простая и простая в использовании. Просто вставьте, и он отлично работает.

<script type="text/javascript">         //<![CDATA[
     window.addEventListener('load', function() {
          var maybePreventPullToRefresh = false;
          var lastTouchY = 0;
          var touchstartHandler = function(e) {
            if (e.touches.length != 1) return;
            lastTouchY = e.touches[0].clientY;
            // Pull-to-refresh will only trigger if the scroll begins when the
            // document Y offset is zero.
            maybePreventPullToRefresh =
                window.pageYOffset == 0;
          }

          var touchmoveHandler = function(e) {
            var touchY = e.touches[0].clientY;
            var touchYDelta = touchY - lastTouchY;
            lastTouchY = touchY;

            if (maybePreventPullToRefresh) {
              // To suppress pull-to-refresh it is sufficient to preventDefault the
              // first overscrolling touchmove.
              maybePreventPullToRefresh = false;
              if (touchYDelta > 0) {
                e.preventDefault();
                return;
              }
            }
          }

          document.addEventListener('touchstart', touchstartHandler, false);
          document.addEventListener('touchmove', touchmoveHandler, false);      });
            //]]>    </script>

Ответ 8

Лучшее решение для чистого CSS:

body {
    width: 100%;
    height: 100%;
    display: block;
    position: absolute;
    top: -1px;
    z-index: 1;
    margin: 0;
    padding: 0;
    overflow-y: hidden;
}
#pseudobody {
    width:100%;
    height: 100%;
    position: absolute;
    top:0;
    z-index: 2;
    margin: 0;
    padding:0;
    overflow-y: auto;
}

Смотрите эту демонстрацию: https://jsbin.com/pokusideha/quiet

Ответ 9

Я считаю, что настройка

body CSS overflow-y: hidden - самый простой способ. Если вы хотите иметь прокручиваемую страницу приложения, вы можете просто использовать контейнер div с функциями прокрутки.

Ответ 10

За пару недель я узнал, что функция javascript, которую я использовал для отключения действия обновления Chrome, больше не будет работать. Я решил это решить:

$(window).scroll(function() {
   if ($(document).scrollTop() >= 1) {
      $("html").css({
         "touch-action": "auto"}
      );
   } else {
      $("html").css({
         "touch-action": "pan-down"
      });
   }
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>

Ответ 11

Обратите внимание, что overflow-y не наследуется, поэтому вам нужно установить его на ВСЕ блочные элементы.

Вы можете сделать это с помощью jQuery, просто:

        $(document.body).css('overflow-y', 'hidden'); 
        $('*').filter(function(index) {
            return $(this).css('display') == 'block';
        }).css('overflow-y', 'hidden');

Ответ 12

То, что я сделал, это добавить следующие события touchstart и touchend/touchcancel:

scrollTo(0, 1)

Поскольку хром не прокручивается, если он не находится в позиции scrollY 0, это предотвратит выполнение chrome для обновления.

Если он все еще не работает, попробуйте сделать это, когда страница загружается.

Ответ 13

Решение Pure js.

// Prevent pull refresh chrome
    var lastTouchY = 0;
    var preventPullToRefresh = false;
    window.document.body.addEventListener("touchstart", function(e){
        if (e.touches.length != 1) { return; }
        lastTouchY = e.touches[0].clientY;
        preventPullToRefresh = window.pageYOffset == 0;
    }, false);

    window.document.body.addEventListener("touchmove", function(e){

        var touchY = e.touches[0].clientY;
        var touchYDelta = touchY - lastTouchY;
        lastTouchY = touchY;
        if (preventPullToRefresh) {
            // To suppress pull-to-refresh it is sufficient to preventDefault the first overscrolling touchmove.
            preventPullToRefresh = false;
            if (touchYDelta > 0) {
                e.preventDefault();
                return;
            }
        }

    }, false);

Ответ 14

Я решил проблему выпадающего меню с помощью этого:

html, body {
    width: 100%;
    height: 100%;
    overflow: hidden;
}