Author: hieppham1999

  • [FLUTTER] MỘT SỐ WIDGET HỮU ÍCH TRONG FLUTTER (PHẦN CUỐI)

    [FLUTTER] MỘT SỐ WIDGET HỮU ÍCH TRONG FLUTTER (PHẦN CUỐI)

    Ở phần cuối này mình sẽ giới thiệu cho anh em nốt những widget hay ho mà mình tìm hiểu được.
    Anh em có thể đọc lại 2 phần trước ở đây nhé:

    Phần 1
    Phần 2

    Bắt đầu luôn nào!!!

    1. RichText

    Có lúc nào anh em muốn viết một dòng chữ nhưng các phần trong đó lại có định dạng khác nhau? Ví dụ có thể kể ra là một phần của đoạn văn bản có thể click vào như ảnh dưới đây:

    Anh em có thể nghĩ đến việc sử dụng Row với 2 Text con bên trong, nhưng có vẻ hơi cồng kềnh nhỉ? Và đó chính là lúc RichText phát huy tác dụng của mình. Thay vì viết như này:

            Row(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                const Text("Not a user?"),
                TextButton(
                  onPressed: () {},
                  child: const Text(
                    "Sign up",
                    style: TextStyle(decoration: TextDecoration.underline),
                  ),
                )
              ],
            ),

    Chúng ta có thể viết như này để dễ hiểu hơn (về mặt logic, code thì cũng same nhau à :D):

            RichText(
              text: TextSpan(
                text: "Not a user? ",
                style: const TextStyle(color: Colors.black),
                children: <TextSpan>[
                  TextSpan(
                      text: "Signup",
                      style: const TextStyle(
                          color: Colors.blue, decoration: TextDecoration.underline),
                      recognizer: TapGestureRecognizer()..onTap = () {})
                ],
              ),
            ),

    RichText sẽ nhận vào một text là InlineSpan, ở đây ta sẽ sử dụng TextSpan. Ở trong TextSpan lại có các children là InlineSpan, cho nên ta có thể nối nhiều đoạn text lại với nhau, mỗi đoạn có thể có các style riêng biệt.

    2. SafeArea

    Các thiết bị di động ngày nay đã khác xưa rất nhiều, không chỉ đơn giản là một màn hình hình chữ nhật nữa. Chúng ta có màn hình “tai thỏ”, “nốt ruồi” rồi thậm chí là “giọt nước”. Các thiết kế phức tạp trên khiến người lập trình cũng phải để ý khi tạo ra các ứng dụng mới.

    Và để tránh nội dung của ứng dụng bị che khuất bởi các vị trí “nhạy cảm” kia, ở Flutter chúng ta có SafeArea.

    So sánh khi không sử dụng / sử dụng SafeArea

    Ở ảnh trên ta thấy, khi sử dụng SafeArea, AppBar sẽ không đè lên phần status bar của máy nữa (AppBar màu xanh dương), rất phù hợp khi thiết bị có những “nốt ruồi” hay “tai thỏ”.

    thông thường ta sẽ wrap cả Scaffold ở trong widget SafeArea để đảm bảo không bị mất nội dung.

    3. SelectableText

    Chắc mình sẽ không cần phải nói nhiều về widget này vì cái tên đã thể hiện quá rõ tác dụng của nó rồi. 😀 😀

    Khi anh em muốn cho phép người dùng chọn được đoạn văn bản thì có thể sử dụng widget này.

    SelectableText

    À mà anh em có thể kết hợp widget này với RichText ở bên trên bằng cách sử dụng SelectableText.rich() nhé, thật tiện lợi phải không ^^

    Tổng kết

    Vậy là qua 3 phần mình đã giới thiệu đến anh em một số widget mà mình cảm thấy hữu ích trong quá trình làm việc với Flutter. Do kiến thức còn hạn chế, khả năng viết bài cũng non nớt nên nếu có lỗi sai thì mong anh em hãy comment góp ý để mọi người có thể nâng cao kiến thức của mình nhé. Cảm ơn anh em đã theo dõi 😀 😀

  • [FLUTTER] Một số widget hữu ích trong Flutter (Phần 2)

    [FLUTTER] Một số widget hữu ích trong Flutter (Phần 2)

    Ở số trước mình đã giới thiệu một vài widget hữu ích, anh em có thể tìm đọc lại tại đây.

    Sang phần 2 này, mình sẽ tiếp tục giới thiệu đến anh em một vài widget ít phổ biến nhưng cũng khá thú vị. Bắt đầu ngay nhé 😀

    1. Chip widgets

    Đây là một loạt các widget có hình dạng mặc định là hình chữ nhật được bo tròn bốn góc (Stadium shape), có thể có avatar đằng trước để thể hiện hình ảnh. Vì có khá nhiều loại nên mình sẽ không đi sâu cụ thể mà chỉ giới thiệu qua cách sử dụng của chúng.

    Chip widget
    • Chip: Đây là loại cơ bản nhất, chỉ đơn giản thể hiện thông tin, kèm theo avatar đằng trước nếu cần.
    • ActionChip: Widget này có thêm thuộc tính onPressed nên có thể click được. Đây có thể là một lựa chọn thay thế cho ElevatedButton, TextButton hay OutlinedButton. Nhưng cần lưu ý là widget này sẽ không có trạng thái disabled (tức thuộc tính onPressed không nhận giá trị null), cho nên widget này được khuyên dùng cho các item không cố định trong UI
      => use case sử dụng: khi người dùng tìm kiếm thông tin, dùng widget này để đưa ra cho người dùng các kết quả gợi ý.
    • FilterChip: Cũng giống như ActionChip nhưng có thêm thuộc tính selected, widget này được sử dụng như CheckBox hay Switch, phù hợp khi đặt filter tìm kiếm thông tin. Ví dụ tại đây
    FilterChip
    • ChoiceChip: Gần tương tự FilterChip nhưng sử dụng khi muốn chọn 1 trong nhiều lựa chọn.
    • InputChip: Là sự kết hợp của những loại Chip bên trên, phù hợp khi thực hiện những tác vụ phức tạp.

    2. ResizeImage

    Thực ra đây cũng không hẳn là một widget nhưng nó khá là hay nên mình cũng xin giới thiệu cho những ai chưa biết 😀

    Đôi khi anh em muốn thêm ảnh vào trong ứng dụng của mình để cho thêm sinh động, nhưng nếu ở những vị trí nhỏ mà chúng ta thêm những ảnh có size lớn vào thì sẽ khá là lãng phí bộ nhớ. ResizeImage sẽ giúp chúng ta giảm thiểu điều này

    Cách sử dụng khá đơn giản, ResizeImage là một ImageProvider và cũng nhận vào một ImageProvider nên ta có thể sử dụng như sau:

    Image(
        image: ResizeImage(
          NetworkImage(imageUrl)),
         ),

    Như vậy là chúng ta có thể tiết kiệm được một chút bộ nhớ rồi 😀

    3. SwitchListTile

    Hầu hết các ứng dụng đều sẽ có phần cài đặt ứng dụng, và ở trong đó đôi khi sẽ có những lựa chọn theo kiểu bật / tắt, chúng ta sẽ nghĩ ngay đến widget Switch phải không nào?

    Nhưng với góc nhìn của một người dùng, việc phải click đúng vào ô switch bé tí để có thể sử dụng khiến ta đôi khi cảm thấy hơi bất tiện. Đừng lo vì chúng ta đã có SwitchListTile :)))

    Có thể hiểu nôm na đây chính là sự kết hợp của ListTile và Switch, chúng ta có thể click lên mọi điểm trong widget này để có thể kích hoạt nút switch, như vậy trải nghiệm người dùng (UX) sẽ được cải thiện thêm 😀

    Anh em có thể xem ví dụ tại đây.

    SwitchListTile

    Lưu ý: CheckBox hay Radio cũng có lựa chọn tương đương là CheckBoxListTileRadioListTile

    Mình xin được phép kết thúc phần 2 tại đây, mong rằng những thông tin mình chia sẻ sẽ giúp ích được anh em trong quá trình làm việc 😀

  • [FLUTTER] Một số widget hữu ích trong Flutter (Phần 1)

    [FLUTTER] Một số widget hữu ích trong Flutter (Phần 1)

    Giới thiệu

    Khi làm việc với Flutter có lẽ ai cũng biết câu nói:

    Trong Flutter, (gần như) mọi thứ đều là widget.

    Nhưng cũng chính vì có quá nhiều widget, lập trình viên đôi khi cảm thấy khó khăn trong việc lựa chọn, thậm chí là không biết đến sự tồn tại của một widget đã được viết sẵn phục vụ cho những yêu cầu thường gặp, thành ra phải tự code lại tốn nhiều thời gian mà chưa chắc đã thực sự tốt.

    Vì vậy, trong bài viết này, mình sẽ giới thiệu một số widget có thể sẽ giúp ích trong quá trình anh em làm việc với Flutter.

    À, nhưng trước hết, mình vẫn muốn recommend anh em kênh youtube chính thức của Flutter, có playlist Widgets of the Week (có lẽ nhiều người đều biết đến list này), mình thường xuyên vào đây xem khi có thời gian rảnh 😀

    1. FittedBox

    Chắc hẳn khi đọc tên thì anh em cũng đã tưởng tượng được ra tác dụng của widget này. Cũng giống như khi sử dụng các widget liên quan tới image, chúng ta có thuộc tính fit để thể hiện cách vẽ widget con (điều này chắc ai cũng biết rồi).

    Nhưng có một cách sử dụng khá hay mà mình mới được biết gần đây là làm cho các text trở nên responsive, khi độ lớn của widget cha thay đổi, text bên trong cũng thay đổi theo, ví dụ mình hoạ tại đây.

    FittedBox(
        fit: BoxFit.fitWidth,
        child: Text("Fitted Box"),
    )
    Text Responsive với FittedBox

    2. Wrap

    Widget này gần tương tự với Flex (lớp cha của Row và Column), nhưng khác ở điểm có thể tự sắp xếp các widget con sang cột / hàng mới tuỳ vào kích thước còn lại. Ví dụ

    Ví dụ về Wrap

    Một số thuộc tính trong Wrap như sau:

    • direction: xác định trục chính (vertical / horizontal)
    • spacing: khoảng cách giữa các widget trong trục chính (Main Axis).
    • runSpacing: khoảng cách giữa các widget trong trục phụ (Cross Axis).
    • alignment: vị trí theo trục chính của các widget con khi được wrap sang một hàng / cột mới (start, center, spaceBetween, …)
    • runAlignment: vị trí theo trục phụ của các widget con khi được wrap sang một hàng / cột mới.

    Ngoài ra còn một số thuộc tính nữa anh em có thể đọc thêm tại link doc của Flutter.

    3. Flexible, Expanded và Spacer

    Tại sao mình lại đưa ra một lúc 3 widget? Bởi vì 3 widget này khá tương đồng nhau về cách sử dụng, để mình giải thích cho nhé.

    3.1. Flexible

    Hãy tưởng tượng, anh em muốn làm một giao diện có các widget con bên trong có thể thay đổi kích thước theo widget cha (không nên nhầm lẫn với việc size màn hình thay đổi nhé), như vậy thì không thể sử dụng các widget có size cố định, chúng ta hãy nghĩ ngay đến việc sử dụng 3 widget trên xem sao ^^

    Ví dụ, chúng ta có 1 Row, bên trong gồm có 4 Container chứa Text, vậy làm thế nào để:

    • Container 1 chiếm 10%
    • Container 2 chiếm 20%
    • Container 3 chiếm 30%
    • Container 4 chiếm 40%

    Rất đơn giản, anh em chỉ cần wrap từng widget con vào trong widget Flexible và cho chúng hệ số flex như sau:

    SizedBox(
              height: 100,
              child: Row(
                children: [
                  Flexible(
                      flex: 1, child: Container(color: Colors.red.shade100)),
                  Flexible(
                      flex: 2,
                      child: Container(
                        color: Colors.red.shade200,
                      )),
                  Flexible(
                      flex: 3,
                      child: Container(
                        color: Colors.red.shade300,
                      )),
                  Flexible(
                      flex: 4,
                      child: Container(
                        color: Colors.red.shade400,
                      )),
                ],
              ),
            ),

    Kích thước của children sẽ được tính như sau:

    • Tính tổng hệ số flex của các widget có trong parent (Bao gồm Flexible, Spacer và Expanded): ví dụ ở trên sẽ là 1 + 2 + 3 + 4 = 10
    • Đặt kích thước của widget theo tỉ lệ hệ số flex / tổng, Ví dụ Container 1 sẽ chiếm 1/10 tức 10% width của row

    Vậy là chúng ta đã có một giao diện động mà không cần sử dụng các kích thước cố định 😀 :D.

    Nhưng nếu giữa các widget Flexible mà có widget kích thước cố định thì sao? Sẽ không có vấn đề gì cả, flutter sẽ trừ đi phần cố định chia theo hệ số flex như trên

    3.2. Expanded

    Expanded cũng giống như Flexible, chỉ khác là nó sẽ luôn muốn chiếm hết không gian còn lại nếu có thể, còn Flexible thì mặc định sẽ chỉ chiếm vừa đủ không gian bằng widget con của nó, và có một điều cần lưu ý:

    Flexible(
    
          fit: FlexFit.tight,
          ...
    ),

    sẽ tương đương với:

    Expanded(
          ...
    )

    Chỉ là đặt tên như vậy sẽ tường minh hơn, dễ trong việc sử dụng hơn 😀 😀

    3.3. Spacer

    Đúng như cái tên của nó, widget này đơn giản là chỉ tạo ra khoảng trắng, được sử dụng giống 2 widget trên, cũng có hệ số flex

    Lưu ý:

    • Các widget này phải được sử dụng trực tiếp dưới widget cha là các widget flex như Flex, Row, Column.
    • Mặc định hệ số flex sẽ luôn là 1

    (Còn tiếp…)

    Tham khảo

    widgets library – Dart API (flutter.dev)

    My 10 Most Favorite Flutter Widgets – YouTube