Flutter開發(fā)技巧RadialGradient中radius計算詳解
一、問題來源
項(xiàng)目中遇到 json 模型映射成 RadialGradient 組件的需求,其他參數(shù)正常傳遞即可;
唯獨(dú) 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,
【貪婪模式】

【非貪婪模式】

【使用對角線半徑】(注意左下角的一點(diǎn)點(diǎn)留白,基本實(shí)現(xiàn)全覆蓋)

三、實(shí)現(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 方法實(shí)現(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{
/// 獲取雷達(dá)漸進(jìn)色 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;
}
}
最后
項(xiàng)目中為了方便查看差異使用了 TileMode.decal 模式,正常使用默認(rèn)模式即可;
以上就是Flutter小技巧RadialGradient 中 radius 的計算的詳細(xì)內(nèi)容,更多關(guān)于Flutter RadialGradient radius計算的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Android tabLayout+recyclerView實(shí)現(xiàn)錨點(diǎn)定位的示例
這篇文章主要介紹了Android tabLayout+recyclerView實(shí)現(xiàn)錨點(diǎn)定位的示例,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-08-08
Android MarkTipsView文字標(biāo)識控件使用方法
這篇文章主要為大家詳細(xì)介紹了Android MarkTipsView文字標(biāo)識控件的使用方法,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2021-04-04
Android實(shí)現(xiàn)可輸入數(shù)據(jù)的彈出框
這篇文章主要為大家詳細(xì)介紹了Android實(shí)現(xiàn)可輸入數(shù)據(jù)的彈出框,文章提供了兩種方式,示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2016-01-01
Android開發(fā)之設(shè)置開機(jī)自動啟動的幾種方法
這篇文章主要介紹了Android開發(fā)之設(shè)置開機(jī)自動啟動的幾種方法的相關(guān)資料,這里提供三種方法幫助大家實(shí)現(xiàn)這樣的功能,需要的朋友可以參考下2017-08-08
詳解Android studio如何導(dǎo)入jar包方法
這篇內(nèi)容主要給大家詳細(xì)說明了如何導(dǎo)入jar包,以及Android studio遇到的各種問題和解決辦法。2017-12-12
Android 自定義底部上拉控件的實(shí)現(xiàn)方法
下面小編就為大家分享一篇Android 自定義底部上拉控件的實(shí)現(xiàn)方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-01-01

