返回顶部
首页 > 资讯 > 移动开发 >Flutter开发技巧RadialGradient中radius计算详解
  • 182
分享到

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

Flutter RadialGradient radius计算Flutter RadialGradient 2023-01-15 12:01:48 182人浏览 安东尼
摘要

目录一、问题来源二、四种情况1、情况一2、情况二3、情况三4、情况四三、实现源码四、radiusOfRadialGradient 方法实现最后一、问题来源 项目中遇到 JSON 模

一、问题来源

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

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

二、四种情况

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

1、情况一

Alignment.center,

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

【贪婪模式】

p>【非贪婪模式】

2、情况二

Alignment.centerLeft,
Alignment.centerRight,

【贪婪模式】

【非贪婪模式】

3、情况三

Alignment.topCenter,
Alignment.bottomCenter,

【贪婪模式】

【非贪婪模式】

4、情况四

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

【贪婪模式】

【非贪婪模式】

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

三、实现源码

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 _GradientOfRadialDemoState 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.isGreed = !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 是否贪婪模式(贪婪模式用大半径,否则小半径)
  /// isDiagonal 四角是否使用对角线(为 true 则 isGreed 参数无效)
  double? radiusOfRadialGradient({
    required double? width,
    required double? height,
    bool isGreed = true,
    bool isDiagonal = true,
  }) {
    if(width == null || height == null
        || 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,
    ].contains(this)) {
      result = isGreed == true ? 1 : max/min * 0.5;
    }
    return result;
  }
}

最后

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

GitHub

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

--结束END--

本文标题: Flutter开发技巧RadialGradient中radius计算详解

本文链接: https://lsjlt.com/news/177801.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作