CupertinoThumbPainter

专门用于绘制iOS风格滑块(slider)的圆形拇指(thumb)部分

CupertinoThumbPainter是Flutter Cupertino风格设计库中一个低级的绘制组件,它专门用于绘制iOS风格滑块(slider)的圆形拇指(thumb)部分。它不直接是一个可交互的widget,而是一个BoxDecoration的自定义绘制器,主要职责 是根据指定状态(如是否按下)来绘制一个具有阴影和特定背景色的圆形。

主要用途

  • CupertinoSlider这类iOS风格的滑块提供统一的拇指绘制逻辑。
  • 允许开发者自定义或扩展滑块拇指的视觉效果,同时保持iOS原生设计感。

使用场景

  • 当您需要构建一个符合iOS设计规范的滑动选择器时,CupertinoThumbPainter在底层帮助实现了滑块拇指的视觉效果。
  • 在自定义滑动条时,如果您想复用iOS风格的拇指绘制逻辑,可以将其集成到自定义的CustomPainterBoxDecoration中。

示例

基本Thumb绘制

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

class BasicThumbPainterExample extends StatelessWidget {
  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Basic CupertinoThumbPainter'),
      ),
      body: Center(
        child: Container(
          width: 100, // 增加容器宽度以容纳阴影
          height: 100, // 增加容器高度以容纳阴影
          color: Colors.grey[200], // 提供背景色以衬托拇指
          child: CustomPaint(
            painter: _ThumbPainter(
              color: CupertinoColors.white,
              pressed: false, // 未按下状态
            ),
            child: Center(
              child: Text('Thumb', style: TextStyle(color: Colors.black)),
            ),
          ),
        ),
      ),
    );
  }
}

class _ThumbPainter extends CustomPainter {
  final Color color;
  final bool pressed;

  _ThumbPainter({required this.color, required this.pressed});

  
  void paint(Canvas canvas, Size size) {
    final double radius = size.width / 2; // 假设绘制一个圆形,半径是宽度的一半
    final Offset center = Offset(size.width / 2, size.height / 2);

    // 调用 CupertinoThumbPainter 的 paint 方法来绘制拇指
    CupertinoThumbPainter.paint(
      canvas,
      Rect.fromCircle(center: center, radius: radius),
      color,
      pressed,
    );
  }

  
  bool shouldRepaint(_ThumbPainter oldDelegate) {
    return oldDelegate.color != color || oldDelegate.pressed != pressed;
  }
}

// void main() => runApp(MaterialApp(home: BasicThumbPainterExample()));

模拟按下状态

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

class PressedThumbPainterExample extends StatefulWidget {
  
  _PressedThumbPainterExampleState createState() => _PressedThumbPainterExampleState();
}

class _PressedThumbPainterExampleState extends State<PressedThumbPainterExample> {
  bool _isPressed = false;

  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Pressed CupertinoThumbPainter'),
      ),
      body: Center(
        child: GestureDetector(
          onTapDown: (_) {
            setState(() {
              _isPressed = true;
            });
          },
          onTapUp: (_) {
            setState(() {
              _isPressed = false;
            });
          },
          onTapCancel: () {
            setState(() {
              _isPressed = false;
            });
          },
          child: Container(
            width: 100,
            height: 100,
            color: Colors.grey[200],
            child: CustomPaint(
              painter: _ThumbPainter(
                color: CupertinoColors.white,
                pressed: _isPressed, // 根据状态变化
              ),
              child: Center(
                child: Text(
                  _isPressed ? 'Pressed' : 'Unpressed',
                  style: TextStyle(color: Colors.black),
                ),
              ),
            ),
          ),
        ),
      ),
    );
  }
}

// _ThumbPainter 和前面示例一致
class _ThumbPainter extends CustomPainter {
  final Color color;
  final bool pressed;

  _ThumbPainter({required this.color, required this.pressed});

  
  void paint(Canvas canvas, Size size) {
    final double radius = size.width / 2;
    final Offset center = Offset(size.width / 2, size.height / 2);

    CupertinoThumbPainter.paint(
      canvas,
      Rect.fromCircle(center: center, radius: radius),
      color,
      pressed,
    );
  }

  
  bool shouldRepaint(_ThumbPainter oldDelegate) {
    return oldDelegate.color != color || oldDelegate.pressed != pressed;
  }
}

// void main() => runApp(MaterialApp(home: PressedThumbPainterExample()));

注意点

  • 这是一个低级绘制工具,不是Widget: CupertinoThumbPainter本身不具备布局能力,它只是提供一个静态的paint方法来在指定的Canvas上绘制图形。您需要将其与CustomPaint或其他绘制上下文结合使用。
  • 尺寸和位置: paint方法需要一个Rect来指定绘制区域和大小。这个Rect定义了拇指的边界。在上述示例中,我们假设了圆形,并计算了合适的Rect
  • 阴影效果: CupertinoThumbPainter的核心功能之一就是绘制不同状态下的阴影效果,以模拟iOS原生滑块的视觉反馈。
  • 主题适配: 绘制的颜色color可以根据CupertinoTheme或其他主题颜色进行动态调整,以确保与应用整体风格一致。
  • 性能: 作为一个纯绘制函数,其性能通常不是瓶颈。但如果在CustomPainter中频繁重绘,且shouldRepaint逻辑不当,仍可能导致不必要的渲染。

构造函数

CupertinoThumbPainter没有公共构造函数。它是一个工具类,其唯一的公共接口是静态方法paint

属性

属性名属性类型说明
canvasCanvas绘制的目标画布。
rectRect定义了拇指绘制的边界和大小。拇指会在此 Rect 内部绘制,包括其阴影。
colorColor拇指的背景颜色。通常默认为 CupertinoColors.white
pressedbool表示拇指是否处于被按下的状态。true 表示按下,false 表示未按下。不同状态下,会绘制出略微不同的阴影效果,以提供触觉反馈。

关键属性解释

  • rect: 这个参数至关重要,它直接决定了CupertinoThumbPainter绘制出的拇指的大小和在画布上的位置。开发者需要根据其父组件或使用场景来精确计算这个Rect的值。
  • pressed: 这是控制拇指视觉反馈的核心参数。当设为true时,CupertinoThumbPainter会绘制一个“更深”或“更突出”的阴影,模拟真实世界中物体被按压时的效果;当设为false时,则绘制一个“平坦”的阴影。这种细微的视觉差异是iOS设计语言的重要组成部分。