Command Palette

Search for a command to run...

Cách làm chủ StyleSheet & Flexbox Layout trong React Native

StyleSheet & Flexbox trong React Native

Chào mừng bạn quay trở lại! Ở bài trước, chúng ta đã có đủ "vật liệu xây dựng" (View, Text, Image...). Nhưng nếu bạn chỉ thả chúng vào code, giao diện trông sẽ vô cùng lộn xộn, xám xịt và các thành phần cứ đè lền nhau.

Giống như việc xây một căn nhà, có gạch vữa thôi là chưa đủ. Bạn cần một bản thiết kế nội thất để quyết định xem tivi đặt ở đâu, sofa màu gì, và các phòng được phân chia ra sao. Trong React Native, công việc "thiết kế nội thất" đó được đảm nhiệm bởi StyleSheet và hệ thống bố cục Flexbox.

Bài viết này sẽ giúp bạn nắm vững nghệ thuật sắp xếp giao diện chuẩn xác đến từng pixel!

1. Tạm biệt CSS truyền thống, chào đón StyleSheet

Nếu bạn xuất thân từ lập trình Web, bạn có thể đang tìm kiếm các file .css để viết style. Hãy dừng lại! React Native không sử dụng CSS thuần túy. Thay vào đó, tất cả các kiểu dáng đều được viết trực tiếp bằng JavaScript Objects.

React Native Styling

Quy tắc "Nhập gia tùy tục"

Có hai điểm khác biệt lớn nhất giữa CSS Web và Styling trong React Native mà bạn phải khắc cốt ghi tâm:

  1. Tên thuộc tính viết theo kiểu camelCase: Thay vì viết background-color, bạn phải viết là backgroundColor. Thay vì font-size, bạn viết là fontSize.
  2. Không có đơn vị px hay em: Mọi con số kích thước đều là số nguyên không có đơn vị. Hệ thống sẽ tự động quy đổi chúng thành các điểm ảnh độc lập với mật độ (dp/pt) để hiển thị đồng nhất trên mọi loại màn hình.

Cách sử dụng StyleSheet.create()

Mặc dù bạn có thể truyền thẳng style vào thẻ (gọi là Inline Style), nhưng cách chuyên nghiệp và tối ưu hiệu năng nhất là sử dụng StyleSheet.create().

import React from 'react'
import { View, Text, StyleSheet } from 'react-native'

export default function App() {
  return (
    <View style={styles.container}>
      <Text style={styles.title}>Phong cách chuẩn React Native</Text>
    </View>
  )
}

const styles = StyleSheet.create({
  container: {
    backgroundColor: '#1e272e',
    padding: 20,
    borderRadius: 15,
  },
  title: {
    color: '#0fbcf9',
    fontSize: 24,
    fontWeight: 'bold',
  },
})

2. Flexbox: Nghệ thuật xếp đội hình chuẩn xác

Biết tô màu và đổi phông chữ là một chuyện, nhưng làm sao để đặt hai nút bấm nằm cạnh nhau, hoặc canh giữa hoàn hảo một bức ảnh trên màn hình? Đó là lúc Flexbox ra sân.

React Native Flexbox Layout

Flexbox là một thuật toán dàn trang vô cùng mạnh mẽ. Hãy tưởng tượng bạn đang thiết kế một ứng dụng cẩm nang chiến thuật cho tựa game LoL, và bạn cần tạo một thẻ hiển thị bộ đôi phối hợp cực mạnh: Katarina (Đường giữa) và Lee Sin (Đi rừng). Bạn không thể vứt bừa bãi avatar của họ lên màn hình được. Flexbox chính là sa bàn chiến thuật giúp bạn định vị họ chính xác.

#1: flexDirection (Trục hướng của đội hình)

Thuộc tính này quyết định các thành phần con bên trong thẻ <View> sẽ xếp theo hàng ngang hay hàng dọc.

  • column: (Mặc định trong React Native) Xếp từ trên xuống dưới.
  • row: Xếp từ trái sang phải.

Lưu ý lớn: Trên Web, Flexbox mặc định là row. Nhưng trên Mobile, do màn hình điện thoại hình chữ nhật đứng, React Native đã thiết lập mặc định là column.

#2: justifyContent (Dàn quân trên trục chính)

Khi bạn đã chọn hướng (flexDirection), justifyContent sẽ giúp bạn phân bổ khoảng cách của các phần tử dọc theo cái hướng đó. Ví dụ, nếu flexDirectionrow (hàng ngang), justifyContent sẽ sắp xếp các avatar nằm trên đường ngang đó.

Các giá trị phổ biến:

  • flex-start: Dồn hết về đầu.
  • center: Căn giữa hoàn hảo.
  • space-between: Đẩy hai phần tử ra sát hai mép màn hình, khoảng trống ở giữa.
  • space-around: Chia đều khoảng trống xung quanh các phần tử.

#3: alignItems (Dàn quân trên trục phụ)

Nếu justifyContent lo trục chính, thì alignItems sẽ lo trục vuông góc với nó. Ví dụ, nếu bạn đang xếp hàng ngang (row), thì alignItems sẽ giúp bạn quyết định xem các avatar nên nằm trồi lên trên, tụt xuống dưới, hay căn giữa theo chiều dọc của hàng đó.

3. Thực hành: Dựng "thẻ chiến thuật" bằng Flexbox

Để hiểu rõ cách các thuộc tính trên phối hợp với nhau, chúng ta hãy viết code cho giao diện hiển thị bộ đôi Katarina và Lee Sin nhé. Mục tiêu là một chiếc thẻ có viền, bên trong là 2 avatar nằm cạnh nhau, chia đều khoảng cách, và được căn giữa theo chiều dọc.

import React from 'react'
import { View, Text, Image, StyleSheet } from 'react-native'

export default function SynergyCard() {
  return (
    // Box ngoài cùng chiếm toàn bộ màn hình và căn giữa cái thẻ
    <View style={styles.screen}>
      {/* Đây là Thẻ Chiến Thuật của chúng ta */}
      <View style={styles.card}>
        {/* Khối chứa Katarina */}
        <View style={styles.championBox}>
          <Image source={{ uri: 'https://link-to-katarina-avatar.png' }} style={styles.avatar} />
          <Text style={styles.name}>Katarina</Text>
          <Text style={styles.role}>Đường Giữa</Text>
        </View>

        {/* Khối chứa biểu tượng kết hợp ở giữa */}
        <Text style={styles.vsText}>🤝</Text>

        {/* Khối chứa Lee Sin */}
        <View style={styles.championBox}>
          <Image source={{ uri: 'https://link-to-leesin-avatar.png' }} style={styles.avatar} />
          <Text style={styles.name}>Lee Sin</Text>
          <Text style={styles.role}>Đi Rừng</Text>
        </View>
      </View>
    </View>
  )
}

const styles = StyleSheet.create({
  screen: {
    flex: 1, // Chiếm toàn bộ không gian màn hình
    justifyContent: 'center', // Căn giữa theo chiều dọc (vì flexDirection mặc định là column)
    alignItems: 'center', // Căn giữa theo chiều ngang
    backgroundColor: '#111',
  },
  card: {
    flexDirection: 'row', // QUAN TRỌNG: Dàn hàng ngang
    justifyContent: 'space-around', // Chia đều khoảng cách giữa 2 tướng và biểu tượng
    alignItems: 'center', // Căn giữa chúng theo chiều dọc của thẻ
    backgroundColor: '#2d3436',
    width: '90%',
    padding: 20,
    borderRadius: 15,
    borderWidth: 2,
    borderColor: '#c8d6e5',
  },
  championBox: {
    alignItems: 'center', // Căn giữa ảnh và chữ của từng tướng
  },
  avatar: {
    width: 80,
    height: 80,
    borderRadius: 40,
    borderWidth: 2,
    borderColor: '#fdcb6e',
  },
  name: {
    color: '#fff',
    fontWeight: 'bold',
    marginTop: 10,
    fontSize: 16,
  },
  role: {
    color: '#b2bec3',
    fontSize: 12,
  },
  vsText: {
    fontSize: 24,
  },
})

Chỉ với vài dòng Flexbox, mọi thứ đã tự động xếp vào đúng vị trí một cách gọn gàng, bất kể màn hình điện thoại to hay nhỏ.

Kết luận: Dựng giao diện đẹp mắt không hề khó

Ghi nhớ "thần chú" khi làm giao diện React Native:

  1. Luôn dùng StyleSheet.create().
  2. Không dùng px, thuộc tính viết kiểu camelCase.
  3. Flexbox là công cụ duy nhất bạn cần để bố cục mọi thứ. Hãy xác định Trục chính (flexDirection) trước, sau đó chỉnh khoảng cách trên trục chính bằng justifyContent, và trục phụ bằng alignItems.

Bây giờ ứng dụng của bạn đã đẹp mắt và có cấu trúc vững vàng. Tuy nhiên, nó vẫn chưa thể phản hồi khi người dùng thao tác. Ở bài tiếp theo, chúng ta sẽ học cách biến những thẻ giao diện tĩnh này thành các nút bấm sống động, biết lắng nghe từng cái chạm của người dùng!

Bài viết liên quan

Tìm hiểu 5 Core Components quan trọng nhất trong React Native

Hướng dẫn cách sử dụng các Core Components trong React Native. Nắm vững View, Text, Image, TextInput và ScrollView để xây dựng mọi giao diện mobile.

Ôn tập React Hooks: Cách hoạt động của chúng trong môi trường Mobile

Chưa hiểu rõ luồng dữ liệu trong React Native? Bài viết này sẽ giải thích cặn kẽ cách sử dụng useState, useEffect và useRef qua các ví dụ thực tế dễ hiểu nhất.

Phân tích luồng chạy ứng dụng Expo chi tiết từ A-Z

Tìm hiểu cách ứng dụng khởi chạy, làm chủ thư mục app/, cấu trúc file cơ bản và phân tích cú pháp JSX một cách cực kỳ dễ hiểu.

Hướng dẫn cài đặt môi trường React Native & Expo trong 15 phút

Bạn sợ cài đặt môi trường lập trình mobile phức tạp? Hướng dẫn chi tiết cách dùng Expo Go, Node.js để chạy app React Native ngay lập tức.