Bạn muốn một thông báo rỗng nằm giữa phần màn hình còn lại, nhưng thêm justifyContent vào style của ScrollView không cho kết quả như dự định. ScrollView có khung hiển thị và vùng bao nội dung con. Cần đặt quy tắc căn các child ở đúng lớp, đồng thời giữ khung cuộn có chiều cao giới hạn.
Bài đối chiếu tài liệu React Native 0.88 ngày 09/11/2026. Ví dụ JSX được rà theo API, chưa chạy Metro, Hermes, build native hoặc thiết bị. Danh sách quan sát trong bài là kế hoạch kiểm tra trên dự án của bạn, không phải kết quả đo layout thực tế.
Hai lớp style phục vụ hai mục đích
ScrollView mô tả contentContainerStyle là style dành cho container bọc các child. Style của ScrollView tác động đến chính khung hiển thị cuộn. Trong ví dụ, khung nhận flex 1 để dùng phần chiều cao còn lại; vùng nội dung nhận padding và cách căn thông báo rỗng.
Tài liệu cũng yêu cầu ScrollView nằm trong một chuỗi cha có chiều cao giới hạn. Chỉ thêm style ở nội dung mà bỏ quên bố cục của các view cha có thể khiến vấn đề khó chẩn đoán hơn. Hãy kiểm tra từ khung ngoài vào trong, thay vì thay ngẫu nhiên nhiều prop cuộn.
Một màn hình chuyển giữa rỗng và nhiều dòng
Thử component sau trong ứng dụng React Native đã được cấu hình. Ví dụ dùng core components và dữ liệu tạo tại máy:
import React, {useState} from 'react';
import {Button, ScrollView, StyleSheet, Text, View} from 'react-native';
export default function ContentContainerDemo() {
const [hasRows, setHasRows] = useState(false);
const rows = hasRows
? Array.from({length: 30}, (_, index) => ({
id: `row-${index + 1}`,
title: `Mục ${index + 1}`,
}))
: [];
return (
<View style={styles.screen}>
<Button
title={hasRows ? 'Chuyển sang rỗng' : 'Hiện 30 dòng'}
onPress={() => setHasRows(value => !value)}
/>
<ScrollView
style={styles.viewport}
contentContainerStyle={[
styles.content,
rows.length === 0 && styles.emptyContent,
]}>
{rows.length === 0 ? (
<Text style={styles.emptyText}>Chưa có mục nào</Text>
) : (
rows.map(row => (
<Text key={row.id} style={styles.row}>{row.title}</Text>
))
)}
</ScrollView>
</View>
);
}
const styles = StyleSheet.create({
screen: {flex: 1, padding: 24},
viewport: {flex: 1, backgroundColor: '#f1f4f8'},
content: {padding: 20},
emptyContent: {flexGrow: 1, justifyContent: 'center', alignItems: 'center'},
emptyText: {fontSize: 18},
row: {paddingVertical: 16, fontSize: 18},
});
emptyContent chỉ được thêm khi danh sách rỗng. Khi có dữ liệu, các row đi theo vùng nội dung có padding mà không nhận quy tắc căn giữa của trạng thái rỗng. Nút chuyển trạng thái nằm ngoài ScrollView để vẫn có thể dùng khi đang xem dữ liệu dài.
Vì sao dùng flexGrow ở nội dung rỗng?
Layout Props mô tả flexGrow là cách phân phối phần không gian còn lại. Ở cấu trúc minh họa này, vùng nội dung rỗng được cho khả năng tăng để có vùng căn giữa bên trong khung còn lại. Đây không phải một chiều cao màn hình được tính tay hoặc một số pixel cố định.
Không coi flex 1 và flexGrow 1 là hai cách viết luôn giống nhau. Tài liệu giải thích flex dương còn liên quan đến flexShrink và flexBasis. Nếu thay một shorthand trong vùng nội dung, cần kiểm tra cả trạng thái ngắn lẫn dài thay vì chỉ nhìn ảnh chụp màn hình rỗng.
Kế hoạch kiểm tra có thể quan sát
Đầu tiên, kiểm tra thông báo rỗng được căn giữa vùng nền của khung cuộn, bên dưới nút. Sau đó chuyển sang 30 dòng, cuộn tới Mục 30 và xác nhận dòng cuối có thể được đọc đầy đủ. Đổi kích thước cửa sổ hoặc xoay thiết bị rồi kiểm tra lại hai trạng thái.
Tiếp theo, tăng cỡ chữ hệ thống. Dữ liệu có thể chiếm chiều cao khác, nên không lấy số dòng trong ví dụ làm bảo đảm rằng mọi màn hình đều cần cuộn đúng một số lần. Khi tìm lỗi, bật inspector để phân biệt kích thước viewport với content container và đọc style đang được áp dụng ở mỗi lớp.
Giữ giới hạn của ví dụ rõ ràng
ScrollView tạo các child cùng lúc; ví dụ dùng 30 dòng chỉ để kiểm tra bố cục, không phải khuyến nghị dùng nó cho danh sách lớn hoặc tải vô hạn. Nếu nội dung là danh sách dài trong sản phẩm, cân nhắc FlatList và các khả năng phù hợp với cấu trúc dữ liệu.
Padding màn hình ở đây là khoảng cách minh họa, không thay cho xử lý safe area hoặc bàn phím của ứng dụng thật. Bài cũng không triển khai gọi API, refresh hoặc khôi phục vị trí cuộn sau khi đổi state. Mục tiêu duy nhất là nhìn rõ lớp nào nhận style nào, rồi kiểm tra vùng rỗng và nội dung dài theo cùng một cấu trúc.


