Flutter 自定义Decoration

Flutter 中 可以给Container设置decoration来设置背景,边框等等效果,非常方便。

      Container(
        decoration: TestDecoration(),
      );

但是Flutter自带的decoration比较少,只能支持常规样式,当我们需要设置特殊背景时,就满足不了我们的需要了。

这时候,就有必要自定义一个我们定制化的decoration。

搜了一下flutter sdk代码,发现flutter里有一个定制化的FlutterLogoDecoration类,用这个FlutterLogoDecoration可以生成一个flutter logo样式的decoration。
我们可以参考它的代码来写一个我们自定义的decoration。

经过我的分析,自定义decoration的步骤还是很简单的。
一个简单的代码框架是这样的。


class MyDecoration extends Decoration {
  @override
  BoxPainter createBoxPainter([VoidCallback onChanged]) {
    return _MyBoxPainter(this);
  }
}

class _MyBoxPainter extends BoxPainter {
  final TestDecoration myDecoration;
  final Paint painter;

  _MyBoxPainter(this.myDecoration)
      : painter = Paint()

  @override
  void paint(Canvas canvas, Offset offset, ImageConfiguration configuration) {
    //我们需要实现的代码
    //具体绘制decoration的内容
  }
}

这段代码中,我们主要需要实现的,就是_MyBoxPainterpaint方法。

上面的的代码,是先写了一个MyDecoration类继承Decoration,然后重写了其中的createBoxPainter方法,创建一个_MyBoxPainter类。
_MyBoxPainter类是继承BoxPainter的,里面的paint方法需要我们实现,在该方法中具体编写decoration实际绘制的内容。
绘制时,主要用到了canvas.draw...相关的api。

下面是一份带有红色边框,和内部有“测试”字样的decoration的demo代码。


class MyDecoration extends Decoration {
  @override
  BoxPainter createBoxPainter([VoidCallback onChanged]) {
    return _MyBoxPainter(this);
  }
}

class _MyBoxPainter extends BoxPainter {
  final MyDecoration testDecoration;
  final Paint painter;

  _MyBoxPainter(this.testDecoration)
      : painter = Paint()
          ..color = Colors.red
          ..strokeWidth = 2;

  @override
  void paint(Canvas canvas, Offset offset, ImageConfiguration configuration) {
    var size = configuration.size;
    Offset leftTop = offset;
    Offset rightTop = leftTop.translate(size.width, 0);
    Offset leftBottom = leftTop.translate(0, size.height);
    Offset rightBottom = leftTop.translate(size.width, size.height);

    canvas.drawLine(leftTop, rightTop, painter);
    canvas.drawLine(leftTop, leftBottom, painter);
    canvas.drawLine(rightTop, rightBottom, painter);
    canvas.drawLine(leftBottom, rightBottom, painter);

    var textPainter = TextPainter(
      text: TextSpan(
        text: "测试",
        style: TextStyle(
          backgroundColor: Colors.green,
          color: Colors.red,
          fontSize: 12,
        ),
      ),
      textDirection: TextDirection.ltr,
    );
    textPainter.layout();
    textPainter.paint(canvas, (leftTop + rightBottom) / 2);
  }
}

在这里插入图片描述
这里设置了painter的颜色是红色,宽度是2,用来绘制边框。
paint方法的Offset offset参数表示控件左上角的位置。
configuration.size 可以得到控件的宽高。
所以,

    Offset leftTop = offset;
    Offset rightTop = leftTop.translate(size.width, 0);
    Offset leftBottom = leftTop.translate(0, size.height);
    Offset rightBottom = leftTop.translate(size.width, size.height);

通过上面这四行代码,就可以得到控件四个角的位置。

	canvas.drawLine(leftTop, rightTop, painter);
    canvas.drawLine(leftTop, leftBottom, painter);
    canvas.drawLine(rightTop, rightBottom, painter);
    canvas.drawLine(leftBottom, rightBottom, painter);

然后通过drawLine可以绘制四个边框。
这里是演示demo,实际要绘制边框可以使用canvas.drawRect(rect, paint)方法更为方便。

    var textPainter = TextPainter(
      text: TextSpan(
        text: "测试",
        style: TextStyle(
          backgroundColor: Colors.green,
          color: Colors.red,
          fontSize: 12,
        ),
      ),
      textDirection: TextDirection.ltr,
    );

这里定义了一个“测试”文字绘制的painter,文字颜色是红色,底色是绿色,字号是12,文字方向是从左到右。
需要注意的是,需要先调用textPainter.layout(); 才能真正绘制,否则会报错。
调用textPainter.paint(canvas, (leftTop + rightBottom) / 2); 即可完成绘制。(leftTop + rightBottom) / 2)表示绘制在中心位置。


总体来说代码很简单,只要按照这个框架实现对应的方法即可。
主要是用了canvas.draw...相关的api 和 TextPainter.paint方法。
在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Flutter中,可以使用自定义Widget来实现自定义键盘。以下是实现自定义键盘的一般步骤: 1. 创建一个StatefulWidget,该Widget将显示自定义键盘。 2. 实现一个键盘布局。可以使用Flutter提供的各种Widget(如Container、Row、Column等)来创建键盘布局,并使用GestureDetector Widget来处理键盘按钮的点击事件。 3. 在需要使用自定义键盘的地方,使用Flutter的FocusNode来控制输入框的焦点,并将自定义键盘与输入框关联起来。 下面是一个简单的实现自定义键盘的示例代码: ```dart import 'package:flutter/material.dart'; class CustomKeyboard extends StatefulWidget { @override _CustomKeyboardState createState() => _CustomKeyboardState(); } class _CustomKeyboardState extends State<CustomKeyboard> { TextEditingController _textEditingController = TextEditingController(); @override Widget build(BuildContext context) { return Container( child: Column( children: [ TextField( controller: _textEditingController, focusNode: FocusNode(), decoration: InputDecoration( hintText: 'Input something', ), ), Row( children: [ CustomButton('1'), CustomButton('2'), CustomButton('3'), ], ), Row( children: [ CustomButton('4'), CustomButton('5'), CustomButton('6'), ], ), Row( children: [ CustomButton('7'), CustomButton('8'), CustomButton('9'), ], ), Row( children: [ CustomButton('0'), CustomButton('backspace'), ], ), ], ), ); } } class CustomButton extends StatelessWidget { final String text; CustomButton(this.text); @override Widget build(BuildContext context) { return GestureDetector( onTap: () { if (text == 'backspace') { String currentText = CustomKeyboard.of(context) .controller .text; if (currentText.isNotEmpty) { CustomKeyboard.of(context) .controller .text = currentText.substring(0, currentText.length - 1); } } else { CustomKeyboard.of(context) .controller .text += text; } }, child: Container( width: 100.0, height: 80.0, decoration: BoxDecoration( border: Border.all( color: Colors.grey, ), ), child: Center( child: Text(text), ), ), ); } } class CustomKeyboardController { final TextEditingController controller; CustomKeyboardController(this.controller); void clear() { controller.clear(); } void close() { FocusScope.of(controller.context).requestFocus(FocusNode()); } } class CustomKeyboardScope extends InheritedWidget { final CustomKeyboardController controller; CustomKeyboardScope({ Key key, @required Widget child, }) : assert(child != null), controller = CustomKeyboardController(TextEditingController()), super(key: key, child: child); static CustomKeyboardController of(BuildContext context) { return (context.dependOnInheritedWidgetOfExactType<CustomKeyboardScope>()) .controller; } @override bool updateShouldNotify(CustomKeyboardScope oldWidget) { return controller != oldWidget.controller; } } ``` 在上面的示例代码中,`CustomKeyboard` Widget是自定义键盘的主Widget,它包含了一个`TextField`和一些自定义的按钮。 `CustomButton` Widget是自定义键盘中的按键,它使用`GestureDetector`来处理按钮点击事件。 `CustomKeyboardController`是自定义键盘的控制器,用于控制输入框的文本内容。 最后,使用`CustomKeyboardScope` Widget来将`CustomKeyboardController`注入到自定义键盘中。 在需要使用自定义键盘的地方,可以使用以下代码来显示自定义键盘: ```dart CustomKeyboardScope( child: CustomKeyboard(), ); ``` 同时,需要将`CustomKeyboardController`与输入框关联起来,可以使用以下代码: ```dart TextField( controller: CustomKeyboardScope.of(context).controller.textEditingController, focusNode: FocusNode(), ); ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值