Flutter 颤振-我正在寻找一种方法来创建一个均匀放置图标的圆
Flutter 颤振-我正在寻找一种方法来创建一个均匀放置图标的圆,flutter,Flutter,导入“包:flift/foundation.dart”; 进口“包装:颤振/材料.省道”; 导入'dart:math'作为数学; 常数double _radisperderegree=Math.pi/180; 最终双倍_startAngle=-90.0*_弧度等级; typedef双项目角度计算器(int索引); 类主页扩展了StatefulWidget{ @凌驾 状态createState(){ 返回新的_HomePageState(); } } 类_HomePageState使用Ticker
导入“包:flift/foundation.dart”;
进口“包装:颤振/材料.省道”;
导入'dart:math'作为数学;
常数double _radisperderegree=Math.pi/180;
最终双倍_startAngle=-90.0*_弧度等级;
typedef双项目角度计算器(int索引);
类主页扩展了StatefulWidget{
@凌驾
状态createState(){
返回新的_HomePageState();
}
}
类_HomePageState使用TickerProviderStateMixin扩展状态{
最终清单项目=[
新容器(
装饰:新盒子装饰(形状:BoxShape.circle,
),
孩子:新材料按钮(
按下:(){},
子:新建Image.asset(
“images/recycling.png”,
宽度:60.0,
身高:60.0,
适合:BoxFit.cover,
),
),
),
新扁平按钮(
按下:(){},
子:新建Image.asset(
“images/gas station.png”,
宽度:60.0,
身高:60.0,
适合:BoxFit.cover,
),
),
新扁平按钮(
按下:(){},
子:新建Image.asset(
“images/lightbulb.png”,
宽度:60.0,
身高:60.0,
适合:BoxFit.cover,
),
),
新扁平按钮(
按下:(){},
子:新建Image.asset(
“images/cflamp.png”,
宽度:60.0,
身高:60.0,
适合:BoxFit.cover,
),
),
新扁平按钮(
按下:(){},
子:新建Image.asset(
“images/plug.png”,
宽度:60.0,
身高:60.0,
适合:BoxFit.cover,
),
)
];
@凌驾
小部件构建(构建上下文){
归还新脚手架(
正文:_buildBody(),
);
}
小部件_buildBody(){
返回容器(
装饰:新盒子装饰(
颜色:颜色。青色),
宽度:MediaQuery.of(context).size.width,
孩子:填充(
填充:常数边集全部(25.0),
子:新列(
mainAxisAlignment:mainAxisAlignment.start,
儿童:[
新填料(
填充:仅限常量边集(顶部:20.0,左侧:20.0,右侧:20.0),
子容器:新容器(
装饰:新盒子装饰(
渐变:新的线性渐变(颜色:[
新颜色(0xFFA19D9A),
颜色,白色,
新颜色(0xFFA19D9A),
]),
边界半径:
新边界半径。全部(新半径。圆形(25.0)),
子容器:新容器(
边距:所有常数边集(5.0),
装饰:新盒子装饰(
颜色:Colors.teal,
边界半径:
新边界半径。全部(新半径。圆形(22.0)),
孩子:新的填充物(
填充:常数边集全部(5.0),
儿童:新文本(
“通过选择任何图标获取建议”,
样式:新文本样式(
字体大小:22.0,
颜色:颜色,白色,
fontFamily:“鱼子酱梦”,
fontWeight:fontWeight.w600),
textAlign:textAlign.center,
),
),
),
),
),
_buildStackView(),
],
),
),
);
}
小部件_buildStackView(){
最终列表饮料=[];
double width=MediaQuery.of(context).size.width;
double height=MediaQuery.of(context).size.height;
双外表面=数学最小值(宽度*3/4,高度*3/4);
双内半径=外半径*3/4;
对于(int i=0;iimport 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'dart:math' as Math;
const double _radiansPerDegree = Math.pi / 180;
final double _startAngle = -90.0 * _radiansPerDegree;
typedef double ItemAngleCalculator(int index);
class HomePage extends StatefulWidget {
@override
State createState() {
return new _HomePageState();
}
}
class _HomePageState extends State<HomePage> with TickerProviderStateMixin {
final List<Widget> items = [
new Container(
decoration: new BoxDecoration(shape: BoxShape.circle,
),
child: new MaterialButton(
onPressed: () {},
child: new Image.asset(
'images/recycling.png',
width: 60.0,
height: 60.0,
fit: BoxFit.cover,
),
),
),
new FlatButton(
onPressed: () {},
child: new Image.asset(
'images/gas-station.png',
width: 60.0,
height: 60.0,
fit: BoxFit.cover,
),
),
new FlatButton(
onPressed: () {},
child: new Image.asset(
'images/light-bulb.png',
width: 60.0,
height: 60.0,
fit: BoxFit.cover,
),
),
new FlatButton(
onPressed: () {},
child: new Image.asset(
'images/cflamp.png',
width: 60.0,
height: 60.0,
fit: BoxFit.cover,
),
),
new FlatButton(
onPressed: () {},
child: new Image.asset(
'images/plug.png',
width: 60.0,
height: 60.0,
fit: BoxFit.cover,
),
)
];
@override
Widget build(BuildContext context) {
return new Scaffold(
body: _buildBody(),
);
}
Widget _buildBody() {
return Container(
decoration: new BoxDecoration(
color: Colors.teal),
width: MediaQuery.of(context).size.width,
child: Padding(
padding: const EdgeInsets.all(25.0),
child: new Column(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
new Padding(
padding: const EdgeInsets.only(top: 20.0,left: 20.0,right: 20.0),
child: new Container(
decoration: new BoxDecoration(
gradient: new LinearGradient(colors: [
new Color(0xFFA19D9A),
Colors.white,
new Color(0xFFA19D9A),
]),
borderRadius:
new BorderRadius.all(new Radius.circular(25.0))),
child: new Container(
margin: const EdgeInsets.all(5.0),
decoration: new BoxDecoration(
color: Colors.teal,
borderRadius:
new BorderRadius.all(new Radius.circular(22.0))),
child: new Padding(
padding: const EdgeInsets.all(5.0),
child: new Text(
"Get recommendations by selecting any icon",
style: new TextStyle(
fontSize: 22.0,
color: Colors.white,
fontFamily: 'CaviarDreams',
fontWeight: FontWeight.w600),
textAlign: TextAlign.center,
),
),
),
),
),
_buildStackView(),
],
),
),
);
}
Widget _buildStackView() {
final List<Widget> beverages = <Widget>[];
double width = MediaQuery.of(context).size.width;
double height = MediaQuery.of(context).size.height;
double outerRadius = Math.min(width * 3 / 4, height * 3 / 4);
double innerWhiteRadius = outerRadius * 3 / 4;
for (int i = 0; i < items.length; i++) {
beverages.add(_buildIcons(i));
}
return Flexible(
child: Container(
padding: EdgeInsets.all(10.0),
child: new Stack(
alignment: AlignmentDirectional.center,
children: <Widget>[
_drawCircle(outerRadius, Color.fromRGBO(255, 255, 255, 0.3)),
_drawCircle(outerRadius - 25, Color.fromRGBO(255, 255, 255, 0.2)),
new CustomMultiChildLayout(
delegate: new _CircularLayoutDelegate(
itemCount: items.length,
radius: outerRadius / 2,
),
children: beverages,
),
GestureDetector(
onTap: () {
Navigator.of(context).pushNamed("/ask/capture");
},
child: Image.asset(
"images/earth-globe.png",
width: innerWhiteRadius,
height: innerWhiteRadius,
fit: BoxFit.cover,
)
),
],
),
),
);
}
// Draw a circle with given radius and color.
Widget _drawCircle(double radius, Color color) {
return new Container(
decoration: new BoxDecoration(shape: BoxShape.circle, color: color),
width: radius,
height: radius,
);
}
Widget _buildIcons(int index) {
final Widget item = items[index];
return new LayoutId(
id: 'BUTTON$index',
child: item,
);
}
}
double _calculateItemAngle(int index) {
double _itemSpacing = 360.0 / 5.0;
return _startAngle + index * _itemSpacing * _radiansPerDegree;
}
class _CircularLayoutDelegate extends MultiChildLayoutDelegate {
static const String actionButton = 'BUTTON';
final int itemCount;
final double radius;
_CircularLayoutDelegate({
@required this.itemCount,
@required this.radius,
});
Offset center;
@override
void performLayout(Size size) {
center = new Offset(size.width / 2, size.height / 2);
for (int i = 0; i < itemCount; i++) {
final String actionButtonId = '$actionButton$i';
if (hasChild(actionButtonId)) {
final Size buttonSize =
layoutChild(actionButtonId, new BoxConstraints.loose(size));
final double itemAngle = _calculateItemAngle(i);
positionChild(
actionButtonId,
new Offset(
(center.dx - buttonSize.width / 2) + (radius) * Math.cos(itemAngle),
(center.dy - buttonSize.height / 2) +
(radius) * Math.sin(itemAngle),
),
);
}
}
}
@override
bool shouldRelayout(_CircularLayoutDelegate oldDelegate) =>
itemCount != oldDelegate.itemCount ||
radius != oldDelegate.radius ;
}
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'dart:math' as Math;
const double _radiansPerDegree = Math.pi / 180;
final double _startAngle = -90.0 * _radiansPerDegree;
typedef double ItemAngleCalculator(int index);
class HomePage extends StatefulWidget {
@override
State createState() {
return new _HomePageState();
}
}
class _HomePageState extends State<HomePage> with TickerProviderStateMixin {
final List<Widget> items = [
new Container(
decoration: new BoxDecoration(
shape: BoxShape.circle,
color: Colors.white,
),
padding: EdgeInsets.all(10),
child: new MaterialButton(
onPressed: () {},
child: new Image.asset(
'assets/images/ball1.png',
width: 60.0,
height: 60.0,
fit: BoxFit.cover,
),
),
),
Container(
decoration: new BoxDecoration(
shape: BoxShape.circle,
color: Colors.white,
),
padding: EdgeInsets.all(10),
child: new FlatButton(
onPressed: () {},
child: new Image.asset(
'assets/images/ball1.png',
width: 60.0,
height: 60.0,
fit: BoxFit.cover,
),
),
),
Container(
decoration: new BoxDecoration(
shape: BoxShape.circle,
color: Colors.white,
),
padding: EdgeInsets.all(10),
child: new FlatButton(
onPressed: () {},
child: new Image.asset(
'assets/images/ball1.png',
width: 60.0,
height: 60.0,
fit: BoxFit.cover,
),
),
),
Container(
decoration: new BoxDecoration(
shape: BoxShape.circle,
color: Colors.white,
),
padding: EdgeInsets.all(10),
child: new FlatButton(
onPressed: () {},
child: new Image.asset(
'assets/images/ball1.png',
width: 60.0,
height: 60.0,
fit: BoxFit.cover,
),
),
),
Container(
decoration: new BoxDecoration(
shape: BoxShape.circle,
color: Colors.white,
),
padding: EdgeInsets.all(10),
child: new FlatButton(
onPressed: () {},
child: new Image.asset(
'assets/images/ball1.png',
width: 60.0,
height: 60.0,
fit: BoxFit.cover,
),
),
)
];
@override
Widget build(BuildContext context) {
return _buildBody();
}
Widget _buildBody() {
return Container(
decoration: new BoxDecoration(color: Colors.white),
width: MediaQuery.of(context).size.width,
child: Padding(
padding: const EdgeInsets.all(25.0),
child: new Column(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
new Padding(
padding:
const EdgeInsets.only(top: 20.0, left: 20.0, right: 20.0),
child: new Container(
decoration: new BoxDecoration(
gradient: new LinearGradient(colors: [
new Color(0xFFA19D9A),
Colors.white,
new Color(0xFFA19D9A),
]),
borderRadius:
new BorderRadius.all(new Radius.circular(25.0))),
child: new Container(
margin: const EdgeInsets.all(5.0),
decoration: new BoxDecoration(
color: Colors.teal,
borderRadius:
new BorderRadius.all(new Radius.circular(22.0))),
child: new Padding(
padding: const EdgeInsets.all(5.0),
child: new Text(
"Get recommendations by selecting any icon",
style: new TextStyle(
fontSize: 22.0,
color: Colors.white,
fontFamily: 'CaviarDreams',
fontWeight: FontWeight.w600),
textAlign: TextAlign.center,
),
),
),
),
),
_buildStackView(),
],
),
),
);
}
Widget _buildStackView() {
final List<Widget> beverages = <Widget>[];
double width = MediaQuery.of(context).size.width;
double height = MediaQuery.of(context).size.height;
double outerRadius = Math.min(width * 3 / 4, height * 3 / 4);
double innerWhiteRadius = outerRadius * 3 / 4;
for (int i = 0; i < items.length; i++) {
beverages.add(_buildIcons(i));
}
return Flexible(
child: Container(
padding: EdgeInsets.all(10.0),
child: new Stack(
alignment: AlignmentDirectional.center,
children: <Widget>[
_drawCircle(outerRadius + 5, Colors.teal[100]),
_drawCircle(outerRadius, Colors.white),
_drawCircle(outerRadius / 2, Colors.teal[100]),
_drawCircle((outerRadius - 40) / 2, Colors.teal),
new CustomMultiChildLayout(
delegate: new _CircularLayoutDelegate(
itemCount: items.length,
radius: outerRadius / 2,
),
children: beverages,
),
GestureDetector(
onTap: () {
Navigator.of(context).pushNamed("/ask/capture");
},
child: Icon(
Icons.check,
size: 100,
color: Colors.white,
)),
],
),
),
);
}
// Draw a circle with given radius and color.
Widget _drawCircle(double outerRadius, Color color) {
return new Container(
decoration: new BoxDecoration(shape: BoxShape.circle, color: color),
width: outerRadius,
height: outerRadius,
);
}
Widget _buildIcons(int index) {
final Widget item = items[index];
return new LayoutId(
id: 'BUTTON$index',
child: item,
);
}
}
double _calculateItemAngle(int index) {
double _itemSpacing = 360.0 / 5.0;
return _startAngle + index * _itemSpacing * _radiansPerDegree;
}
class _CircularLayoutDelegate extends MultiChildLayoutDelegate {
static const String actionButton = 'BUTTON';
final int itemCount;
final double radius;
_CircularLayoutDelegate({
@required this.itemCount,
@required this.radius,
});
Offset center;
@override
void performLayout(Size size) {
center = new Offset(size.width / 2, size.height / 2);
for (int i = 0; i < itemCount; i++) {
final String actionButtonId = '$actionButton$i';
if (hasChild(actionButtonId)) {
final Size buttonSize =
layoutChild(actionButtonId, new BoxConstraints.loose(size));
final double itemAngle = _calculateItemAngle(i);
positionChild(
actionButtonId,
new Offset(
(center.dx - buttonSize.width / 2) + (radius) * Math.cos(itemAngle),
(center.dy - buttonSize.height / 2) +
(radius) * Math.sin(itemAngle),
),
);
}
}
}
@override
bool shouldRelayout(_CircularLayoutDelegate oldDelegate) =>
itemCount != oldDelegate.itemCount || radius != oldDelegate.radius;
}