2012-09-18 42 views
6

Tôi sử dụng preventDefault() trên touchstart trên tài liệu để tránh di chuyển trên trang. Thật không may điều này ngăn cản quá nhiều. Người dùng không còn có thể tập trung vào đầu vào (và mở bàn phím mềm). Sử dụng jQuery focus(), tôi có thể tập trung vào đầu vào trên touchstart. Điều này mở bàn phím mềm trên iOS (hầu hết thời gian), nhưng không bao giờ trên Android.Ngăn chặn di chuyển trên trình duyệt di động, mà không ngăn chặn việc nhập tiêu điểm

nền:

Tôi có một trang web mà tôi muốn thực hiện càng nhiều như một ứng dụng di động càng tốt. Tôi chỉ thực sự quan tâm đến Android và iOS, nhưng bất kỳ yếu tố hình thức nào. Tôi bắt đầu bằng cách làm cho nội dung trong trang chính xác cùng kích thước với kích thước màn hình. Điều này là tốt đẹp cho đến khi người dùng đặt ngón tay của họ trên trang. Tôi cần phải ngăn người dùng cuộn. Mã sau đây hoàn thành điều này, nhưng theo những cách hơi khác nhau trên hai hệ điều hành.

$(document).on('touchstart', function(e) { 
    e.preventDefault(); 
}); 

Trên iOS, điều này sẽ ngăn không cho cuộn đàn hồi: nơi người dùng có thể cuộn ra khỏi trang. Tính năng này rất hay cho một trang web thông thường, nhưng trong trường hợp của tôi nó làm giảm chất lượng của UX.

Trên Android, ngăn chặn sự mặc khải của một hack tiện dụng mà tôi sử dụng để ẩn thanh địa chỉ. Trình duyệt Android bắt đầu bằng thanh địa chỉ có thể nhìn thấy, nhưng khi người dùng cuộn xuống trang, nó sẽ biến mất. Để lập trình buộc trình duyệt ẩn thanh địa chỉ, chỉ cần thêm dòng mã này vào hàm của bạn được gọi là lúc tải.

$('html, body').scrollTop(1); 

Đây là cách hacky (nhưng cũng là cách duy nhất) để thông báo cho trình duyệt android mà chúng tôi đã cuộn và thanh địa chỉ không còn cần thiết nữa.

Nếu không có ngăn chặnĐối với tài liệu, trình duyệt Android sẽ cho phép cuộn và thanh địa chỉ có thể được tiết lộ.

Vì vậy, cả hai hệ điều hành đều có lý do chính đáng để ngăn chặn điều nàyDefault() được gọi trên mọi touchstart trên tài liệu, nhưng nó ngăn cản quá nhiều. Khai thác trên một lĩnh vực đầu vào không có gì. Sử dụng một cuộc gọi đến jQuery focus() có thể giúp, nhưng chỉ mở bàn phím mềm trên iOS chứ không phải Android.

$('input').on('touchstart', function() { 
    $(this).focus(); 
}); 

Làm thế nào tôi có thể ngăn chặn trang từ di chuyển, nhưng sử dụng các chức năng bản địa trình duyệt đã cho tập trung vào các lĩnh vực đầu vào?

Lưu ý: Mã này

$(document).on('touchstart', function(e) { 
    if (e.target.nodeName !== 'INPUT') { 
     e.preventDefault(); 
    } 
}); 

là sai lầm vì người sử dụng vẫn có thể cuộn trang miễn là các liên lạc ban đầu xuất phát từ bên trong lĩnh vực đầu vào.

Trả lời

8

Tôi thực sự đã giải quyết vấn đề này trên một dự án khác, quên nó đi, và nhớ nó hầu hết các cách thông qua việc gõ này lên.

Điều quan trọng là chỉ cần làm điều đó trên touchmove.

$(document).on('touchmove', function(e) { 
    e.preventDefault(); 
}); 

Tuy nhiên, ngăn chặnDefault on touchstart thực hiện tất cả những điều tốt đẹp như ngăn menu lưu hình trên trình chiếu được bật cử chỉ. Các dự án của tôi cũng bao gồm điều này.

$(document).on('touchstart', function(e) { 
    if (e.target.nodeName !== 'INPUT') { 
     e.preventDefault(); 
    } 
}); 

Nếu ai đó có một số đề xuất về nội dung bổ sung hoặc cách định dạng lại để có thể tiếp cận nhiều khán giả hơn. Tôi chưa bao giờ nhìn thấy nội dung tôi có ở đây tất cả ở một nơi, vì vậy tôi cảm thấy rằng nó cần phải được trên SO.

0

Kết hợp hai!

// prevent scrolling from outside of input field 
$(document).on('touchstart', function(e) { 
    if (e.target.nodeName !== 'INPUT') { 
     e.preventDefault(); 
    } 
}); 

// prevent scrolling from within input field 
$(document).on('touchmove', function(e) { 
    if (e.target.nodeName == 'INPUT') { 
     e.preventDefault(); 
    } 
}); 

Điều này có lẽ không hoàn hảo, và tôi đặc biệt lo lắng rằng chức năng đầu tiên sẽ ngăn các liên kết sau, nhưng tôi sẽ để cho người khác thực hiện các kiểm tra mở rộng.

0

Câu trả lời đơn giản cho câu hỏi của bạn là không sử dụng "preventDefault" thay vì sử dụng con trỏ-sự kiện css tài sản để vô hiệu hóa các di chuyển trên các yếu tố có thể cuộn.

CSS cho đầu vào của bạn:

input { 
    pointer-events: auto !important; 
} 

touchstart nghe sự kiện:

document.body.addEventListener('touchstart', function(e) { 
    if (e.target.nodeName === 'INPUT') { 
     this.style.pointerEvents = 'none'; 
    } 
}); 

Bạn sẽ cần phải thiết lập lại con trỏ-sự kiện khi bạn làm mờ đầu vào.

document.body.pointerEvents = 'auto'; 

+1 Tốt Câu hỏi

+0

Vì vậy, bạn đang thay đổi DOM trên mỗi touchstart và trên mỗi touchend. Có lẽ đây không phải là cách ánh sáng, nếu chúng ta xem xét các màn trình diễn. –

Các vấn đề liên quan