Bạn đặt một lớp View phủ lên vùng nội dung để hiển thị nút nổi. Phần nền trong suốt của lớp phủ có thể ảnh hưởng thao tác với nội dung bên dưới. Nếu tắt chạm cho cả cây con, nút nổi cũng không dùng được. pointerEvents cho phép mô tả riêng vai trò của hộp View và các con của nó.
Bài đọc tài liệu React Native 0.88 ngày 05/11/2026. JSX được rà thủ công theo View và StyleSheet; chưa build native, chạy Hermes hoặc kiểm tra thao tác trên Android/iOS. Mọi hành vi cần quan sát bên dưới là checklist thử nghiệm, không phải kết quả đã đo trên thiết bị.
Bốn chế độ cần phân biệt
| Giá trị | Hộp View có thể là đích chạm | Các con có thể là đích chạm |
|---|---|---|
| auto | Có | Có |
| none | Không | Không |
| box-none | Không | Có |
| box-only | Có | Không |
Bảng nói về khả năng tham gia chọn đích chạm trong cây View. Nó không tự gắn onPress cho một View, không đổi thứ tự vẽ và không thay cho trạng thái disabled của nút. Một lớp phủ nhìn xuyên qua được chưa có nghĩa thao tác chạm cũng xuyên qua.
1. Demo có vùng nền và nút nổi riêng
Trong project React Native đang chạy, dùng component sau làm một màn hình thử. Các nút đổi chế độ nằm ngoài vùng phủ để bạn luôn đổi lại được:
import React, {useState} from 'react';
import {Button, Pressable, StyleSheet, Text, View} from 'react-native';
const modes = ['auto', 'none', 'box-none', 'box-only'];
export default function PointerEventsDemo() {
const [mode, setMode] = useState('box-none');
const [baseCount, setBaseCount] = useState(0);
const [floatingCount, setFloatingCount] = useState(0);
return (
<View style={styles.screen}>
{modes.map(value => (
<Button key={value} title={value} onPress={() => setMode(value)} />
))}
<Text>Chế độ: {mode}</Text>
<Text>Nền: {baseCount} / Nút nổi: {floatingCount}</Text>
<View style={styles.stage}>
<Pressable
accessibilityRole="button"
style={[StyleSheet.absoluteFill, styles.base]}
onPress={() => setBaseCount(count => count + 1)}>
<Text>Chạm vùng nền ở giữa</Text>
</Pressable>
<View
pointerEvents={mode}
style={[StyleSheet.absoluteFill, styles.overlay]}>
<Pressable
accessibilityRole="button"
style={styles.floating}
onPress={() => setFloatingCount(count => count + 1)}>
<Text>Nút nổi</Text>
</Pressable>
</View>
</View>
</View>
);
}
const styles = StyleSheet.create({
screen: {flex: 1, padding: 24, paddingTop: 48},
stage: {flex: 1, minHeight: 200, marginTop: 12},
base: {backgroundColor: '#e4eef7', alignItems: 'center', justifyContent: 'center'},
overlay: {alignItems: 'flex-end', justifyContent: 'flex-start'},
floating: {padding: 20, backgroundColor: '#ffe3a3'},
});
StyleSheet.absoluteFill đặt vị trí tuyệt đối với bốn cạnh bằng 0. Cả nút nền và View phủ lấy kích thước của stage; vùng stage được cấp chỗ bằng flex và minHeight. Nút nổi chỉ chiếm vùng của chính nó ở góc trên bên phải.
Ví dụ dùng pointerEvents như prop của View. Đừng chép cú pháp CSS pointer-events vào StyleSheet rồi mặc định nó là cùng API. Khi đổi phiên bản hoặc chuyển sang thư viện gesture, đối chiếu hợp đồng tương ứng của thành phần đang thật sự nhận sự kiện.
2. Kiểm tra box-none trước
Ở chế độ mặc định box-none, thử chạm giữa vùng nền, cách xa nút nổi. Bộ đếm nền là dấu hiệu để bạn kiểm tra thao tác đã tới Pressable bên dưới. Sau đó chạm đúng nút nổi và quan sát bộ đếm riêng của nó.
Điểm cần chứng minh là hộp View phủ không làm đích chạm, nhưng con tương tác của nó vẫn có thể nhận thao tác. Nếu nút nổi cũng không hoạt động, kiểm tra mode hiện tại, kích thước vùng con và các lớp cha; không chỉ nhìn màu nền.
3. Đổi chế độ để đối chiếu
Với none, cả lớp phủ lẫn con không tham gia nhận chạm; thử vị trí nút nổi và kiểm tra nội dung bên dưới vị trí ấy. Với box-only, các con không làm đích chạm; trong demo, bản thân View phủ không có handler nghiệp vụ nên không có bộ đếm dành cho nó.
Với auto, lớp phủ có thể tham gia chọn đích chạm ở vùng hộp của nó. Dùng chế độ này để đối chiếu phần nền trống của overlay với box-none. Ghi lại kết quả trên cả Android và iOS của project, đặc biệt nếu màn hình thật có ScrollView, gesture handler hoặc handler responder ở tổ tiên.
Giới hạn cần kiểm tra riêng
pointerEvents không tự ẩn component khỏi screen reader và không thay thế việc thiết kế thứ tự focus. Sau khi kiểm tra chạm trực tiếp, thử TalkBack hoặc VoiceOver theo yêu cầu của ứng dụng. Bộ đếm onPress trong demo chưa chứng minh trải nghiệm accessibility hoàn chỉnh.
Không suy ra một lớp phủ là cơ chế chặn toàn bộ tương tác chỉ vì nó trông như loading mask. Nếu nghiệp vụ cần khóa hành động, xử lý trạng thái disabled và đường gọi tương ứng của component. Dùng pointerEvents để cấu hình chọn đích chạm, rồi xác nhận các vùng thật sự hoạt động bằng một màn hình thử nhỏ trước khi ghép vào layout phức tạp.

