gpt4 book ai didi

flutter - 在 Flutter 中画一个圆形菜单

转载 作者:行者123 更新时间:2023-12-05 02:50:34 26 4
gpt4 key购买 nike

我正在尝试绘制一个圆形菜单,如下图所示,但是我是 Flutter 的新手,我不知道从哪里开始做这样的事情。

我只有 8 个 peace,而不是图片中的 12 个,它们都是链接,每个链接都指向应用程序的不同部分。

在中心的灰色区域,我们将有简短的文字

最佳答案

我希望它能有所作为。

enter image description here

步骤:

  1. 通过类似 Figma 的方式绘制 svg
  2. 使用path_parsingsvg path
  3. 创建 flutter Path 的包
  4. 创建 ShapeDecoration 重新 ClipPath,我选择了 ClipPath,但是使用 ShapeDecoration 你可以添加阴影.
  5. 使用Matrix4作为PathTransform.rotate进行旋转。我选择了 `Transform.rotate 两次它更快但是使用 Path.transform是更简洁的方法。
  6. 使用角度的正弦和余弦计算菜单每个花瓣的位置。
  7. 稍微调整一下。

编码愉快!享受吧!

附注如果我们不指定具体的 block 数来求解会更好。

示例代码:

import 'dart:math' as math;

import 'package:flutter/material.dart';

const double degrees2Radians = math.pi / 180.0;

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: Scaffold(
backgroundColor: Colors.amber,
body: SafeArea(
child: MyHomePage(),
),
),
);
}
}

class MyHomePage extends StatelessWidget {
final items = [
ButtonData(title: 'one', onTap: () => print('1')),
ButtonData(title: 'two', onTap: () => print('2')),
ButtonData(title: 'three', onTap: () => print('3')),
ButtonData(title: 'four', onTap: () => print('4')),
ButtonData(title: 'five', onTap: () => print('5')),
ButtonData(title: 'six', onTap: () => print('6')),
ButtonData(title: 'seven', onTap: () => print('7')),
ButtonData(title: 'eight', onTap: () => print('8')),
ButtonData(onTap: () => print('center')),
];

@override
Widget build(BuildContext context) {
return Container(
height: 300,
width: 300,
child: Stack(
children: items
.asMap()
.map((index, buttonData) {
if (index < 8) {
var degree = 360 / 8 * index;
var radian = degree * degrees2Radians;
return MapEntry(
index,
Align(
alignment: Alignment(
math.sin(radian),
math.cos(radian),
),
child: Transform.rotate(
angle: -radian,
child: MenuPetal(angle: -radian, buttonData: buttonData),
),
),
);
}
return MapEntry(
index,
_centerButton(buttonData),
);
})
.values
.toList(),
),
);
}

Widget _centerButton(ButtonData buttonData) {
return Center(
child: ClipRRect(
borderRadius: BorderRadius.circular(25),
child: GestureDetector(
onTap: buttonData.onTap,
child: Container(
width: 50,
height: 50,
color: Colors.black38,
),
),
),
);
}
}

class ButtonData {
final String title;
final void Function() onTap;

ButtonData({this.title, this.onTap});
}

class MenuPetal extends StatelessWidget {
const MenuPetal({
Key key,
this.angle,
this.buttonData,
}) : super(key: key);

final double angle;
final ButtonData buttonData;
final double factor = 0.38;

@override
Widget build(BuildContext context) {
return FractionallySizedBox(
heightFactor: factor,
widthFactor: factor,
child: GestureDetector(
onTap: buttonData.onTap,
child: ClipPath(
clipper: MyCustomClipper(),
child: Container(
alignment: Alignment.center,
decoration: BoxDecoration(
image: DecorationImage(
fit: BoxFit.fill,
image:
NetworkImage('https://source.unsplash.com/featured/?white'),
),
),
child: Padding(
padding: EdgeInsets.only(top: 60),
child: Transform.rotate(
angle: -angle,
child: Text(buttonData.title),
),
),
),
),
),
);
}
}

class MyCustomClipper extends CustomClipper<Path> {
@override
Path getClip(Size size) {
var x = size.width / 100 * 0.802;
var y = size.height / 100;
var path = Path()
..moveTo(39.4 * x, 6.1 * y)
..cubicTo(43.2 * x, -1.8 * y, 57.1 * x, -1.8 * y, 60.9 * x, 6.1 * y)
..lineTo(99.1 * x, 84.1 * y)
..cubicTo(102.1 * x, 90.2 * y, 99.1 * x, 93.9 * y, 92.0 * x, 95.6 * y)
..cubicTo(67.4 * x, 101.7 * y, 36.9 * x, 101.7 * y, 9.2 * x, 95.6 * y)
..cubicTo(1.2 * x, 93.8 * y, -1.3 * x, 88.7 * y, 1.2 * x, 84.1 * y)
..lineTo(39.4 * x, 6.1 * y);

return path.shift(Offset(12, 0));
}

@override
bool shouldReclip(CustomClipper<Path> oldClipper) => true;
}

关于flutter - 在 Flutter 中画一个圆形菜单,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63623345/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com