![]()
Ở bài trước, chúng ta đã trở thành những "kiến trúc sư" thực thụ khi sử dụng Flexbox để dàn trang và StyleSheet để làm đẹp cho ứng dụng. Tuy nhiên, dù giao diện của bạn có lộng lẫy đến đâu, nó vẫn chỉ là một bức tranh tĩnh nếu người dùng chạm vào mà không có chuyện gì xảy ra.
Trong bài này, chúng ta sẽ biến ứng dụng thành một thực thể "sống", biết lắng nghe và phản hồi lại mọi thao tác vuốt, chạm của người dùng. Hãy cùng khám phá cách xử lý sự kiện (Event Handling) trong React Native!
1. Sự thật bất ngờ về thẻ Button trong React Native
Nếu bạn đã từng lập trình Web, phản xạ đầu tiên của bạn khi muốn tạo một nút bấm là tìm đến thẻ <button>. React Native cũng cung cấp một Core Component tên là <Button>.
Tuy nhiên, có một sự thật phũ phàng: Các lập trình viên chuyên nghiệp hiếm khi dùng nó.
Tại sao vậy? Vì thẻ <Button> gốc của React Native rất cứng nhắc. Bạn không thể thêm thuộc tính style cho nó. Bạn không thể đổi font chữ, không thể bo góc, và tệ nhất là: Giao diện của nó trên iOS và Android trông hoàn toàn khác nhau!
Để có một nút bấm đẹp mắt, đồng nhất trên mọi thiết bị và có thể tùy biến 100% bằng Flexbox, chúng ta phải sử dụng nhóm component mang họ Touchable hoặc thế hệ mới nhất là Pressable.
2. Kỷ nguyên của Touchable: TouchableOpacity
Đây là "người hùng" được sử dụng nhiều nhất để tạo nút bấm trong suốt chiều dài lịch sử của React Native.
Đúng như tên gọi của nó (Opacity = Độ mờ), khi người dùng chạm vào thẻ này, toàn bộ nội dung bên trong sẽ hơi mờ đi một chút, tạo ra một hiệu ứng phản hồi thị giác cực kỳ tự nhiên và quen thuộc trên điện thoại.
Cách biến mọi thứ thành nút bấm
Bạn có thể bọc TouchableOpacity bên ngoài một đoạn Text, một bức ảnh, hoặc cả một khối View khổng lồ.
Hãy lấy ví dụ về việc xây dựng giao diện cho một ứng dụng cẩm nang chiến thuật. Khi người dùng muốn chốt một đội hình phối hợp chuẩn xác (đảm bảo tính tương thích về vai trò đi đường, chẳng hạn như kết hợp Đường Giữa và Đi Rừng), họ sẽ nhấn vào một nút xác nhận.
import React, { useState } from 'react'
import { View, Text, TouchableOpacity, StyleSheet } from 'react-native'
export default function SynergySelector() {
const [selectedSynergy, setSelectedSynergy] = useState('Chưa có đội hình nào được chọn')
const handleSelectDuo = () => {
// Cập nhật state khi nút được nhấn.
// Ở đây ta chọn một cặp Mid - Rừng chuẩn mực.
setSelectedSynergy('Katarina (Mid) & Amumu (Rừng)')
}
return (
<View style={styles.container}>
<Text style={styles.statusText}>Đang chọn: {selectedSynergy}</Text>
{/* Nút bấm tự thiết kế với TouchableOpacity */}
<TouchableOpacity
style={styles.button}
onPress={handleSelectDuo} // Bắt sự kiện nhấn
activeOpacity={0.7} // Tùy chỉnh độ mờ khi nhấn (mặc định là 0.2)
>
<Text style={styles.buttonText}>Xác Nhận Đội Hình</Text>
</TouchableOpacity>
</View>
)
}
const styles = StyleSheet.create({
container: { flex: 1, justifyContent: 'center', alignItems: 'center' },
statusText: { fontSize: 18, marginBottom: 20, color: '#333' },
button: {
backgroundColor: '#0984e3',
paddingVertical: 12,
paddingHorizontal: 30,
borderRadius: 8,
elevation: 3, // Tạo bóng đổ trên Android
shadowColor: '#000', // Tạo bóng đổ trên iOS
shadowOffset: { width: 0, height: 2 },
shadowOpacity: 0.2,
},
buttonText: { color: 'white', fontSize: 16, fontWeight: 'bold' },
})
(Lưu ý: Nếu bạn sử dụng TouchableWithoutFeedback, nút bấm sẽ nhận sự kiện nhưng không có bất kỳ hiệu ứng mờ hay đổi màu nào. Nó thường được dùng cho các thao tác ẩn, ví dụ: Chạm vào khoảng không bên ngoài để ẩn bàn phím đi).
3. Tương lai của tương tác: Component Pressable
Mặc dù TouchableOpacity rất tốt, nhưng khi ứng dụng ngày càng phức tạp, đôi khi bạn muốn hiệu ứng nút bấm phong phú hơn là chỉ việc "làm mờ". Ví dụ: Bạn muốn nút bấm đổi sang màu đỏ khi giữ chặt, và chuyển lại màu xanh khi thả tay ra.
Đó là lý do React Native cho ra mắt Pressable. Đây là component hiện đại nhất, linh hoạt nhất và được khuyên dùng để thay thế toàn bộ họ nhà Touchable trong các dự án mới.
Sức mạnh của trạng thái pressed
Điểm "ăn tiền" nhất của Pressable là nó cho phép bạn truyền một hàm vào thuộc tính style để theo dõi xem nút có đang bị nhấn hay không.
import React from 'react'
import { Pressable, Text, StyleSheet, View } from 'react-native'
export default function ModernButton() {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Pressable
onPress={() => console.log('Đã nhấn!')}
style={({ pressed }) => [
styles.baseButton,
// Nếu đang bị nhấn (pressed = true), đổi nền sang màu xám đen
pressed ? { backgroundColor: '#2d3436' } : { backgroundColor: '#00b894' },
]}
>
{({ pressed }) => <Text style={styles.text}>{pressed ? 'Đang giữ chặt...' : 'Chạm vào tôi!'}</Text>}
</Pressable>
</View>
)
}
const styles = StyleSheet.create({
baseButton: {
padding: 15,
borderRadius: 10,
minWidth: 150,
alignItems: 'center',
},
text: { color: 'white', fontWeight: 'bold' },
})
Với Pressable, bạn làm chủ 100% cảm giác tương tác mà không cần phải viết những dòng code phức tạp để theo dõi animation.
4. Các loại sự kiện chạm mở rộng
Cả TouchableOpacity và Pressable đều hỗ trợ nhiều mốc sự kiện hơn là chỉ một cú chạm (onPress). Bạn có thể tận dụng chúng để tạo ra các tính năng nâng cao:
onPress: Kích hoạt khi người dùng chạm và thả tay ra (Hành động click phổ biến nhất).onLongPress: Kích hoạt khi người dùng nhấn và giữ nút trong khoảng thời gian đủ lâu (khoảng 500ms). Thường dùng để mở menu phụ hoặc xóa một mục.onPressIn: Kích hoạt ngay khoảnh khắc ngón tay vừa chạm vào màn hình (trước cả khi thả tay).onPressOut: Kích hoạt khoảnh khắc ngón tay rời khỏi màn hình.
Mẹo nâng cao: Pressable còn có thuộc tính hitSlop. Nếu bạn có một nút bấm nhỏ (như nút X để tắt popup), bạn có thể dùng hitSlop={{ top: 10, bottom: 10, left: 10, right: 10 }} để mở rộng vùng có thể chạm, giúp người dùng ngón tay to dễ dàng bấm trúng hơn mà không làm thay đổi kích thước thực sự của nút bấm trên giao diện.
Kết luận: Ứng dụng giờ đã có sự tương tác
Để ứng dụng React Native phản hồi tương tác mượt mà:
- Tránh dùng
<Button>mặc định nếu bạn muốn một giao diện có tính thẩm mỹ và đồng nhất cao. - Dùng
TouchableOpacitycho các trường hợp làm nút bấm nhanh, cần hiệu ứng mờ đơn giản. - Chuyển sang sử dụng
Pressablecho các dự án mới hoặc khi bạn cần tùy biến sâu trạng thái hiển thị lúc bấm, cũng như tận dụnghitSlopđể tối ưu trải nghiệm (UX).
Đến đây, bạn đã biết cách vẽ giao diện và làm cho chúng "biết lắng nghe". Nhưng ứng dụng thực tế thường chứa hàng trăm, hàng ngàn mục dữ liệu (như bảng tin Facebook hay danh sách hàng hóa). Nếu bạn hiển thị tất cả chúng cùng lúc, điện thoại sẽ lập tức bị đơ!
Để giải quyết bài toán hóc búa này, chúng ta sẽ bước sang những bài học tiếp theo.