Вимкнення функції хромування Android, що висувається для оновлення


135

Я створив невелику веб-програму HTML5 для своєї компанії.

Ця програма відображає список елементів, і все працює добре.

Додаток використовується в основному на андроїд-телефонах та Chrome як браузер. Також сайт зберігається на головному екрані, тому Android керує всією справою як додаток ( я думаю, використовуючи WebView ).

Chrome Beta (і я думаю, також Android System WebView) ввів функцію "тягнути вниз для оновлення" ( див. Наприклад, це посилання ).

Це зручна функція, але мені було цікаво, чи не можна її відключити за допомогою якогось метатега (або JavaScript), оскільки оновлення може бути спровоковано користувачем під час навігації по списку, і весь додаток перезавантажується.

Також ця функція не потрібна додатку.

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

Дякую!

Редагувати: я видалив Chrome Beta, і посилання, прикріплене до головного екрану, тепер відкривається зі стабільним Chrome. Отже, покладені посилання починаються з Chrome, а не з веб-перегляду.

Редагувати: сьогодні (2015-03-19) перехід на оновлення прийшов до стабільного хрому.

Редагувати: з відповіді @Evyn Я переходжу за цим посиланням і отримаю цей код JavaScript / jquery, який працює.

Як зазначав @bcintegrity, я сподіваюся, що рішення щодо маніфесту сайту (та / або метатегів) буде надалі.

Більше того, пропозиції щодо коду вище вітаються.


18
Так, це справді відстійно. Був у середині форми і прокрутився до верху занадто далеко, і це освіжило і втратило все. Це затримка за замовчуванням, я клацну піктограму «Оновити», якщо хочу оновити!
Брок Хенслі

12
Було б добре, якби цю функцію можна було б відключити в маніфесті веб-додатків. На жаль, на кожній сторінці в моєму веб-додатку є вміст, який можна прокручувати, що робить його майже неможливим переміщення без оновлення. Я трохи поставлений. : /
bcintegrity

Це гарна інформація. Я ненавиджу веб-сайти, які вимикають функцію "тягнути до оновлення". Я хотів би розробити функцію, щоб зробити оновлення роботи незалежно від вмісту сторінки.
LS

5
Виступаючи як веб-розробник, оновлення, що випадає, несумісне з веб-сайтами, керованими даними, оскільки воно перезавантажує додаток. Користувач унеможливлює прокручування до верхньої частини сторінки, не оновлюючи всю сторінку. Я на 100% підтримую Chrome, сподіваюся, що вони усунуть цю антифункцію.
Квасоля

3
Я зіткнувся з цією "особливістю" GC ... багато веб-сторінок, багато форм, одна необережна тягнути пальцем і дані на цій сторінці втрачаються! Затримка функції ІМО. Він повинен бути вимкненим за замовчуванням, кому це потрібно, то нехай він кодує. Я днями цікавився, чому мої "клієнти" час від часу втрачають свої дані про GC ...
Ludus H

Відповіді:


157

Дію ефекту "тягнути до оновлення" за замовчуванням можна ефективно запобігти, виконавши будь-що з наступного:

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

Побачити більше


12
Дякую @Evyn Я не можу повірити, що це було швидко виправити! Я встановлюю CSS для елемента body, щоб переповнювати y: приховано.
bcintegrity

Дякую @Evyn, я вирішив використовувати метод prevenDefault () (перша точка). Зокрема, мені було цікавим вихідний код посилання ( посилання ), що знаходиться всередині документу, який ви зв'язали. Я поставлю код в кінці запитання.
Себастьяно

2
як програмно робиться "chrome: // flags (відключити-тягнути до оновлення")?
Хтось десь

2
@SomeoneSnewhere, наскільки я знаю, це не неможливо. налаштування хрому може встановлювати тільки користувач - це може становити загрозу безпеці в іншому випадку
Майк

1
Застосування "overflow-y: hidden" до елемента body, використовуючи div для прокручуваного вмісту, який працював на мене.
Робін

103

Просте рішення на 2019 рік

Chrome 63 додав властивість css, щоб вирішити саме це. Прочитайте цей посібник від Google, щоб зрозуміти, як з цим впоратися.

Ось їх TL: DR

Властивість поведінки overscroll поведінки CSS дозволяє розробникам переосмислити поведінку прокрутки за промовчанням браузера за замовчуванням під час досягнення верхньої / нижньої частини вмісту. Сюди використання включають відключення функції мобільного оновлення для мобільних пристроїв, видалення ефектів світіння та прокладки гуми, а також запобігання прокручування вмісту сторінки під модальним / накладенням.

Щоб працювати, все, що вам потрібно додати, - це це у вашому CSS:

body {
  overscroll-behavior: contain;
}

Він також тільки при підтримці з боку Chrome, Firefox Краю і зараз , але я впевнений , що Safari додасть його в найближчий час, як вони , здається, повністю на борту з сервісними працівниками і майбутнього PWA років.


16
це найсучасніший привид
Колсі

Хтось ще помітив, що це затримує появу хромового банера "Додати на домашню панель"?
Натаніел Хілл

2
довелося застосувати його до елемента html, щоб відключити його
Jakob Eriksson,

1
Ця робота лише для Android, Chrome на IO все ще демонструє ефект світіння +
натискання

developers.google.com/web/updates/2017/11/overscroll-behavior це посилання також може пояснити краще
arung86

15

На даний момент ви можете відключити цю функцію лише за допомогою chrome: // flags / # disabled-pull-to-refresh-effect - відкрийте безпосередньо зі свого пристрою.

Можна спробувати зловити touchmoveподії, але шанси досягти прийнятного результату дуже малі.


1
Дякую Кевін за відповідь. Я не міг прийняти це як прийняте, бо шукав щось, що не залежить від користувачів. Однак цей метод працює, тому я підтримаю вашу відповідь, оскільки я набуду достатньої репутації.
Себастьяно

Шкода, що, здається, це найкраще рішення - що робити, якщо налаштування прапора зміниться в майбутньому, або ви хочете мати змогу використовувати функцію "pull" для оновлення на інших сайтах ... Дивно, що це неможливо контролювати програмно. :(.
user1063287

1
Якщо генеральний директор Google це читає, видаліть цю функцію. Не здається, що його можна легко і всебічно відключити, і на мою думку, це "функція" веб-додатків, яку хочуть не всі веб-програми.
користувач1063287

8

Я використовую 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, ми зупиняємо подію. Таким чином, ніякого оновлення.

Це означає, що ми стріляємо з кожного "ходу", який може бути дорогим, але це найкраще рішення, яке я знайшов поки що ...


2
Безпечно припиняти перегляд, як тільки користувач прокручується вниз, оскільки тягнення для оновлення не має шансу викликати його. Так само, якщо scrolltop > 0, подія не буде запущено. У своїй реалізації я пов'язую touchmoveподію touchstart, лише якщо scrollTop <= 0. Я скасовую її, як тільки користувач прокручує вниз ( initialY >= e.touches[0].clientY). Якщо користувач прокручує вгору ( previousY < e.touches[0].clientY), я дзвоню preventDefault.
Nicolas Bouliane

7

Після багатьох годин спроб це рішення працює для мене

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

Для цього не потрібно використовувати jQuery. Просто додайте в файл коду css "touch-action: pan-down".
Keegan Teetaert

1
просто використовуйте це у своєму css:html{touch-action:pan-down}
csandreas1

5

КутовийJS

Я успішно відключив його за допомогою цієї директиви 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.


Мені довелося скористатися, e.originalEvent.touches[0].clientYщоб зробити цю роботу. Досі бореться з логікою, коли запобігти перезавантаженню. Зараз, здається, що випадковим чином запобігти прокручування вгору ... Подякуйте за підказку в правильному напрямку!
томас

До якого елемента додається директива?
Fizzix

Директива AngularJS добре працювала для мене. Ми використовуємо Framework7 і Angular разом (не пропонуємо цього), і щось блокувало правильну поведінку scrollTop. Тому мені довелося змінити, коли blockScroll буде доданий до елемента. Але просто хотів сказати спасибі!
Дастін Йенсен

5

Простий 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's 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>

Це дуже добре працювало для Chrome, але викликало деякі проблеми з прокруткою для мене на Safari / iOS 9.2, коли прокручуєте div у верхній частині сторінки (відтворено тут ). Я в кінцевому підсумку використовував body: {overflow-y:hidden}трюк від Евіна вище .
сеннетт

downvoting як не працює на хром, але працює на прикладі firefox, embed.plnkr.co/rqbOVSOkKyhAgoHK2sEP відкрито в МОБІЛЬНОМУ ТОЛЬКІ
vijay

посилання, яке ви вставили, працювало в хромі, а також на моєму мобільному пристрої Android. це не дозволило освіжитись на тязі. яку версію Android / ios ви використовуєте для тестування?
Саккі Сан-

2
З Chrome 56 вам потрібно встановити пасивний: false, щоб він працював: document.addEventListener ('touchstart', touchstartHandler, {пасивний: false}); document.addEventListener ('touchmove', touchmoveHandler, {пасивний: помилковий});
Антон Кузьмін

4

Найкраще рішення для чистого 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


Ви справді тестували це на мобільному пристрої за допомогою хрому?
Грегор Войнов


3

Я знаходжу налаштування вашого тіло CSS переповнення-у: приховане це найпростіший спосіб. Якщо ви хочете мати сторінку прокрутки, ви можете просто скористатися контейнером div з функціями прокрутки.


Здається, це неможливо виправити лінією, але працює як шарм, велике спасибі!
Ігнасіо Ара

2

Зауважте, що overflow-y не успадковується, тому вам потрібно встановити його на ВСІ елементи блоку.

Зробити це за допомогою jQuery можна просто:

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

Серед інших відповідей ця справді допомагає. Дякую. Додайте цей рядок у css. тіло {переповнення-у: приховано; }
Сарін JS

2

Через пару тижнів я дізнався, що функція 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>


1

Чистий розчин 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);

0

Що я зробив, додав наступні дії touchstartта touchend/ touchcancelподії:

scrollTo(0, 1)

Оскільки хром не прокручується, якщо він не знаходиться у положенні прокруткиY 0 це не дозволить хрому зробити для оновлення.

Якщо це все ще не працює, спробуйте також зробити це під час завантаження сторінки.


0

Я вирішив цю проблему зі спадним оновленням:

html, body {
    width: 100%;
    height: 100%;
    overflow: hidden;
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.