问题描述
我在使用它时遇到了问题,因为屏幕右侧的这条曲线不是小部件,当我想在绿色一侧有一些其他小部件时,我不能,因为设计的曲线不是小部件,它是从绿色中剪裁的布局.
假设我想在屏幕右侧有这条曲线,在下方有一些小部件.
源代码
import 'package:flutter/material.dart';无效的主要(){runApp(MaterialApp(home: Scaffold(body: Test())));}类测试扩展 StatefulWidget {@覆盖_TestState createState() =>_TestState();}类 _TestState 扩展了状态<Test>{双 _height = 0.0;双 _width = 0.0;双 _rightPadding = 2.0;双 _btnSize = 25.0;双 _btnY = 0.0;@覆盖小部件构建(BuildContext 上下文){如果 (_height == 0.0)设置状态((){_height = MediaQuery.of(context).size.height;_width = MediaQuery.of(context).size.width;_btnY = _height/3 * 2;});返回 _height == 0.0?容器(): 堆(孩子们:<小部件>[容器(颜色:颜色.白色,),自定义油漆(尺寸:尺寸(_width - _rightPadding,_height),画家:CurvedPainter(_btnSize,_btnY),),],);}}类 CurvedPainter 扩展 CustomPainter {CurvedPainter(this.btnSize, this.btnY);最终双 btnSize;最终双 btnY;@覆盖无效油漆(帆布画布,尺寸大小){路径 path = Path();path.moveTo(0.0, 0.0);path.lineTo(size.width, 0.0);path.lineTo(size.width, btnY - btnSize * 2);path.cubicTo(size.width, btnY - btnSize * 0.3, size.width - btnSize * 0.95, btnY - btnSize * 0.9, size.width - btnSize, btnY);path.cubicTo(size.width - btnSize * 0.95, btnY + btnSize * 0.9, size.width, btnY + btnSize * 0.3, size.width, btnY + btnSize * 2);path.lineTo(size.width, size.height);path.lineTo(0.0, size.height);path.lineTo(0.0, 0.0);画布.drawPath(小路,画()..color = 颜色.透明..style = 绘画风格.fill);}@覆盖bool shouldRepaint(CurvedPainter oldDelegate) =>oldDelegate.btnY != btnY;}
我想在所有小部件之上使用右曲线作为小部件,没有绿色边,你假设绿色边是 ListView
.
您似乎需要下图中给出的类似的东西.
更新:添加了拖动控件
import 'dart:math' as math;导入包:颤振/material.dart";无效的主要()=>运行应用程序(我的应用程序());MyApp 类扩展 StatelessWidget {@覆盖小部件构建(BuildContext 上下文){返回材料应用程序(debugShowCheckedModeBanner:假,标题:颤振演示",主题:主题数据(primarySwatch:颜色.蓝色,),家:脚手架(正文:测试(),),);}}类测试扩展 StatefulWidget {@覆盖_TestState createState() =>_TestState();}枚举拖动类型 { 垂直,水平 }类 _TestState 扩展了状态<Test>{最终双 _btnSize = 48.0;最终双 _rightPadding = 0;双 _extraOffcet = 0;双_btnY;双 _currentX;双 _currentY;双倍高度;双宽度;bool _isHorizontalActive = true;bool _isVerticalActive = true;@覆盖无效初始化状态(){WidgetsBinding.instance.addPostFrameCallback(_afterLayout);super.initState();}_afterLayout(_) {_height = MediaQuery.of(context).size.height;_width = MediaQuery.of(context).size.width;_btnY = _height/2;setState(() {});}_onDrag(详细信息){_updateCoordinates(details.globalPosition.dx,details.globalPosition.dy,);}_updateCoordinates(双 x, 双 y) {设置状态((){如果(_isHorizontalActive){_updateX(x);}如果(_isVerticalActive){_updateY(y);}});}_updateX(x) {var dx = _currentX - x;_currentX = x;_extraOffcet = _extraOffcet + dx;_extraOffcet = math.max(_extraOffcet, _rightPadding);_extraOffcet = math.min(_extraOffcet, _width - _btnSize);}_updateY(y) {var dy = _currentY - y;_currentY = y;_btnY = _btnY - dy;_btnY = math.max(_btnY, _btnSize);_btnY = math.min(_btnY, _height - _btnSize);}_listItem(字符串文本,双倍高度){返回容器(高度:高度,孩子:文本(文本,样式:TextStyle(字体大小:20.0)),);}@覆盖小部件构建(BuildContext 上下文){返回 _height == null?容器(): 堆(孩子们:<小部件>[容器(填充:EdgeInsets.only(右:30),颜色:颜色.蓝色,高度:双无限,宽度:双无限,孩子:列(mainAxisAlignment:MainAxisAlignment.center,孩子:[_buildSwitch(类型:dragType.vertical),_buildSwitch(类型:dragType.horizontal),...列表.生成(4、(索引)=>_listItem('内部', 80),),]),),定位(右:_extraOffcet + _rightPadding,孩子:自定义油漆(尺寸:尺寸(_btnSize,_height),画家:CurvedPainter(_btnSize,_btnY),),),定位(顶部:_btnY - _btnSize/2 + 5,右:_extraOffcet + _rightPadding + 5,孩子:手势检测器(onPanDown:(详细信息){_currentX = details.globalPosition.dx;_currentY = details.globalPosition.dy;},onPanStart: _onDrag,onPanUpdate: _onDrag,孩子:材料(类型:MaterialType.circle,颜色:颜色.白色,海拔:8.0,孩子:容器(宽度:_btnSize - 10,高度:_btnSize - 10,孩子:图标(Icons.add),),),),),定位(顶部:0,左:_width - _extraOffcet,孩子:容器(颜色:颜色.白色,孩子:列(mainAxisAlignment: MainAxisAlignment.center,crossAxisAlignment:CrossAxisAlignment.start,孩子: List.generate(8, (index) => _listItem('from right', 20)),),高度:_高度,宽度:_width,),),],);}SwitchListTile _buildSwitch({dragType type}) {函数 onChange;字符串标题文本,标题文本;布尔值;if (type == dragType.horizontal) {值 = _isHorizontalActive;titleText = '水平拖动';onChange = (newValue) =>setState(() => _isHorizontalActive = newValue);} 别的 {值 = _isVerticalActive;titleText = '垂直拖动';onChange = (newValue) =>setState(() => _isVerticalActive = newValue);}字幕文本 = 价值?活动":禁用";返回 SwitchListTile(价值:价值,onChanged: onChange,标题:文本(titleText),副标题:文本(sutitleText),);}}类 CurvedPainter 扩展 CustomPainter {CurvedPainter(this.btnSize, this.btnY);最终双 btnSize;最终双 btnY;@覆盖无效油漆(帆布画布,尺寸大小){var halfBtnSize = btnSize/2;var xMax = size.width;var yMax = size.height;变量路径 = 路径()..moveTo(halfBtnSize, yMax)..lineTo(halfBtnSize, btnY + halfBtnSize * 2)..cubicTo(halfBtnSize, btnY + halfBtnSize, 0, btnY + halfBtnSize, 0, btnY)..cubicTo(0, btnY - halfBtnSize, halfBtnSize, btnY - halfBtnSize, halfBtnSize,btnY - halfBtnSize * 2)..lineTo(halfBtnSize, 0)..lineTo(xMax, 0)..lineTo(xMax, yMax);画布.drawPath(小路,画()..color = 颜色.white..style = 绘画风格.fill);}@覆盖bool shouldRepaint(CurvedPainter oldDelegate) =>oldDelegate.btnY != btnY;}
Here solved question about design this layout.
I have a problem to using that, because of this curve on right of screen is not widget and when I want to have some other widgets in green side, I can't, because designed curve is not widget its clipped from green layout.
Suppose I want to have this curve on right of screen and some widget in below of that.
Source code
import 'package:flutter/material.dart';
void main() {
runApp(MaterialApp(home: Scaffold(body: Test())));
}
class Test extends StatefulWidget {
@override
_TestState createState() => _TestState();
}
class _TestState extends State<Test> {
double _height = 0.0;
double _width = 0.0;
double _rightPadding = 2.0;
double _btnSize = 25.0;
double _btnY = 0.0;
@override
Widget build(BuildContext context) {
if (_height == 0.0)
setState(() {
_height = MediaQuery.of(context).size.height;
_width = MediaQuery.of(context).size.width;
_btnY = _height / 3 * 2;
});
return _height == 0.0
? Container()
: Stack(
children: <Widget>[
Container(
color: Colors.white,
),
CustomPaint(
size: Size(_width - _rightPadding, _height),
painter: CurvedPainter(_btnSize, _btnY),
),
],
);
}
}
class CurvedPainter extends CustomPainter {
CurvedPainter(this.btnSize, this.btnY);
final double btnSize;
final double btnY;
@override
void paint(Canvas canvas, Size size) {
Path path = Path();
path.moveTo(0.0, 0.0);
path.lineTo(size.width, 0.0);
path.lineTo(size.width, btnY - btnSize * 2);
path.cubicTo(size.width, btnY - btnSize * 0.3, size.width - btnSize * 0.95, btnY - btnSize * 0.9, size.width - btnSize, btnY);
path.cubicTo(size.width - btnSize * 0.95, btnY + btnSize * 0.9, size.width, btnY + btnSize * 0.3, size.width, btnY + btnSize * 2);
path.lineTo(size.width, size.height);
path.lineTo(0.0, size.height);
path.lineTo(0.0, 0.0);
canvas.drawPath(
path,
Paint()
..color = Colors.transparent
..style = PaintingStyle.fill);
}
@override
bool shouldRepaint(CurvedPainter oldDelegate) => oldDelegate.btnY != btnY;
}
I want to use right curve as an widget on top of all widgets, without having green side, you suppose green side is as ListView
.
It seems that you need something like this given in the image below.
Update: Dragging control added
import 'dart:math' as math;
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: Scaffold(
body: Test(),
),
);
}
}
class Test extends StatefulWidget {
@override
_TestState createState() => _TestState();
}
enum dragType { vertical, horizontal }
class _TestState extends State<Test> {
final double _btnSize = 48.0;
final double _rightPadding = 0;
double _extraOffcet = 0;
double _btnY;
double _currentX;
double _currentY;
double _height;
double _width;
bool _isHorizontalActive = true;
bool _isVerticalActive = true;
@override
void initState() {
WidgetsBinding.instance.addPostFrameCallback(_afterLayout);
super.initState();
}
_afterLayout(_) {
_height = MediaQuery.of(context).size.height;
_width = MediaQuery.of(context).size.width;
_btnY = _height / 2;
setState(() {});
}
_onDrag(details) {
_updateCoordinates(
details.globalPosition.dx,
details.globalPosition.dy,
);
}
_updateCoordinates(double x, double y) {
setState(() {
if (_isHorizontalActive) {
_updateX(x);
}
if (_isVerticalActive) {
_updateY(y);
}
});
}
_updateX(x) {
var dx = _currentX - x;
_currentX = x;
_extraOffcet = _extraOffcet + dx;
_extraOffcet = math.max(_extraOffcet, _rightPadding);
_extraOffcet = math.min(_extraOffcet, _width - _btnSize);
}
_updateY(y) {
var dy = _currentY - y;
_currentY = y;
_btnY = _btnY - dy;
_btnY = math.max(_btnY, _btnSize);
_btnY = math.min(_btnY, _height - _btnSize);
}
_listItem(String text, double height) {
return Container(
height: height,
child: Text(text, style: TextStyle(fontSize: 20.0)),
);
}
@override
Widget build(BuildContext context) {
return _height == null
? Container()
: Stack(
children: <Widget>[
Container(
padding: EdgeInsets.only(right: 30),
color: Colors.blue,
height: double.infinity,
width: double.infinity,
child: Column(mainAxisAlignment: MainAxisAlignment.center, children: [
_buildSwitch(type: dragType.vertical),
_buildSwitch(type: dragType.horizontal),
...List.generate(
4,
(index) => _listItem('inside', 80),
),
]),
),
Positioned(
right: _extraOffcet + _rightPadding,
child: CustomPaint(
size: Size(_btnSize, _height),
painter: CurvedPainter(_btnSize, _btnY),
),
),
Positioned(
top: _btnY - _btnSize / 2 + 5,
right: _extraOffcet + _rightPadding + 5,
child: GestureDetector(
onPanDown: (details) {
_currentX = details.globalPosition.dx;
_currentY = details.globalPosition.dy;
},
onPanStart: _onDrag,
onPanUpdate: _onDrag,
child: Material(
type: MaterialType.circle,
color: Colors.white,
elevation: 8.0,
child: Container(
width: _btnSize - 10,
height: _btnSize - 10,
child: Icon(Icons.add),
),
),
),
),
Positioned(
top: 0,
left: _width - _extraOffcet,
child: Container(
color: Colors.white,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
children: List.generate(8, (index) => _listItem('from right', 20)),
),
height: _height,
width: _width,
),
),
],
);
}
SwitchListTile _buildSwitch({dragType type}) {
Function onChange;
String titleText, sutitleText;
bool value;
if (type == dragType.horizontal) {
value = _isHorizontalActive;
titleText = 'Horizontal dragging';
onChange = (newValue) => setState(() => _isHorizontalActive = newValue);
} else {
value = _isVerticalActive;
titleText = 'Vertical dragging';
onChange = (newValue) => setState(() => _isVerticalActive = newValue);
}
sutitleText = value ? 'active' : 'disabled';
return SwitchListTile(
value: value,
onChanged: onChange,
title: Text(titleText),
subtitle: Text(sutitleText),
);
}
}
class CurvedPainter extends CustomPainter {
CurvedPainter(this.btnSize, this.btnY);
final double btnSize;
final double btnY;
@override
void paint(Canvas canvas, Size size) {
var halfBtnSize = btnSize / 2;
var xMax = size.width;
var yMax = size.height;
var path = Path()
..moveTo(halfBtnSize, yMax)
..lineTo(halfBtnSize, btnY + halfBtnSize * 2)
..cubicTo(halfBtnSize, btnY + halfBtnSize, 0, btnY + halfBtnSize, 0, btnY)
..cubicTo(0, btnY - halfBtnSize, halfBtnSize, btnY - halfBtnSize, halfBtnSize,
btnY - halfBtnSize * 2)
..lineTo(halfBtnSize, 0)
..lineTo(xMax, 0)
..lineTo(xMax, yMax);
canvas.drawPath(
path,
Paint()
..color = Colors.white
..style = PaintingStyle.fill);
}
@override
bool shouldRepaint(CurvedPainter oldDelegate) => oldDelegate.btnY != btnY;
}
这篇关于颤动设计曲线布局作为单个小部件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!