FractionalTranslation: Dịch Chuyển Linh Hoạt Trong Flutter
Flutter

FractionalTranslation: Dịch Chuyển Linh Hoạt Trong Flutter

Author

Admin System

@root

Ngày xuất bản

18 Mar, 2026

Lượt xem

36 Lượt

"FractionalTranslation"

Chào các "thợ code" tương lai, hôm nay chúng ta sẽ mổ xẻ một công cụ khá hay ho trong hộp đồ nghề Flutter mà nhiều khi các bạn bỏ qua: FractionalTranslation. Nghe tên có vẻ học thuật, nhưng thực ra nó là một "chiếc đòn bẩy" cực kỳ linh hoạt để dịch chuyển các widget của chúng ta.

FractionalTranslation là gì và để làm gì?

Thầy Creyt hay ví von thế này: Bạn có một bức tranh treo tường. Bình thường, bạn sẽ nói "đẩy bức tranh sang phải 10cm" đúng không? Đó là cách chúng ta dùng Transform.translate hoặc Positioned với các giá trị tuyệt đối (pixel). Nhưng nếu bạn muốn nói "đẩy bức tranh sang phải một nửa chiều rộng của chính nó", hoặc "kéo nó lên trên một phần tư chiều cao của nó" thì sao? Đó chính là lúc FractionalTranslation tỏa sáng!

FractionalTranslation là một widget trong Flutter cho phép bạn dịch chuyển con của nó (child widget) tương đối so với kích thước của chính con đó. Thay vì dùng pixel, bạn dùng các giá trị phân số (fraction) từ 0.0 đến 1.0 (hoặc hơn) để định vị.

Để làm gì ư? Nó cực kỳ hữu ích khi bạn muốn tạo ra các hiệu ứng UI động, responsive, hay các animation mà vị trí dịch chuyển cần phải tự động điều chỉnh theo kích thước của widget. Ví dụ, một menu trượt vào từ cạnh màn hình, một thành phần UI tự động căn chỉnh khi kích thước màn hình thay đổi, hoặc hiệu ứng parallax tinh tế.

Thuộc tính chính của nó là translation, nhận một đối tượng Offset.

  • Offset(0.5, 0): Dịch sang phải 50% chiều rộng của child.
  • Offset(-0.25, 0): Dịch sang trái 25% chiều rộng của child.
  • Offset(0, 1.0): Dịch xuống dưới 100% chiều cao của child.
  • Offset(0.5, 0.5): Dịch sang phải 50% chiều rộng VÀ xuống dưới 50% chiều cao của child.
Illustration

Code Ví Dụ Minh Họa: Một Widget "Lướt" Vào Mượt Mà

Để các bạn dễ hình dung, chúng ta sẽ tạo một widget đơn giản, khi bấm nút thì nó sẽ "lướt" từ bên ngoài vào giữa màn hình, rồi lướt ra khi bấm lại. Toàn bộ quá trình dịch chuyển sẽ dựa trên kích thước của chính nó.

import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'FractionalTranslation Demo',
      theme: ThemeData(primarySwatch: Colors.blueGrey),
      home: const FractionalTranslationScreen(),
    );
  }
}

class FractionalTranslationScreen extends StatefulWidget {
  const FractionalTranslationScreen({super.key});

  @override
  State<FractionalTranslationScreen> createState() => _FractionalTranslationScreenState();
}

class _FractionalTranslationScreenState extends State<FractionalTranslationScreen> with SingleTickerProviderStateMixin {
  late AnimationController _controller;
  late Animation<Offset> _animation;

  @override
  void initState() {
    super.initState();
    _controller = AnimationController(
      vsync: this,
      duration: const Duration(milliseconds: 700),
    );

    // Animation starts from Offscreen (1.0 means 100% of its width to the right)
    // and ends at its original position (0.0).
    _animation = Tween<Offset>(
      begin: const Offset(1.0, 0.0), // Start 100% of its width to the right
      end: Offset.zero, // End at its original position
    ).animate(CurvedAnimation(parent: _controller, curve: Curves.easeOutCubic));
  }

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }

  void _toggleAnimation() {
    if (_controller.status == AnimationStatus.completed) {
      _controller.reverse();
    } else {
      _controller.forward();
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('FractionalTranslation Example'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            // Sử dụng AnimatedBuilder để rebuild widget khi animation thay đổi giá trị
            AnimatedBuilder(
              animation: _animation,
              builder: (context, child) {
                return FractionalTranslation(
                  translation: _animation.value, // Giá trị offset thay đổi theo animation
                  child: Material(
                    elevation: 8.0,
                    borderRadius: BorderRadius.circular(12.0),
                    child: Container(
                      width: 200, // Kích thước cố định để dễ hình dung
                      height: 100,
                      padding: const EdgeInsets.all(16.0),
                      alignment: Alignment.center,
                      decoration: BoxDecoration(
                        color: Colors.teal.shade300,
                        borderRadius: BorderRadius.circular(12.0),
                      ),
                      child: const Text(
                        'Xin chào, tôi lướt đây!',
                        style: TextStyle(color: Colors.white, fontSize: 16),
                      ),
                    ),
                  ),
                );
              },
            ),
            const SizedBox(height: 40),
            ElevatedButton(
              onPressed: _toggleAnimation,
              child: const Text('Bật/Tắt Hiệu Ứng Lướt'),
            ),
          ],
        ),
      ),
    );
  }
}

Giải thích:

  1. Chúng ta dùng AnimationController để điều khiển tiến trình animation.
  2. Tween<Offset> được tạo với begin: const Offset(1.0, 0.0)end: Offset.zero. Điều này có nghĩa là widget sẽ bắt đầu dịch chuyển từ vị trí 100% chiều rộng của nó sang phải (ngoài màn hình, nếu nó nằm trong một Row hoặc Stack lớn hơn) và kết thúc ở vị trí ban đầu của nó (không dịch chuyển).
  3. AnimatedBuilder lắng nghe sự thay đổi của _animation và rebuild FractionalTranslation với giá trị translation mới.
  4. FractionalTranslation nhận _animation.value làm thuộc tính translation, khiến Container con của nó dịch chuyển mượt mà.

Mẹo Hay và Best Practices từ Thầy Creyt

  • Nghĩ theo tỷ lệ, không phải pixel: Đây là "bí kíp" lớn nhất. Khi bạn cần một widget dịch chuyển một cách tương đối với chính nó hoặc với một container lớn hơn, hãy nghĩ ngay đến FractionalTranslation. Nó giúp code của bạn linh hoạt và dễ bảo trì hơn rất nhiều khi giao diện thay đổi kích thước.
  • Kết hợp với Animation: FractionalTranslation "sinh ra" là để làm bạn với các animation. Sử dụng AnimatedBuilder hoặc TweenAnimationBuilder để tạo ra các hiệu ứng dịch chuyển mượt mà, tự nhiên.
  • Cẩn thận với Clipping: Đôi khi, khi dịch chuyển một widget ra khỏi giới hạn của cha nó, bạn có thể thấy nó bị cắt (clipped). Nếu muốn nó vẫn hiển thị đầy đủ, hãy đảm bảo widget cha không có thuộc tính clipBehaviorClip.hardEdge hoặc bạn có thể bọc nó trong OverflowBox nếu cần hiển thị ngoài giới hạn.
  • So sánh với Transform.translate: Transform.translate cũng dịch chuyển widget, nhưng nó dùng giá trị pixel tuyệt đối. FractionalTranslation dùng giá trị phân số. Chọn cái nào tùy thuộc vào yêu cầu: dịch chuyển cố định một lượng pixel hay dịch chuyển tương đối theo kích thước.

Ứng Dụng Thực Tế

FractionalTranslation (hoặc các kỹ thuật tương tự dựa trên dịch chuyển tương đối) được ứng dụng rất nhiều trong các sản phẩm thực tế:

  1. Hiệu ứng Parallax Scrolling: Trong các trang web hoặc ứng dụng có hiệu ứng cuộn parallax, các lớp nội dung khác nhau sẽ di chuyển với tốc độ (tỷ lệ) khác nhau khi người dùng cuộn. FractionalTranslation có thể giúp mô phỏng điều này bằng cách dịch chuyển các lớp dựa trên vị trí cuộn và kích thước của chúng.
  2. Slide-in Menus/Drawers: Mặc dù Flutter có Drawer widget riêng, nhưng để tạo các menu tùy chỉnh trượt vào từ cạnh màn hình (như các ứng dụng tin tức, mạng xã hội) với hiệu ứng tinh tế, FractionalTranslation có thể được dùng để kiểm soát vị trí trượt dựa trên chiều rộng của menu.
  3. Onboarding Screens/Walkthroughs: Khi bạn thấy các phần tử UI dịch chuyển vào/ra màn hình một cách mượt mà trong các màn hình giới thiệu ứng dụng lần đầu, đó thường là sự kết hợp của animation và các kỹ thuật dịch chuyển tương đối.
  4. Responsive UI Elements: Trong một bố cục responsive, bạn có thể muốn một nút bấm hoặc một banner quảng cáo dịch chuyển một khoảng nhất định tính theo tỷ lệ của màn hình hoặc của chính nó, thay vì một giá trị pixel cố định có thể bị lệch trên các thiết bị khác nhau.

Nhớ nhé, lập trình không chỉ là viết code, mà là "điêu khắc" logic và giao diện. FractionalTranslation là một trong những "dụng cụ" tinh xảo giúp bạn làm điều đó. Chúc các bạn code vui vẻ!

Thuộc Series: Flutter

Bài giảng này được tự động xuất bản ngẫu nhiên từ thư viện kiến thức. Đừng quên đón xem các Từ khoá Hướng Dẫn tiếp theo nhé!

#tech #cyberpunk #laravel
Chỉnh sửa bài viết

Bình luận (0)

Vui lòng Đăng Nhập để Bình luận

Hỗ trợ Markdown cơ bản
Nguyễn Văn A
1 ngày trước

Tính năng này đỉnh quá ad ơi, chờ mãi mới thấy một blog Tiếng Việt có UI/UX xịn như vầy!