Tuyên bố từ chối trách nhiệm: những gì tiếp theo chủ yếu là kết quả của thử nghiệm của riêng tôi trong React Native 0.50. Các ScrollView
tài liệu hiện đang thiếu rất nhiều thông tin đề cập dưới đây; chẳng hạn onScrollEndDrag
là hoàn toàn không có giấy tờ. Vì mọi thứ ở đây đều dựa trên hành vi không có giấy tờ, rất tiếc là tôi không thể đưa ra lời hứa rằng thông tin này sẽ vẫn chính xác sau một năm hoặc thậm chí một tháng kể từ bây giờ.
Ngoài ra, mọi thứ bên dưới giả định một chế độ xem cuộn dọc hoàn toàn có độ lệch y mà chúng tôi quan tâm; dịch sang hiệu số x , nếu cần, hy vọng là một bài tập dễ dàng cho người đọc.
Các trình xử lý sự kiện khác nhau khi ScrollView
thực hiện event
và cho phép bạn có được vị trí cuộn hiện tại qua event.nativeEvent.contentOffset.y
. Một số trình xử lý này có hành vi hơi khác nhau giữa Android và iOS, như chi tiết bên dưới.
Trên Android
Kích hoạt mọi khung hình khi người dùng đang cuộn, trên mọi khung hình trong khi chế độ xem cuộn đang lướt sau khi người dùng thả nó ra, trên khung hình cuối cùng khi chế độ xem cuộn dừng lại và cũng có thể bất cứ khi nào độ lệch của chế độ xem cuộn thay đổi do khung của nó thay đổi (ví dụ: do xoay từ ngang sang dọc).
Trên iOS
Kích hoạt khi người dùng đang kéo hoặc trong khi chế độ xem cuộn đang lướt, ở một số tần suất được xác định bởi scrollEventThrottle
và nhiều nhất một lần trên mỗi khung hình khi nào scrollEventThrottle={16}
. Nếu người dùng nhả chế độ xem cuộn trong khi nó có đủ động lượng để lướt, onScroll
trình xử lý cũng sẽ kích hoạt khi nó nghỉ sau khi lướt. Tuy nhiên, nếu người dùng kéo và sau đó phát hành xem di chuyển trong khi nó đang đứng yên, onScroll
được không đảm bảo để lửa cho vị trí chính thức trừ khi scrollEventThrottle
đã được thiết lập như vậy mà onScroll
đám cháy mỗi khung di chuyển.
Có scrollEventThrottle={16}
thể giảm chi phí hiệu suất để cài đặt bằng cách đặt nó thành một số lớn hơn. Tuy nhiên, điều này có nghĩa là điều đó onScroll
sẽ không kích hoạt mọi khung hình.
Kích hoạt khi chế độ xem cuộn dừng lại sau khi lướt. Hoàn toàn không kích hoạt nếu người dùng thả chế độ xem cuộn trong khi nó đứng yên để nó không lướt đi.
onScrollEndDrag
Kích hoạt khi người dùng ngừng kéo chế độ xem cuộn - bất kể chế độ xem cuộn là đứng yên hay bắt đầu lướt.
Với những khác biệt này trong hành vi, cách tốt nhất để theo dõi sự bù đắp phụ thuộc vào hoàn cảnh cụ thể của bạn. Trong trường hợp phức tạp nhất (bạn cần hỗ trợ Android và iOS, bao gồm xử lý các thay đổi trong ScrollView
khung của do xoay và bạn không muốn chấp nhận hình phạt hiệu suất trên Android từ cài đặt scrollEventThrottle
thành 16) và bạn cần xử lý những thay đổi đối với nội dung trong chế độ xem cuộn, thì đó là một mớ hỗn độn chết tiệt.
Trường hợp đơn giản nhất là nếu bạn chỉ cần xử lý Android; chỉ cần sử dụng onScroll
:
<ScrollView
onScroll={event => {
this.yOffset = event.nativeEvent.contentOffset.y
}}
>
Để hỗ trợ thêm cho iOS, nếu bạn hài lòng với việc kích hoạt onScroll
trình xử lý mọi khung hình và chấp nhận các tác động hiệu suất của điều đó và nếu bạn không cần xử lý các thay đổi về khung hình, thì nó chỉ phức tạp hơn một chút:
<ScrollView
onScroll={event => {
this.yOffset = event.nativeEvent.contentOffset.y
}}
scrollEventThrottle={16}
>
Để giảm chi phí hiệu suất trên iOS trong khi vẫn đảm bảo rằng chúng tôi ghi lại bất kỳ vị trí nào mà chế độ xem cuộn ổn định, chúng tôi có thể tăng scrollEventThrottle
và cung cấp thêm một onScrollEndDrag
trình xử lý:
<ScrollView
onScroll={event => {
this.yOffset = event.nativeEvent.contentOffset.y
}}
onScrollEndDrag={event => {
this.yOffset = event.nativeEvent.contentOffset.y
}}
scrollEventThrottle={160}
>
Nhưng nếu chúng ta muốn xử lý các thay đổi về khung hình (ví dụ: vì chúng ta cho phép thiết bị được xoay, thay đổi chiều cao có sẵn cho khung của chế độ xem cuộn) và / hoặc thay đổi nội dung, thì chúng ta phải triển khai thêm cả hai onContentSizeChange
và onLayout
để theo dõi chiều cao của cả hai khung của chế độ xem cuộn và nội dung của nó, và do đó liên tục tính toán độ chênh lệch tối đa có thể và suy ra khi độ lệch được tự động giảm do thay đổi kích thước khung hoặc nội dung:
<ScrollView
onLayout={event => {
this.frameHeight = event.nativeEvent.layout.height;
const maxOffset = this.contentHeight - this.frameHeight;
if (maxOffset < this.yOffset) {
this.yOffset = maxOffset;
}
}}
onContentSizeChange={(contentWidth, contentHeight) => {
this.contentHeight = contentHeight;
const maxOffset = this.contentHeight - this.frameHeight;
if (maxOffset < this.yOffset) {
this.yOffset = maxOffset;
}
}}
onScroll={event => {
this.yOffset = event.nativeEvent.contentOffset.y;
}}
onScrollEndDrag={event => {
this.yOffset = event.nativeEvent.contentOffset.y;
}}
scrollEventThrottle={160}
>
Vâng, nó khá kinh hoàng. Tôi cũng không chắc chắn 100% rằng nó sẽ luôn hoạt động bình thường trong trường hợp bạn đồng thời thay đổi kích thước của cả khung và nội dung của dạng xem cuộn. Nhưng đó là cách tốt nhất mà tôi có thể nghĩ ra và cho đến khi tính năng này được thêm vào trong chính khuôn khổ , tôi nghĩ đây là điều tốt nhất mà bất kỳ ai cũng có thể làm được.