Отключение функции Chrome pull-down-to-refresh для android
Я создал небольшое веб-приложение HTML5 для своей компании.
Это приложение отображает список элементов, и все работает нормально.
приложение в основном используется на телефонах android и Chrome в качестве браузера. Кроме того, сайт сохраняется на главном экране, поэтому Android управляет всем этим как приложением (используя WebView, я думаю).
Chrome Beta (и я думаю, также система Android WebView) ввел " pull down to обновить " функция (см. эту ссылку, например).
это удобная функция, но мне было интересно, можно ли ее отключить с помощью некоторого мета-тега (или javascript), потому что обновление может быть легко инициировано Пользователем при навигации по списку, и все приложение перезагружается.
также это функция, не необходимая приложению.
Я знаю, что эта функция доступна только в бета-версии Chrome, но у меня есть ощущение, что это посадки на стабильное приложение, тоже.
спасибо!
Edit: я удалил бета-версию Chrome, и ссылка, прикрепленная к главному экрану, теперь открывается со стабильным Chrome. Таким образом, закрепленные ссылки начинаются с Chrome, а не с webview.
Edit: сегодня (2015-03-19) выпадающее обновление пришло в стабильный chrome.
Edit: от @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;
}
}
});
как отметил @bcintegrity, я надеюсь на решение манифеста сайта (и / или мета-тег) в будущем.
кроме того, предложения для кода выше приветствуются.
13 ответов
действие по умолчанию эффекта pull-To-refresh можно эффективно предотвратить, выполнив одно из следующих действий:
-
preventDefault
' ing некоторая часть последовательности касания, включая любое из следующего (в порядке самого разрушительного к наименьшему разрушительному):- a. Весь сенсорный поток (не идеальный).
- b. Все верхние overscrolling touchmoves.
- c. Первый верхний overscrolling touchmove.
- d. Первая вершина overscrolling touchmove только тогда, когда 1) начальный touchstart произошел, когда смещение прокрутки страницы y было равно нулю и 2) touchmove вызовет верхний overscroll.
- применения "
touch-action: none
" для сенсорных целевых элементов, где это необходимо, отключив действия по умолчанию (включая pull-To-refresh) сенсорной последовательности. - применения "
overflow-y: hidden
" к элементу body, при необходимости используя div для прокручиваемого содержимого. - отключение эффекта локально через
chrome://flags/#disable-pull-to-refresh-effect
).
простое решение для 2018+
Chrome 63 (выпущен 5 декабря 2017) добавил свойство css, чтобы помочь именно с этим. Прочтите это руководство от Google чтобы получить хорошее представление о том, как вы можете справиться с этим.
вот их TL: DR
свойство CSS overscroll-behavior позволяет разработчикам переопределять поведение прокрутки переполнения браузера по умолчанию при достижении сверху / снизу содержимого. Варианты использования включают отключение функции pull-To-refresh характеристика на черни, извлекающ зарево overscroll и влияния rubberbanding, и предотвращение прокрутки содержимого страницы, когда оно находится под модальное / наложение.
чтобы заставить его работать, все, что вы должны добавить это:
body {
overscroll-behavior: contain;
}
Это поддерживает Chrome, Edge и Firefox на данный момент, но я уверен, что Safari добавит его, как только они, похоже, будут полностью на борту с сервисными работниками и будущим PWA.
на данный момент Вы можете отключить эту функцию только через chrome:/ / flags / #disable-pull-To-refresh-effect - откройте прямо с вашего устройства.
вы можете попытаться поймать touchmove
события, но шансы на достижение приемлемого результата очень малы.
Я использую 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 touchmove, и если мы движемся вниз по экрану, а целевой прокрутки 0, мы останавливаем событие. Таким образом, нет обновления.
это означает, что мы стреляем по каждому "ходу", что может быть дорого, но это лучшее решение, которое я нашел до сих пор ...
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()
.
это избавляет нас от просмотра событий прокрутки без необходимости, но блокирует overscrolling.
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.
Простой 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>
лучшее решение для чистого 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
после многих часов попыток, это решение работает для меня
$("html").css({
"touch-action": "pan-down"
});
найти настройка тело в CSS overflow-y: hidden Это самый простой способ. Если вы хотите иметь страницу приложения прокрутки, вы можете просто использовать контейнер div с прокруткой особенности.
через пару недель я узнал, что функция 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>
обратите внимание, что overflow-y не наследуется, поэтому вам нужно установить его для всех элементов блока.
вы можете сделать это с помощью jQuery, просто:
$(document.body).css('overflow-y', 'hidden');
$('*').filter(function(index) {
return $(this).css('display') == 'block';
}).css('overflow-y', 'hidden');
то, что я сделал, это добавить следующее к touchstart
и touchend
/touchcancel
события:
scrollTo(0, 1)
поскольку chrome не прокручивается, если он не находится в позиции scrollY 0
это предотвратит chrome от выполнения pull для обновления.
если он все еще не работает, попробуйте также сделать это при загрузке страницы.
чистое решение 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);