Flutter开发笔记 —— 自定义按钮边框虚线实现

前言

之前做业务的时候,一直依赖依赖库来实现虚线,今天学习了一下,才得知按钮也可以实现自定义虚线边框

思路

我们以ElevatedButton按钮为例,style下的ButtonStyle中,存在shape属性字段,支持一个OutlinedBorder类型的边框类,从下面可以了解到paint绘制方法,这个是绘制虚线的重点方法

自定义虚线边框组件

import 'dart:ui';

import 'package:flutter/material.dart';

class CustomDashBorder extends OutlinedBorder{
  final double? dashGap;
  final BorderRadiusGeometry? borderRadius;

  CustomDashBorder({super.side,this.dashGap,this.borderRadius});



  @override
  OutlinedBorder copyWith({BorderSide? side,double? dashGap,BorderRadiusGeometry? borderRadius}) {
    return CustomDashBorder(side: side ?? this.side,dashGap: dashGap ?? this.dashGap,borderRadius: borderRadius ?? this.borderRadius);
  }

  @override
  Path getInnerPath(Rect rect, {TextDirection? textDirection}) {
    var innerRRect = borderRadius!.resolve(textDirection).toRRect(rect);
    var adjustedRRect = innerRRect.deflate(side.strokeInset);
    return Path()..addRRect(adjustedRRect);
  }

  @override
  Path getOuterPath(Rect rect, {TextDirection? textDirection}) {
    return Path()..addRRect(borderRadius!.resolve(textDirection).toRRect(rect));
  }

  @override
  void paint(Canvas canvas, Rect rect, {TextDirection? textDirection}) {

    final Paint paint = Paint()
      ..color = side.color
      ..strokeWidth = side.width
     ..style = PaintingStyle.stroke;
    
    // TODO: implement paint
    var path = getOuterPath(rect);
    
    CustomDashBorderPaint(dashGap ?? 3).paint(canvas, path, paint);
  }

  @override
  ShapeBorder scale(double t) {
    return CustomDashBorder(
      side: side.scale(t),
      dashGap: dashGap! * t,
    );
  }

  @override
  ShapeBorder? lerpTo(ShapeBorder? b, double t) {
    if (b is CustomDashBorder) {
      return CustomDashBorder(
        side: BorderSide.lerp(side, b.side, t),
        borderRadius: BorderRadiusGeometry.lerp(borderRadius, b.borderRadius, t)!,
        dashGap: lerpDouble(dashGap, b.dashGap, t) ?? 0,
      );
    }
    return super.lerpTo(b, t);
  }

  @override
  ShapeBorder? lerpFrom(ShapeBorder? a, double t) {
    if (a is CustomDashBorder) {
      return CustomDashBorder(
        side: BorderSide.lerp(a.side, side, t),
        borderRadius: BorderRadiusGeometry.lerp(a.borderRadius, borderRadius, t)!,
        dashGap: lerpDouble(a.dashGap, dashGap, t) ?? 0,
      );
    }
    return super.lerpFrom(a, t);
  }
}

class CustomDashBorderPaint {
  final double dashGap;

  CustomDashBorderPaint(this.dashGap);

  void paint(Canvas canvas,Path path,Paint paint){
    var pms = path.computeMetrics();
    final double partLength = dashGap + dashGap;

    for(var pm in pms) {
      int count = pm.length ~/ partLength;
      for (var i = 0; i < count; i++) {
        canvas.drawPath(
            pm.extractPath(partLength * i, partLength * i + dashGap), paint);
      }
      var sub = pm.length % partLength;
      canvas.drawPath(pm.extractPath(pm.length - sub, pm.length), paint);
    }

  }
}

先简单介绍下复写的几个方法
  • copyWith (就是复制一个属性值一样的类)
  • getInnerPath (获取当前矩形内部的空间 如果width = 10 则内层空间只有一半5)
  • getOuterPath (获取当前可视化矩形完整的显示RRect矩形路径)
  • paint (绘制方法
  • scale (根据当前边框进行缩放)
  • lerpTo 和 lerpFrom(动画过渡)

自定义绘制方法

可以看到我们自己定义了一个CustomDashBorderPaint类,其中提供了dashGap 实际上可以分开为 step(实现) / span(空白) 我们为了方便则统一值

var pms = path.computeMetrics(); 用来分成当前边框一个个连续的路径段落
final double partLength = dashGap + dashGap; (可认为 step + span)

for(var pm in pms) {
//获取当前路径段落总长度整除实线和空白的总和
      int count = pm.length ~/ partLength;
      for (var i = 0; i < count; i++) {
// extractPath 用来裁切段落 这里规律假设pm.length = 30 
        //step = 5 span = 3
        // 30 ~ 8
        // 0 - > 5 i = 0
        // 8 -> 13  i= 1
        // 16 -> 21 i = 2
        // 24 -> 29 +  i = 3
        canvas.drawPath(
            pm.extractPath(partLength * i, partLength * i + dashGap), paint);
      }
//处理尾巴不够整除的绘制逻辑
      var sub = pm.length % partLength;
      canvas.drawPath(pm.extractPath(pm.length - sub, pm.length), paint);
    }
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇