, October 26, 2021

0 kết quả được tìm thấy

Tìm hiểu Flutter Opacity Widget qua ví dụ cơ bản

  • Đăng bởi  Kieu Hoa
  •  Sep 04, 2021

  •   6 min reads
Tìm hiểu Flutter Opacity Widget qua ví dụ cơ bản

Nếu bạn chưa xem video "Widget of the Week" về Opacity widget, hãy xem ngay bây giờ. Video cung cấp một cái nhìn tổng quan hơn về những gì Widget này hoạt động.

Bài viết dưới đây sẽ cung cấp cho bạn đoạn code từ video để bạn có thể tự thực hành với nó. Đó là cách tốt nhất để học.

1. Những điều cơ bản

1.1 Ẩn Widget (full opacity)

Giả sử bạn có 1 list Widget được sắp xếp theo Column như sau:

class SomeWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final widgets = [
      MyWidget(Colors.green),
      MyWidget(Colors.blue),
      MyWidget(Colors.yellow),
    ];

    return Column(
      children: widgets,
    );
  }
}

Thật dễ dàng để loại bỏ màu xanh lam chỉ bằng cách rebuild mà không dùng nó (comment code chỗ đó lại như sau):

final widgets = [
  MyWidget(Colors.green),
  // MyWidget(Colors.blue),
  MyWidget(Colors.yellow),
];

Nhưng điều đó đã khiến Widget màu vàng di chuyển lên để chiếm vị trí của Widget màu xanh lam. Nếu bạn muốn bố cục giữ nguyên và chỉ làm cho Widget màu xanh lam biến mất, bạn có thể bọc nó trong một Opacity widget.

final widgets = [
  MyWidget(Colors.green),
  Opacity(
    opacity: 0.0,
    child: MyWidget(Colors.blue),
  ),
  MyWidget(Colors.yellow),
];

Opacity bằng 0.0 nghĩa là nó hoàn toàn trong suốt. Nếu bạn muốn làm cho nó hoàn toàn transparent (nghĩa là không còn trong suốt (transparency)), bạn sẽ đặt opacity thành 1.0. Bất kỳ thứ gì trong khoảng từ 0.0 đến 1.0 đều làm cho Widget trở nên trong suốt dần.

Chạy đoạn code trên ta được kết quả sau. Widget màu xanh lam vẫn ở đó, nhưng bạn không thể nhìn thấy nó.

Tiếp theo giả sử chúng ta có một hình ảnh như sau:

placekitten.com/200/200

Và chúng ta muốn phủ lên nó bằng một lớp gradient như hình dưới:

Chúng ta có thể sử dụng Stack và bọc gradient bằng Opacity widget:

Stack(
  children: [
    MyImageWidget(),
    Opacity(
        opacity: 0.25,
        child: MyGradientWidget()
    )
  ]
)

Đặt opacity thành 0.25 có nghĩa là gradient hầu như trong suốt. Đây là kết quả bạn nhận được sau khi chạy lại chương trình:

Sự khác biệt rất nhỏ nhưng nếu bạn để ý kỹ hơi sẽ thấy phần trên hơi đen hơn và phần dưới hơi trắng hơn một chút.

2. AnimatedOpacity

Nếu bạn muốn tạo Animation(hoạt ảnh) cho độ trong suốt(opacity) của một Widget bất kỳ, bạn có thể sử dụng Widget AnimatedOpacity.

Stack(
  children: [
    MyImageWidget(),
    AnimatedOpacity(
      duration: _myDuration,
      opacity: _myOpacity,
      child: MyGradientWidget(),
    )
  ],
)

Đặt duration một khoảng thời gian nào đó, chẳng hạn như 2 giây. Cho _myOpacity một giá trị ban đầu, chẳng hạn như 1.0, sau đó cập nhật _myOpacity với một giá trị mới và chạy lại ứng dụng:

setState(() {
  _myOpacity = 0.0;
});

Sau đó, hãy xem child của widget AnimatedOpacity thay đổi opacity của nó:

3. Tìm hiểu sâu hơn

Opacity widget rất hữu ích nếu bạn muốn làm cho toàn bộ Widget trong suốt. Tuy nhiên có lúc bạn chỉ cần tạo một màu trong suốt duy nhất mà thôi. Đây là một ví dụ về AppBar trong suốt:

Bản thân AppBar không trong suốt, nó chỉ có thuộc tính backgroundColor để bạn thay đổi màu của nó mà thôi. Do đó, bạn hoàn toàn có thể biến nó trong suốt bằng cách sau:

final myColor = Colors.transparent;

Ngoài ra, bạn còn có thể biến một màu bất kỳ trong suốt đi một phần bằng cách sử dụng phương thức withOpacity ().

final myColor = Colors.green.withOpacity(0.25);

Giống như trước đây, opacity là một số từ 0.0 đến 1.0, trong đó 0.0 là hoàn toàn trong suốt.

Một cách khác để làm một cái gì đó trở nên trong suốt là đặt giá trị alpha. Sau đây là hai cách khác nhau để diễn đạt cùng một điều:

final myColor = Colors.green.withOpacity(1.0);
final myColor = Colors.green.withAlpha(255);

Không giống như opacity, double nằm trong khoảng từ 0.0 đến 1.0, alpha là int nằm trong khoảng từ 0 đến 255 (hoặc 0 đến FF trong ký hiệu thập lục phân). Alpha thường thuận tiện khi thiết lập một màu theo số hex. Dạng là 0xAARRGGBB, trong đó 0x có nghĩa là ký hiệu hex, AA là alpha, RR là đỏ, GG là xanh lục và BB là xanh lam. Đây là một ví dụ:

final myColor = Color(0xC344AA50); 

Alpha trong ví dụ đó là CC trong hex hoặc 204 trong ký hiệu thập phân, giống như độ mờ 80% (204/255 = 0.8).

Nếu bạn nhìn vào source code, withOpacity()withAlpha() chỉ là các phương thức thuận tiện cho Color.fromARGB(alpha, red, green, blue), trong đó mỗi tham số đó lấy số nguyên từ 0 đến 255.

Full code

Nếu bạn có bất kỳ thắc mắc nào về việc triển khai các ví dụ Opacity hoặc AnimatedOpacity ở trên, hãy xem đoạn code bên dưới.

import 'dart:ui';
import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: Scaffold(
        body: Padding(
          padding: const EdgeInsets.only(top: 100),
          // You can SomeWidget() with StackedWidgetsDemo() or
          // AnimatedOpacityDemo() below.
          child: Center(child: SomeWidget()),
        ),
      ),
    );
  }
}

class SomeWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final widgets = [
      MyWidget(Colors.green),
      Opacity(
        opacity: 0.0,
        child: MyWidget(Colors.blue),
      ),
      MyWidget(Colors.yellow),
    ];

    return Column(
      children: widgets,
    );
  }
}

class MyWidget extends StatelessWidget {
  final Color color;

  MyWidget(this.color);

  @override
  Widget build(BuildContext context) {
    return Container(
      margin: EdgeInsets.all(10),
      width: 50,
      height: 50,
      color: color,
    );
  }
}


// To see this layout, in the MyApp widget replace SomeWidget() with this
// StackedWidgetsDemo widget.
class StackedWidgetsDemo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return SizedBox(
      width: 200,
      height: 200,
      child: Stack(children: [
        MyImageWidget(),
        Opacity(
          opacity: 0.25,
          child: MyGradientWidget(),
        )
      ]),
    );
  }
}

class MyImageWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Image(
      image: NetworkImage('https://placekitten.com/200/200'),
    );
  }
}

class MyGradientWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(
      decoration: BoxDecoration(
        gradient: LinearGradient(
          begin: Alignment.topCenter,
          end: Alignment.bottomCenter,
          colors: [Colors.black, Colors.white],
        ),
      ),
    );
  }
}


// To see this layout, in the MyApp widget replace SomeWidget() with this
// AnimatedOpacityDemo widget.
class AnimatedOpacityDemo extends StatefulWidget {
  @override
  _AnimatedOpacityDemoState createState() => _AnimatedOpacityDemoState();
}

class _AnimatedOpacityDemoState extends State<AnimatedOpacityDemo> {
  final _myDuration = Duration(seconds: 2);
  var _myOpacity = 1.0;

  @override
  Widget build(BuildContext context) {
    return Stack(
      children: [
        Center(
          child: SizedBox(
            width: 200,
            height: 200,
            child: Stack(
              children: [
                MyImageWidget(),
                AnimatedOpacity(
                  duration: _myDuration,
                  opacity: _myOpacity,
                  child: MyGradientWidget(),
                )
              ],
            ),
          ),
        ),
        updateStateButton()
      ],
    );
  }

  Align updateStateButton() {
    return Align(
      alignment: Alignment.bottomCenter,
      child: Padding(
        padding: EdgeInsets.only(bottom: 100),
        child: RaisedButton(
          child: Text('Animate Opacity'),
          onPressed: () {
            setState(() {
              _myOpacity = 0.0;
            });
          },
        ),
      ),
    );
  }
}

Kết

Cá nhân tôi sẽ không sử dụng Opacity widget thường xuyên, mặc dù thỉnh thoảng tôi muốn sử dụng nó để ẩn một widget.

Bài viết liên quan

[FREE EBOOK] TIPS & TRICKS GIÚP X3 TỐC ĐỘ CODE FLUTTER CỦA BẠN

Cuốn ebook "TIPS & TRICKS GIÚP X3 TỐC ĐỘ CODE FLUTTER CỦA BẠN" chỉ ra 32 trường hợp giúp bạn code nhanh hơn so với việc code thông thường...

[FREE EBOOK] TIPS & TRICKS GIÚP X3 TỐC ĐỘ CODE FLUTTER CỦA BẠN
Flutter 2.5 có gì mới?

Bản phát hành Flutter 2.5 lần này có rất nhiều bản cập nhật mới thú vị. Cùng bắt đầu tìm hiểu trong bài viết này nhé!...

Flutter 2.5 có gì mới?
Flutter Tutorial 2021 #34 - Hướng dẫn tạo hiệu ứng "fancy" khi chuyển màn hình

Thêm một hiệu ứng mới nữa mà các bạn sẽ được giới thiệu tới! Đó chính là hiệu ứng "fancy" khi chuyển màn hình. Hiệu ứng này sẽ giúp tăng trải nghiệm và gây ấn tượng cực mạnh với người dùng....

Flutter Tutorial 2021 #34 - Hướng dẫn tạo hiệu ứng "fancy" khi chuyển màn hình
Flutter Tutorial 2021 #33 - "Giao tiếp" giữa 2 màn hình bất kỳ trong Flutter

Làm sao để giao tiếp 2 hoặc 3, 4 màn hình trong app với nhau? Chúng ta cùng xem video bên dưới để hiểu được cách truyền dữ liệu từ màn hình A sang màn hình B và ngược lại nhé!...

Flutter Tutorial 2021 #33 - "Giao tiếp" giữa 2 màn hình bất kỳ trong Flutter
Flutter Tutorial 2021 #32 - Giới thiệu Navigation trong Flutter

Trong video lần này bạn sẽ được giới thiệu một khái niệm mới. Đó chính là navigation. Vậy Navigation là gì? Cùng tìm hiểu video dưới đây nhé!...

Flutter Tutorial 2021 #32 - Giới thiệu Navigation trong Flutter
You've successfully subscribed to 200Lab Blog
Great! Next, complete checkout for full access to 200Lab Blog
Xin chào mừng bạn đã quay trở lại
OK! Tài khoản của bạn đã kích hoạt thành công.
Success! Your billing info is updated.
Billing info update failed.
Your link has expired.