Flutter開發(fā)技巧RadialGradient中radius計算詳解
一、問題來源
項目中遇到 json 模型映射成 RadialGradient 組件的需求,其他參數(shù)正常傳遞即可;
唯獨 radius 參數(shù)效果有出入,總結(jié)記錄一下;
二、四種情況
通過 RadialGradient 參數(shù) center 可以分為四種情況,這四種情況分別對應(yīng)四種 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,
【貪婪模式】
【非貪婪模式】
【使用對角線半徑】(注意左下角的一點點留白,基本實現(xiàn)全覆蓋)
三、實現(xiàn)源碼
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 方法實現(xiàn)
// 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 參數(shù)無效) 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 模式,正常使用默認模式即可;
以上就是Flutter小技巧RadialGradient 中 radius 的計算的詳細內(nèi)容,更多關(guān)于Flutter RadialGradient radius計算的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Android tabLayout+recyclerView實現(xiàn)錨點定位的示例
這篇文章主要介紹了Android tabLayout+recyclerView實現(xiàn)錨點定位的示例,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-08-08Android MarkTipsView文字標識控件使用方法
這篇文章主要為大家詳細介紹了Android MarkTipsView文字標識控件的使用方法,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2021-04-04Android實現(xiàn)可輸入數(shù)據(jù)的彈出框
這篇文章主要為大家詳細介紹了Android實現(xiàn)可輸入數(shù)據(jù)的彈出框,文章提供了兩種方式,示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2016-01-01Android開發(fā)之設(shè)置開機自動啟動的幾種方法
這篇文章主要介紹了Android開發(fā)之設(shè)置開機自動啟動的幾種方法的相關(guān)資料,這里提供三種方法幫助大家實現(xiàn)這樣的功能,需要的朋友可以參考下2017-08-08詳解Android studio如何導(dǎo)入jar包方法
這篇內(nèi)容主要給大家詳細說明了如何導(dǎo)入jar包,以及Android studio遇到的各種問題和解決辦法。2017-12-12