开发者

Flutter开发技巧RadialGradient中radius计算详解

开发者 https://www.devze.com 2023-01-16 10:22 出处:网络 作者: SoaringHeart
目录一、问题来源二、四种情况1、情况一2、情况二3、情况三4、情况四三、实现源码四、radiusOfRadialGradient 方法实现最后一、问题来源
目录
  • 一、问题来源
  • 二、四种情况
    • 1、情况一
    • 2、情况二
    • 3、情况三
    • 4、情况四
  • 三、实现源码
    • 四、radiusOfRadialGradient 方法实现
      • 最后

        一、问题来源

        项目中遇到 json 模型映射成 RadialGradient 组件的需求,其他参数正常传递即可;

        唯独 radius 参数效果有出入,总结记录一下;

        二、四种情况

        通过 RadialGradient 参数 center 可以分为四种情况,这四种情况分别对应四种 radius 的值:

        1、情况一

        Alignment.center,
        

        贪婪模式下组件的宽高中最大值的一半/最小值的一半为 radius;否则radius是0.5;

        【贪婪模式】

        Flutter开发技巧RadialGradient中radius计算详解

        p>【非贪婪模式】

        Flutter开发技巧RadialGradient中radius计算详解

        2、情况二

        Alignment.centerLeft,
        Alignment.centerRight,
        

        【贪婪模式】

        Flutter开发技巧RadialGradient中radius计算详解

        【非贪婪模式】

        Flutter开发技巧RadialGradient中radius计算详解

        3、情况三

        Alignment.topCenter,
        Alignment.bottomCenter,
        

        【贪婪模式】

        Flutter开发技巧RadialGradient中radius计算详解

        【非贪婪模式】

        Flutter开发技巧RadialGradient中radius计算详解

        4、情况四

        Alignment.topLeft,
        Alignment.topRight,
        Alignment.bottomLeft,
        Alignment.bottomRight,
        

        【贪婪模式】

        Flutter开发技巧RadialGradient中radius计算详解

        【非贪婪模式】

        Flutter开发技巧RadialGradient中radius计算详解

        【使用对角线半径】(注意左下角的一点点留白,基本实现全覆盖)

        Flutter开发技巧RadialGradient中radius计算详解

        三、实现源码

        GradientOfRadialDemo

        import 'package:flutter/material.Dart';
        import 'package:flutter_templet_project/basicWidget/SectionHeader.dart';
        import 'package:flutter_templet_project/extension/alignment_ext.dart';
        import 'package:tuple/tuple.dart';
        class GradientOfRadialDemo extends StatefulWidget {
          GradientOfRadialDemo({ Key? key, this.title}) : super(key: key);
          final String? title;
          @override
          _GradientOfRadialDemoState createState() => _GradientOfRadialDemoState();
        }
        class _GradientOfRadialDemoSFWNrduYXOtate extends State<GradientOfRadialDemo> {
          var maxWidth = double.infinity;
          var maxHeight = double.infinity;
          /// 是否是贪婪模式
          var isGreed = true;
          /// 是否使用对角线做半径
          bool isDiagonal = true;
          @override
          Widget build(BuildContext context) {
            return Scaffold(
                appBar: AppBar(
                  title: Text(widget.title ?? "$widget"),
                  bottom: buildAppBottom(),
                ),
                body: Container(
                  // height: 300,
                  child: buildRadial(),
                ),
                // body: ListView(
                //   children: [
                //     SectionHeader.h4(title: 'RadialGradient',),
                //     buildRadial(),
                //   ],
                // )
            );
          }
          buildAppBottom() {
            return PreferredSize(
              preferredSize: Size(double.infinity, 50),
              child: Row(
                mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                children: [
                  _buildDropdownButton(),
                  _buildButton(
                    text: "isGreed: ${isGreed.toString()}",
                    onPressed: () {
                      this.isGphpreed = !this.isGreed;
                      setState(() {});
                    },
                  ),
                  _buildButton(
                    text: "isDiagonal: ${isDiagonal.toString()}",
                    onPressed: () {
                      this.isDiagonal = !this.isDiagonal;
                      setState(() {});
                    },
                  ),
                ],
              )
            );
          }
          var _dropValue = AlignmentExt.allCases[0];
          var _radius = 0.5;
          _buildDropdownButton() {
            return DropdownButton<Alignment>(
              value: _dropValue,
              items: AlignmentExt.allCases.map((e) => DropdownMenuItem(
                child: Text(e.toString().split('.')[1]),
                value: e,
              ),
              ).toList(),
              onChanged: (Alignment? value) {
                if (value == null) return;
                _dropValue = value;
                setState(() {});
              },
            );
          }
          _buildButton({
            required String text,
            required VoidCallback onPressed
          }) {
            return TextButton(
              onPressed: onPressed,
              child: Center(
                  child: Text(text,
                    style: TextStyle(color: Colors.white),
                  )
              ),
            );
          }
          Widget _buildBox({
            required String text,
            required Decoration decoration,
            double height: 100,
            double? width,
          }) {
            return LayoutBuilder(
              builder: (context, constraints) {
                this.maxWidth = constraints.maxWidth;
                this.maxHeight = constraints.maxHeight;
                return Container(
                  // width: width,
                  // height: height,
                  margin: const EdgeInsets.all(8.0),
                  decoration: decoration,
                  alignment: Alignment.center,
                  child: Text(text, style: TextStyle(color: Colors.white, fontSize: 16.0)),
                );
            编程  }
            );
          }
          buildRadial() {
            var tuples = <Tuple2<Color, double>>[      Tuple2(Colors.red, 0.1),      Tuple2(Colors.blue, 0.3),      Tuple2(Colors.yellow, 0.5),      Tuple2(Colors.green, 1),    ];
            _radius = _dropValue.radiusOfRadialGradient(
              width: this.maxWidth,
              height: this.maxHeight,
              isGreed: this.isGreed,
              isDiagonal: this.isDiagonal
            ) ?? 0.5;
            print("_dropValue:${_dropValue} _radius:${_radius} maxWidth:${maxWidth} maxHeight:${maxHeight}");
            print("_radius: $_radius");
            return _buildBox(
              height: 100,
              text: 'RadialGradient',
              decoration: BoxDecoration(
                border: Border.all(),
                gradient: RadialGradient(
                  // tileMode: this.tileMode,
                  // tileMode: TileMode.mirror,
                  radius: _radius,
                  tileMode: TileMode.decal,
                  center: _dropValue,
                  // focal: Alignment.bottomCenter,
                  colors: tuples.map((e) => e.item1).toList(),
                  stops: tuples.map((e) => e.item2).toList(),
                ),
              ),
            );
          }
        }
        

        四、radiusOfRadialGradient 方法实现

        //  AlignmentExtension.dart
        //  flutter_templet_project
        //
        //  Created by shang on 2023/1/12 20:57.
        //  Copyright  2023/1/12 shang. All rights reserved.
        //
        import 'dart:math' as math;
        import 'package:flutter/cupertino.dart';
        extension AlignmentExt on Alignment{
          /// 获取雷达渐进色 radius
          /// isGreed 是否贪婪模式(贪婪模式用大半径,否则小半径)
          /// isDiago开发者_C入门nal 四角是否使用对角线(为 true 则 isGreed 参数无效)
          double? radiusOfRadialGradient({
            required double? width,
            required double? height,
            bool isGreed = true,
            bool isDiagonal = true,
          }) {
            if(width == null || height == nulFWNrduYXOl
                || width <= 0 || height <= 0) {
              return null;
            }
            final max = math.max(width, height);
            final min = math.min(width, height);
            double result = 0.5;
            if([
              Alignment.center,
            ].contains(this)){
              result = isGreed == true ? max/min * 0.5 : 0.5;
            } else if ([
              Alignment.topCenter,
              Alignment.bottomCenter,
            ].contains(this)) {
              result = isGreed == true ? max/min : 0.5;
            } else if ([
              Alignment.topLeft,
              Alignment.topRight,
              Alignment.bottomLeft,
              Alignment.bottomRight
            ].contains(this)) {
              if (isDiagonal) {
                final tmp = math.sqrt(math.pow(max, 2) + math.pow(min, 2)).ceil();
                // result = isGreed == true ? tmp/min : max/min;
                result = tmp/min;
              } else {
                result = isGreed == true ? max/min : 1;
              }
            } else if ([
              Alignment.centerLeft,
              Alignment.centerRight,
           FWNrduYXO ].contains(this)) {
              result = isGreed == true ? 1 : max/min * 0.5;
            }
            return result;
          }
        }
        

        最后

        项目中为了方便查看差异使用了 TileMode.decal 模式,正常使用默认模式即可;

        github

        以上就是Flutter小技巧RadialGradient 中 radius 的计算的详细内容,更多关于Flutter RadialGradient radius计算的资料请关注我们其它相关文章!

        0

        精彩评论

        暂无评论...
        验证码 换一张
        取 消

        关注公众号