Vô hiệu hóa tính năng kéo xuống để làm mới chrome của Android


135

Tôi đã tạo một ứng dụng web HTML5 nhỏ cho công ty của mình.

Ứng dụng này hiển thị một danh sách các mục và mọi thứ hoạt động tốt.

Ứng dụng này chủ yếu được sử dụng trên điện thoại Android và Chrome làm trình duyệt. Ngoài ra, trang web được lưu trên màn hình chính để Android quản lý toàn bộ nội dung dưới dạng một ứng dụng ( tôi đoán là sử dụng WebView ).

Chrome Beta (và tôi cũng nghĩ là Android System WebView) đã giới thiệu tính năng "kéo xuống để làm mới" ( ví dụ: xem liên kết này ).

Đây là một tính năng tiện dụng nhưng tôi đã tự hỏi liệu nó có thể bị vô hiệu hóa với một số thẻ meta (hoặc nội dung javascript) bởi vì người dùng có thể dễ dàng kích hoạt làm mới trong khi điều hướng danh sách và toàn bộ ứng dụng được tải lại.

Ngoài ra đây là một tính năng không cần thiết cho ứng dụng.

Tôi biết rằng tính năng này vẫn chỉ khả dụng trong Chrome beta, nhưng tôi có cảm giác rằng đây cũng là ứng dụng ổn định.

Cảm ơn bạn!

Chỉnh sửa: Tôi đã gỡ cài đặt Chrome Beta và liên kết được ghim vào màn hình chính hiện mở với Chrome ổn định. Vì vậy, các liên kết được ghim bắt đầu với Chrome chứ không phải với webview.

Chỉnh sửa: hôm nay (2015-03-19), kéo xuống để làm mới đã ổn định.

Chỉnh sửa: từ câu trả lời @Evyn Tôi theo liên kết này và nhận được mã javascript / jquery này hoạt động.

Như @bcintegrity đã chỉ ra, tôi hy vọng về một giải pháp bảng kê khai trang web (và / hoặc thẻ meta) trong tương lai.

Hơn nữa, đề xuất cho các mã ở trên được chào đón.


18
Vâng, điều này thực sự hút. Ở giữa hình thức và di chuyển lên đầu quá xa và nó làm mới và mất tất cả. Đây là một tính năng mặc định bị trì hoãn, tôi nhấp vào biểu tượng Làm mới nếu tôi muốn làm mới!
Brock Hensley

12
Sẽ rất tuyệt nếu tính năng này có thể bị vô hiệu hóa trong bảng kê khai ứng dụng web của tôi. Thật không may, mỗi trang trên ứng dụng web của tôi đều có nội dung có thể cuộn, khiến nó gần như không thể điều hướng mà không làm mới. Tôi có một chút tích tắc. : /
bcintegrity

Đây là thông tin tốt. Tôi ghét các trang web vô hiệu hóa tính năng kéo để làm mới. Tôi muốn phát triển một tính năng để làm mới công việc bất kể nội dung trang.
LS

5
Nói như một nhà phát triển web, làm mới kéo xuống không tương thích với các trang web điều khiển dữ liệu, vì nó tải lại ứng dụng. Nó khiến người dùng không thể cuộn lên đầu trang mà không làm mới toàn bộ trang. Tôi ủng hộ 100% cho Chrome, hy vọng họ loại bỏ tính năng chống đối này.
Đậu

3
Tôi đã phải đối mặt với "tính năng" GC này ... nhiều trang web, nhiều hình thức, một ngón tay bất cẩn kéo xuống và dữ liệu trên trang này bị mất! Chức năng làm chậm IMO. Nó nên được tắt theo mặc định, ai cần nó thì hãy để mã. Tôi đã tự hỏi nhiều ngày tại sao "khách hàng" của tôi thỉnh thoảng bị mất dữ liệu của họ trên GC ...
Ludus H

Câu trả lời:


157

Hành động mặc định của hiệu ứng kéo để làm mới có thể được ngăn chặn một cách hiệu quả bằng cách thực hiện bất kỳ thao tác nào sau đây:

  1. preventDefault'trong một số phần của chuỗi cảm ứng, bao gồm bất kỳ phần nào sau đây (theo thứ tự từ đột phá nhất đến ít gây rối nhất):
    • a. Toàn bộ luồng cảm ứng (không lý tưởng).
    • b. Tất cả các cảm ứng overscrolling hàng đầu.
    • c. Các touchmove ghi đè đầu tiên đầu tiên.
    • d. Touchmove ghi đè đầu tiên đầu tiên chỉ khi 1) lần chạm đầu tiên xảy ra khi độ lệch cuộn y bằng 0 và 2) touchmove sẽ tạo ra overscroll.
  2. Áp dụng touch-action: noneđịnh hướng dữ liệu cho các yếu tố nhắm mục tiêu cảm ứng, khi thích hợp, vô hiệu hóa các hành động mặc định (bao gồm kéo để làm mới) của chuỗi cảm ứng.
  3. Áp dụng overflow-y: hiddenthành phần trên nền tảng cơ thể, sử dụng div cho nội dung có thể cuộn nếu cần.
  4. Vô hiệu hóa hiệu ứng cục bộ thông qua chrome://flags/#disable-pull-to-refresh-effect).

Xem thêm


12
Cảm ơn bạn @Evyn. Tôi không thể tin rằng đây là một sửa chữa nhanh chóng! Tôi đặt CSS cho phần tử cơ thể thành overflow-y: hidden.
bcintegrity

Cảm ơn @Evyn, tôi đã quyết định sử dụng phương thức notifyDefault () (điểm đầu tiên). Đặc biệt tôi đã thấy thú vị mã nguồn của liên kết ( liên kết ) bên trong tài liệu bạn đã liên kết. Tôi sẽ đặt mã vào cuối câu hỏi của tôi.
Sebastiano

2
"chrome: // flags (vô hiệu hóa-pull-to-refresh-effect)" được lập trình như thế nào?
Ai đó ở đâu đó

2
@SomeoneSomewhere theo như tôi biết, nó không phải là không thể. Người dùng chỉ có thể cài đặt chrome - nó sẽ gây rủi ro bảo mật nếu không
Mike

1
Áp dụng tràn over-y: ẩn giấu vào phần tử cơ thể, sử dụng div cho nội dung có thể cuộn được làm việc cho tôi.
Robin

103

Giải pháp đơn giản cho năm 2019+

Chrome 63 đã thêm một thuộc tính css để trợ giúp chính xác điều này. Hãy đọc qua hướng dẫn này của Google để có ý tưởng hay về cách bạn có thể xử lý nó.

Đây là TL của họ: DR

Thuộc tính hành vi ghi đè CSS cho phép nhà phát triển ghi đè hành vi cuộn tràn mặc định của trình duyệt khi đạt đến đỉnh / cuối nội dung. Các trường hợp sử dụng bao gồm vô hiệu hóa tính năng kéo để làm mới trên thiết bị di động, loại bỏ các hiệu ứng phát sáng và dải cao su quá mức và ngăn nội dung trang cuộn khi nó ở dưới chế độ / lớp phủ.

Để làm cho nó hoạt động, tất cả những gì bạn phải thêm là điều này trong CSS của bạn:

body {
  overscroll-behavior: contain;
}

Hiện tại, nó cũng chỉ được Chrome, Edge và Firefox hỗ trợ nhưng tôi chắc chắn Safari sẽ bổ sung ngay vì chúng dường như hoàn toàn sẵn sàng với các nhân viên dịch vụ và tương lai của PWA.


16
đây là anwser cập nhật nhất
colxi

Có ai khác nhận thấy điều này làm trì hoãn sự xuất hiện của biểu ngữ chrome "Thêm vào màn hình chính" không?
Nathaniel Hill

2
đã phải áp dụng nó cho phần tử html để vô hiệu hóa nó
Jakob Eriksson

1
Điều này chỉ hoạt động cho Android, Chrome trên IOs vẫn hiển thị hiệu ứng phát sáng + kéo tự nhiên để làm mới
Fky

developers.google.com/web/updates/2017/11/overscroll-behavior liên kết này cũng có thể giải thích rõ hơn
arung86

15

Hiện tại, bạn chỉ có thể tắt tính năng này qua chrome: // flags / # vô hiệu hóa-kéo-để-làm mới hiệu ứng - mở trực tiếp từ thiết bị của bạn.

Bạn có thể cố gắng nắm bắt touchmovecác sự kiện, nhưng cơ hội rất mong manh để đạt được kết quả chấp nhận được.


1
Cảm ơn Kevin vì câu trả lời. Tôi không thể chấp nhận điều này với tư cách là người được chấp nhận vì tôi đang tìm kiếm thứ gì đó không phụ thuộc vào người dùng. Tuy nhiên phương pháp này hiệu quả, vì vậy tôi sẽ nêu lên câu trả lời của bạn khi tôi có đủ danh tiếng.
Sebastiano

Thật đáng tiếc, đây có vẻ là giải pháp tốt nhất - điều gì sẽ xảy ra nếu cài đặt cờ đó thay đổi trong tương lai hoặc bạn muốn có thể sử dụng pull để làm mới trên các trang web khác ... Thật ngạc nhiên khi điều này không thể được kiểm soát theo chương trình. :(.
user1063287

1
Nếu CEO của Google đang đọc điều này, vui lòng xóa tính năng này. Dường như nó không thể bị vô hiệu hóa một cách dễ dàng và toàn diện, và theo tôi là một "tính năng" của ứng dụng web mà không phải ứng dụng web nào cũng muốn.
dùng1063287

8

Tôi sử dụng MooTools và tôi đã tạo một Class để vô hiệu hóa làm mới trên một phần tử được nhắm mục tiêu, nhưng mấu chốt của nó là (JS gốc):

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;
});

Tất cả những gì chúng ta làm ở đây là tìm hướng y của touchmove và nếu chúng ta đang di chuyển xuống màn hình và cuộn mục tiêu là 0, chúng ta sẽ dừng sự kiện. Như vậy, không làm mới.

Điều này có nghĩa là chúng tôi đang bắn vào mọi 'động thái', có thể tốn kém, nhưng là giải pháp tốt nhất tôi tìm thấy cho đến nay ...


2
Sẽ an toàn khi dừng xem ngay khi người dùng cuộn xuống, vì thao tác kéo để làm mới không có cơ hội được kích hoạt. Tương tự như vậy, nếu scrolltop > 0, sự kiện sẽ không được kích hoạt. Trong triển khai của tôi, tôi liên kết touchmovesự kiện trên touchstart, chỉ khi scrollTop <= 0. Tôi hủy liên kết nó ngay khi người dùng cuộn xuống ( initialY >= e.touches[0].clientY). Nếu người dùng cuộn lên ( previousY < e.touches[0].clientY), thì tôi gọi preventDefault.
Nicolas Bouliane

7

Sau nhiều giờ cố gắng, giải pháp này hiệu quả với tôi

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

Không cần sử dụng jQuery cho việc này. Chỉ cần thêm "hành động chạm: pan-down" vào tệp mã css của bạn.
Keegan Teetaert

1
chỉ cần sử dụng điều này trong css của bạn:html{touch-action:pan-down}
csandreas1

5

AngularJS

Tôi đã vô hiệu hóa thành công với chỉ thị AngularJS này:

//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);
        }
    };
});

Sẽ an toàn khi dừng xem ngay khi người dùng cuộn xuống, vì thao tác kéo để làm mới không có cơ hội được kích hoạt.

Tương tự như vậy, nếu scrolltop > 0, sự kiện sẽ không được kích hoạt. Trong triển khai của tôi, tôi liên kết sự kiện touchmove trên touchstart, chỉ khi scrollTop <= 0. Tôi hủy liên kết nó ngay khi người dùng cuộn xuống ( initialY >= e.touches[0].clientY). Nếu người dùng cuộn lên ( previousY < e.touches[0].clientY), thì tôi gọi preventDefault().

Điều này giúp chúng tôi không phải xem các sự kiện cuộn một cách không cần thiết, nhưng vẫn chặn quá mức.

jQuery

Nếu bạn đang sử dụng jQuery, đây là tương đương chưa được kiểm tra . elementlà một phần tử 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);

Đương nhiên, điều tương tự cũng có thể đạt được với JS thuần túy.


Tôi đã phải sử dụng e.originalEvent.touches[0].clientYđể làm cho công việc này. Vẫn đang vật lộn với logic khi để ngăn tải lại. Ngay bây giờ có vẻ như ngẫu nhiên ngăn cuộn lên ... Cảm ơn vì gợi ý đi đúng hướng!
thomas

Yếu tố nào là chỉ thị được thêm vào?
Fizzix

Chỉ thị AngularJS làm việc tốt cho tôi. Chúng tôi đang sử dụng Framework7 và Angular cùng nhau (sẽ không đề xuất điều đó) và một cái gì đó đã chặn hành vi chính xác của scrollTop. Vì vậy, tôi đã phải sửa đổi khi blockScroll sẽ được thêm vào phần tử. Nhưng chỉ muốn nói lời cảm ơn!
Dustin Jensen

5

Javascript đơn giản

Tôi đã thực hiện bằng cách sử dụng javascript tiêu chuẩn. Đơn giản và dễ thực hiện. Chỉ cần dán và nó hoạt động tốt.

<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>

Điều này hoạt động rất tốt cho Chrome, nhưng gây ra một số vấn đề khi cuộn lên cho tôi trên Safari / iOS 9.2 khi cuộn một div ở đầu trang (được sao chép ở đây ). Tôi đã kết thúc bằng cách sử dụng body: {overflow-y:hidden}thủ thuật từ Evyn ở trên .
sennett

downvote như không hoạt động trên chrome, nhưng hoạt động trong ví dụ firefox, embed.plnkr.co/rqbOVSOkKyhAgoHK2sEP mở trong CHỈ DI ĐỘNG
vijay

liên kết mà bạn đã dán cũng hoạt động với chrome trên điện thoại di động Android của tôi. nó không cho phép làm mới khi kéo. Phiên bản android / ios nào bạn đang sử dụng để kiểm tra?
Sacky San

2
Từ Chrome 56, bạn cần đặt thụ động: false để làm cho nó hoạt động: document.addEventListener ('touchstart', touchstartHandler, {passive: false}); document.addEventListener ('touchmove', touchmoveHandler, {passive: false});
Anton Kuzmin

4

Giải pháp tốt nhất về CSS thuần túy:

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;
}

Xem bản demo này: https://jsbin.com/pokusideha/quiet


Bạn có thực sự thử nghiệm điều này trên điện thoại di động bằng chrome?
Gregor Voinov


3

Tôi thấy thiết lập CSS tràn cơ thể của bạn : ẩn là cách đơn giản nhất. Nếu bạn muốn có một trang ứng dụng cuộn, bạn chỉ có thể sử dụng thùng chứa div với các tính năng cuộn.


Có vẻ như không thể sửa nó bằng một dòng nhưng hoạt động như một nét duyên dáng, cảm ơn rất nhiều!
Ignacio Ara

2

Lưu ý rằng overflow-y không được kế thừa, vì vậy bạn cần đặt nó trên TẤT CẢ các phần tử khối.

Bạn có thể làm điều này với jQuery chỉ bằng cách:

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

Trong số các câu trả lời khác, điều này thực sự có ích. Cảm ơn. Thêm dòng này vào css. cơ thể {tràn-y: ẩn; }
Sarin JS

2

Kể từ một vài tuần, tôi phát hiện ra rằng chức năng javascript mà tôi đã sử dụng để vô hiệu hóa hành động làm mới Chrome sẽ không hoạt động nữa. Tôi đã làm điều này để giải quyết nó:

$(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

Dung dịch js nguyên chất.

// 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

Những gì tôi đã làm là thêm sau touchstarttouchend/ touchcancelsự kiện:

scrollTo(0, 1)

Vì chrome không cuộn nếu nó không ở vị trí cuộn, 0điều này sẽ ngăn chrome thực hiện thao tác kéo để làm mới.

Nếu nó vẫn không hoạt động, hãy thử làm điều đó khi tải trang.


0

Tôi đã giải quyết vấn đề kéo xuống để làm mới bằng cách này:

html, body {
    width: 100%;
    height: 100%;
    overflow: hidden;
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.