Flutter-實(shí)現(xiàn)雙向PK進(jìn)度條

如何實(shí)現(xiàn)一個(gè)雙向PK進(jìn)度條

在Flutter應(yīng)用中,進(jìn)度條是一個(gè)非常常見(jiàn)的組件。而雙向PK進(jìn)度條則能夠展示兩個(gè)對(duì)立的數(shù)值,如對(duì)戰(zhàn)中的雙方得分對(duì)比等。本文將介紹如何實(shí)現(xiàn)一個(gè)具有雙向PK效果的進(jìn)度條,并支持豎直和斜角兩種過(guò)渡效果。

1. 需求

我們需要一個(gè)自定義的雙向PK進(jìn)度條,要求如下:

  • 能夠顯示兩個(gè)對(duì)立的數(shù)值。
  • 進(jìn)度條兩端有圓角。
  • 中間過(guò)渡部分可以是豎直或者45度斜角。
  • 支持自定義顏色和高度。

2. 效果

通過(guò)我們的實(shí)現(xiàn),可以得到如下效果:

image.png

3. 實(shí)現(xiàn)思路

  1. 定義組件:創(chuàng)建一個(gè)自定義的PKProgressBar組件,包含左右兩側(cè)的數(shù)值、顏色、高度和過(guò)渡類型。
  2. 繪制左側(cè)和右側(cè)的圓角矩形:使用CustomPainter來(lái)繪制左右兩部分的圓角矩形。
  3. 處理中間過(guò)渡部分:根據(jù)過(guò)渡類型繪制豎直或者45度斜角的過(guò)渡效果。

4. 實(shí)現(xiàn)代碼

下面是實(shí)現(xiàn)雙向PK進(jìn)度條的完整代碼:

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: const Text('雙向PK進(jìn)度條')),
        body: const Center(
            child: Padding(
          padding: EdgeInsets.symmetric(horizontal: 16),
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              PKProgressBar(
                leftValue: 75,
                rightValue: 150,
                leftColor: Colors.blue,
                rightColor: Colors.red,
                height: 20,
                transitionType: TransitionType.diagonal, // 設(shè)置過(guò)渡類型為斜角
              ),
              SizedBox(height: 50),
              PKProgressBar(
                leftValue: 90,
                rightValue: 55,
                leftColor: Colors.brown,
                rightColor: Colors.green,
                height: 20,
                transitionType: TransitionType.vertical, // 設(shè)置過(guò)渡類型為豎直
              ),
            ],
          ),
        )),
      ),
    );
  }
}

// 定義過(guò)渡類型枚舉
enum TransitionType { vertical, diagonal }

class PKProgressBar extends StatelessWidget {
  final double leftValue;
  final double rightValue;
  final Color leftColor;
  final Color rightColor;
  final double height;
  final TransitionType transitionType;

  const PKProgressBar({
    super.key,
    required this.leftValue,
    required this.rightValue,
    required this.leftColor,
    required this.rightColor,
    this.height = 20.0,
    this.transitionType = TransitionType.diagonal, // 默認(rèn)過(guò)渡類型為斜角
  });

  @override
  Widget build(BuildContext context) {
    return CustomPaint(
      size: Size(double.infinity, height),
      painter: PKProgressPainter(
        leftValue: leftValue,
        rightValue: rightValue,
        leftColor: leftColor,
        rightColor: rightColor,
        transitionType: transitionType,
      ),
    );
  }
}

class PKProgressPainter extends CustomPainter {
  final double leftValue;
  final double rightValue;
  final Color leftColor;
  final Color rightColor;
  final TransitionType transitionType;

  PKProgressPainter({
    required this.leftValue,
    required this.rightValue,
    required this.leftColor,
    required this.rightColor,
    required this.transitionType,
  });

  @override
  void paint(Canvas canvas, Size size) {
    final paint = Paint()..style = PaintingStyle.fill;

    final double totalValue = leftValue + rightValue;
    final double leftWidth = (leftValue / totalValue) * size.width;
    final double rightWidth = (rightValue / totalValue) * size.width;
    final double radius = size.height / 2;

    // 左側(cè)帶圓角的矩形
    final leftRRect = RRect.fromLTRBAndCorners(
      0,
      0,
      leftWidth,
      size.height,
      topLeft: Radius.circular(radius),
      bottomLeft: Radius.circular(radius),
    );

    // 右側(cè)帶圓角的矩形
    final rightRRect = RRect.fromLTRBAndCorners(
      leftWidth,
      0,
      size.width,
      size.height,
      topRight: Radius.circular(radius),
      bottomRight: Radius.circular(radius),
    );

    // 繪制左側(cè)部分
    paint.color = leftColor;
    canvas.drawRRect(leftRRect, paint);

    // 繪制右側(cè)部分
    paint.color = rightColor;
    canvas.drawRRect(rightRRect, paint);

    // 根據(jù)過(guò)渡類型繪制中間部分
    if (transitionType == TransitionType.vertical) {
      // 豎直過(guò)渡
      final middleRect = Rect.fromLTWH(
        leftWidth - radius,
        0,
        2 * radius,
        size.height,
      );
      paint.color = rightColor;
      canvas.drawRect(middleRect, paint);
    } else if (transitionType == TransitionType.diagonal) {
      // 斜角過(guò)渡,形成45度斜線
      final leftPath = Path()
        ..moveTo(leftWidth - size.height / 2, 0)
        ..lineTo(leftWidth + size.height / 2, size.height)
        ..lineTo(leftWidth - size.height / 2, size.height)
        ..close();
      paint.color = leftColor;
      canvas.drawPath(leftPath, paint);

      // 斜角過(guò)渡,形成45度斜線
      final rightPath = Path()
        ..moveTo(leftWidth - size.height / 2, 0)
        ..lineTo(leftWidth, 0)
        ..lineTo(leftWidth, size.height)
        ..close();
      paint.color = rightColor;
      canvas.drawPath(rightPath, paint);
    }
  }

  @override
  bool shouldRepaint(covariant CustomPainter oldDelegate) {
    return false;
  }
}

在這個(gè)實(shí)現(xiàn)中,我們通過(guò)CustomPainter來(lái)自定義繪制PK進(jìn)度條,并根據(jù)過(guò)渡類型繪制豎直或斜角的過(guò)渡效果。通過(guò)這些代碼,你可以輕松實(shí)現(xiàn)一個(gè)具有雙向PK效果的進(jìn)度條,并根據(jù)需求調(diào)整樣式和效果。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容