Flutter 入门笔记(Part 4) 自定义控件,主题

10 . 自定义控件

10.1 组合控件

  • 将多个控件组合在一起

10.2 自定义控件

  • CustomPaint是用来承接自绘控件的容器,并不负责真正的绘制.
  • 画布是canvas,画笔是Paint.
  • 画成什么样子由CustomPainter来控制,将CustomPainter设置给容器CustomPaint的painter属性,我们就完成了一个自绘组件的封装
  • Paint,其实和Android中的差不多,可以配置它的各种属性,比如颜色、样式、粗细等;而画布 Canvas,则提供了各种常见的绘制方法,比如画线 drawLine、画矩形 drawRect、画点 DrawPoint、画路径 drawPath、画圆 drawCircle、画圆弧 drawArc 等。
class WheelPainter extends CustomPainter {
  Paint getColoredPaint(Color color) {
    Paint paint = Paint();
    paint.color = color;
    return paint;
  }

  @override
  void paint(Canvas canvas, Size size) {
    //半径
    double wheelSize = min(size.width, size.height) / 2;
    //分成6份
    double nbElem = 6;
    //角度
    double radius = (2 * pi) / nbElem;
    //包裹饼图的矩形框  center:相对于原点的偏移量
    Rect boundingRect = Rect.fromCircle(
        center: Offset(wheelSize, wheelSize), radius: wheelSize);

    //每次画1/6圆
    canvas.drawArc(
        boundingRect, 0, radius, true, getColoredPaint(Colors.orange));
    canvas.drawArc(
        boundingRect, radius, radius, true, getColoredPaint(Colors.green));
    canvas.drawArc(
        boundingRect, radius * 2, radius, true, getColoredPaint(Colors.red));
    canvas.drawArc(
        boundingRect, radius * 3, radius, true, getColoredPaint(Colors.blue));
    canvas.drawArc(
        boundingRect, radius * 4, radius, true, getColoredPaint(Colors.pink));
    canvas.drawArc(boundingRect, radius * 5, radius, true,
        getColoredPaint(Colors.deepOrange));
  }

  @override
  bool shouldRepaint(CustomPainter oldDelegate) {
    //判断是否需要重绘,简单做下比较
    return oldDelegate != this;
  }
}

class Cake extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    //CustomPaint是用来承载自定义View的容器,需要自定义一个画笔,得继承自CustomPainter
    return CustomPaint(
      size: Size(200, 200),
      painter: WheelPainter(),
    );
  }
}

11 . 主题定制

  • 视觉效果是易变的,我们将这些变化的部分抽离出来,把提供不同视觉效果的资源和配置按照主题进行归类,整合到一个统一的中间层去管理,这样我们就能实现主题的管理和切换.
  • Flutter中由ThemeData来统一管理主题的配置信息
  • ThemeData中涵盖了Material Design规范的可自定义部分样式,比如应用明暗模式 brightness、应用主色调 primaryColor、应用次级色调 accentColor、文本字体 fontFamily、输入框光标颜色 cursorColor 等。
  • 全局统一的视觉风格:

MaterialApp(
  title: 'Flutter Demo',//标题
  theme: ThemeData(//设置主题
      brightness: Brightness.dark,//设置明暗模式为暗色
      accentColor: Colors.black,//(按钮)Widget前景色为黑色
      primaryColor: Colors.cyan,//主色调为青色
      iconTheme:IconThemeData(color: Colors.yellow),//设置icon主题色为黄色
      textTheme: TextTheme(body1: TextStyle(color: Colors.red))//设置文本颜色为红色
  ),
  home: MyHomePage(title: 'Flutter Demo Home Page'),
);
  • 局部主题: 需要使用Theme来对App的主题进行局部覆盖,Theme是一个单子Widget容器,将控件放里面就可以控制主题了.
  • 局部新建主题: 如果不想继承任何App全局的颜色或字体样式,可以直接新建一个ThemeData实例,依次设置对应的样式.
// 新建主题
Theme(
    data: ThemeData(iconTheme: IconThemeData(color: Colors.red)),
    child: Icon(Icons.favorite)
);
  • 继承主题: 如果不想在局部重写所有的样式,则可以继承App的主题,使用copyWith方法,只更新部分样式
// 继承主题
Theme(
    data: Theme.of(context).copyWith(iconTheme: IconThemeData(color: Colors.green)),
    child: Icon(Icons.feedback)
);
  • 主题另一个用途是样式复用.
Container(
    color: Theme.of(context).primaryColor,//容器背景色复用应用主题色
    child: Text(
      'Text with a background color',
      style: Theme.of(context).textTheme.title,//Text组件文本样式复用应用文本样式
    ));

手机扫码阅读