Lớp con CustomPainter ghi đè hai phương thức: paint()và shouldRepaint().

Hãy để tôi hướng dẫn bạn qua mã để hiểu rõ hơn về những gì đang xảy ra ở đây. Như bạn có thể thấy giao diện người dùng mà chúng ta sẽ đạt được theo đó, tôi đã tạo một lớp <strong>CustomPaintExample</strong> chứa mã cho giao diện người dùng. Có hai yếu tố chính, hình dạng và hoạt ảnh của nút. Nút khi được nhấn sẽ tăng giá trị percentValue lên 10 và theo đó có thể thấy tiến trình trên đường viền nút đang tăng lên. Tiện ích này cũng được chia thành hai phần tử CustomPainterExample.buildShape() và CustomPainterExample.buildButtonAnimation() tôi đã tạo trong các lớp khác nhau CustomPainterExampleWidgets.

Trong Class CustomPainterExampleWidgets, Phần tử CustomPainterExample.buildShape()trả về một ClipPath bao gồm clipper CustomShapeClass và phần tử còn lại CustomPainterExample.buildButtonAnimation() bao gồm một Container với CustomPaint là phần tử con của nó hiển thị ở giữa màn hình. . Phần trăm tăng được hiển thị bằng phương thức onPressed tại nút Raised.

import 'package:flutter/material.dart';
class CustomShapeClass extends CustomClipper<Path> {
  @override
  getClip(Size size) {
    // TODO: implement getClip
    var path = new Path();
    path.lineTo(0, size.height / 4.25);
    var firstControlPoint = new Offset(size.width / 4, size.height / 3);
    var firstEndPoint = new Offset(size.width / 2, size.height / 3 - 60);
    var secondControlPoint =
    new Offset(size.width - (size.width / 4), size.height / 4 - 65);
    var secondEndPoint = new Offset(size.width, size.height / 3 - 40);
    path.quadraticBezierTo(firstControlPoint.dx, firstControlPoint.dy,
        firstEndPoint.dx, firstEndPoint.dy);
    path.quadraticBezierTo(secondControlPoint.dx, secondControlPoint.dy,
        secondEndPoint.dx, secondEndPoint.dy);
    path.lineTo(size.width, size.height / 3);
    path.lineTo(size.width, 0);
    path.close();
    return path;
  }
  @override
  bool shouldReclip(CustomClipper oldClipper)
  {
    return true;
  }
}

CustomShapeClass kế thừa CustomClipper được minh họa ở trên Trong điều khiển này, các điểm điều khiển và điểm kết thúc được xác định trong đó đường cong bezier bậc hai được vẽ. Bây giờ hãy khai báo lõi của ứng dụng lớp ButtonPainter

import 'dart:math';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
class ButtonPainter extends CustomPainter
{
  Color buttonBorderColor;
  Color progressColor;
  double percentage;
  double width;
  ButtonPainter({this.buttonBorderColor,this.progressColor,this.percentage,this.width});
  @override
  void paint(Canvas canvas, Size size) {
    Paint line = Paint()
      ..color = buttonBorderColor
      ..strokeCap = StrokeCap.round
      ..style = PaintingStyle.stroke
      ..strokeWidth = width;
    Paint complete =  Paint()
      ..color = progressColor
      ..strokeCap = StrokeCap.round
      ..style = PaintingStyle.stroke
      ..strokeWidth = width;
    Offset center  = Offset(size.width/2, size.height/2);
    double radius  = min(size.width/2,size.height/2);
    canvas.drawCircle(
        center,
        radius,
        line
    );
    double arcAngle = 2*pi* (percentage/100);
    canvas.drawArc(
        Rect.fromCircle(center: center,radius: radius),
        -pi/2,
        arcAngle,
        false,
        complete
    );
  }
  @override
  bool shouldRepaint(CustomPainter oldDelegate) {
    return true;
  }
}

Ở đây chúng ta nhận được các thuộc tính khác nhau lineColor, có nghĩa là màu cho đường đi, trên đó tiến trình sẽ được vẽ, completeColor cho tiến độ đã hoàn thành, completePercent cho mức tiến độ đã hoàn thành. Từ tiện ích con của nó, chúng tôi gửi thuộc tính này xuống, ở đây chúng tôi chỉ đơn giản là vẽ.

<strong>ButtonPainter</strong> kế thừa lớp <strong>CustomPainter</strong> và chúng ta cần ghi đè <strong>paint</strong> phương thức của nó để vẽ đồ họa. Để vẽ, ngay từ đầu, chúng ta cần thông báo một thứ gọi là Paint , nó định hình tất cả các thuộc tính dự kiến ​​sẽ vẽ thứ gì đó trên màn hình. Vì vậy, chúng ta có hai đối tượng Paint ; đầu tiên là một dòng nói lên đường theo dõi mà tiến trình sẽ được vẽ trên đó. Chúng tôi cung cấp cho nó một màu sắc, được cung cấp dưới dạng thuộc tính, strokeCap ​​là hình tròn và chúng tôi yêu cầu style là PaintingStyle cho một trong những cung cấp. Vì vậy, ngoài ra, chúng tôi thông báo đối tượng Paint hoàn chỉnh cho tiến trình đã hoàn thành.

Tóm lại, chúng ta phải vẽ một vòng tròn đầy đủ và sau đó vẽ một vòng cung trên đó, thế là đã hoàn thành.

Offset center  = Offset(size.width/2, size.height/2);
double radius  = min(size.width/2,size.height/2);

Trong hai đường thẳng này, chúng tôi tính toán các hướng cho tâm của hình tròn và bán kính cơ bản của nó, tâm là chiều rộng và chiều cao của thùng chứa chia cho 2. Chúng tôi cần chính xác tâm của các hình tròn ở giữa. size là những gì chúng ta nhận được dưới dạng một tham số trong hàm paint, là kích thước của thùng chứa. radius Đây là mức tối thiểu của một nửa chiều rộng và chiều cao và bây giờ chúng tôi đang lấy mức tối thiểu của cả hai vì vùng chứa có thể không phải luôn luôn là hình vuông

canvas.drawCircle(center,radius,line);

Bây giờ chúng ta chỉ vẽ với hàm drawCircle được gọi trên đối tượng canvas được cung cấp, chúng ta chuyền vào tâm, bán kính và đối tượng Paint .

canvas.drawArc(Rect.fromCircle(center: center,radius: radius),
    -pi/2,arcAngle,false,complete);

Bây giờ, chúng ta tìm góc cho cung tròn đã hoàn thành, mà nó đã xuất hiện. Tôi không đi sâu vào tính toán hình học. Để gọi drawArc, chúng ta cần chỉ định một Rect , là hộp giới hạn của cung tròn, chúng ta nhận được Rect bao gồm các tham số của đường tròn mà chúng ta đã vẽ trước đó. Tại thời điểm đó, chúng ta cho một góc bắt đầu là -pi / 2 radian, hãy nhớ nó không phải là 0. Đỉnh là -pi/2, 0 là đích ngoài cùng bên phải của đường tròn. Chúng tôi cung cấp arcAngle tại điểm đó, đó là cung sẽ kéo dài bao nhiêu. Sau đó, chúng tôi chuyền vào false để nói rằng chúng tôi không muốn phần cuối của vòng cung được kết nối trở lại trung tâm và cuối cùng chúng chuyền vào complete. Đó là tất cả những gì chúng tôi mong đợi để vẽ bằng cách sử dụng CustomPaint.

Bây giờ, hãy thêm các hình ảnh động.

percentageAnimationController = new AnimationController(vsync: this,
    duration: new Duration(milliseconds: 1000))
  ..addListener((){setState(() {
      percentage=lerpDouble(percentage,newPercentage,
      percentageAnimationController.value);});});

Chúng tôi thêm hoạt ảnh trên màn hình HomePage trong initState(). Sau đó, chúng tôi đã thêm một trình nghe trên AnimationController đó được gọi ở mỗi bước của hoạt ảnh và chúng tôi thay đổi tỷ lệ phần trăm. Để thay đổi tỷ lệ phần trăm, chúng tôi nhận được một giá trị được chèn với sự trợ giúp của hàm lerpDouble , giá trị nằm trong percentage và newPercentage lớn hơn giá trị ban đầu 10, chúng ta nhận dựa trên giá trị AnimationController’s.

Chúng ta thêm dòng này vào nút onPressed để bắt đầu hoạt ảnh.

percentageAnimationController.forward(from: 0.0);

Bạn sẽ thấy mã đầy đủ trên GitHub và đây là một ví dụ về quy trình vòng tròn nhỏ để tích hợp với custom paint và video dưới đây cho biết cách CustomPaint sẽ hoạt động.

Hy vọng blog này sẽ cung cấp cho bạn đầy đủ thông tin trong việc thử Custom Paint trong các dự án hiện tại của bạn Cảm ơn vì đã đọc bài viết này

Leave a Comment

* By using this form you agree with the storage and handling of your data by this website.