我正在尝试创建一个需要大小参数的可调整大小的小部件。我想根据它的子尺寸使高度和宽度字段动态化,这样我们就不必给出小部件的静态尺寸。请帮帮我!
注意:请通过采用高度和宽度参数的 ResizebleWidget 类。我想根据它的子部件大小使这些参数动态化
import 'package:flutter/material.dart';
class ResizeWidget extends StatefulWidget {
@override
_ResizeWidgetState createState() => _ResizeWidgetState();
}
class _ResizeWidgetState extends State<ResizeWidget> {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
backgroundColor: Colors.black,
body: Container(
// padding: EdgeInsets.only(top: 50),
child: ResizebleWidget(
child: Container(
padding: EdgeInsets.all(10),
child: Text(
'Waao!! you can really dance.',
style: TextStyle(
color: Colors.white,
fontStyle: FontStyle.italic,
fontSize: 18),
),
),
),
),
),
);
}
}
**HOW to create this ResizebleWidget size dynamic according to its children**
class ResizebleWidget extends StatefulWidget {
ResizebleWidget({this.child});
final Widget child;
@override
_ResizebleWidgetState createState() => _ResizebleWidgetState();
}
const ballDiameter = 10.0;
class _ResizebleWidgetState extends State<ResizebleWidget> {
double height = 100;
double width = 200;
bool isCorner = false;
double top = 0;
double left = 0;
@override
Widget build(BuildContext context) {
return Stack(
children: <Widget>[
Positioned(
top: top,
left: left,
child: Container(
height: height,
width: width,
decoration: BoxDecoration(
color: Colors.blueGrey,
border: Border.all(
width: 2,
color: Colors.white70,
),
borderRadius: BorderRadius.circular(0.0),
),
// need tp check if draggable is done from corner or sides
child: isCorner
? FittedBox(
child: widget.child,
)
: Center(
child: widget.child,
),
),
),
// top left
Positioned(
top: top - ballDiameter / 2,
left: left - ballDiameter / 2,
child: ManipulatingBall(
onDrag: (dx, dy) {
var mid = (dx + dy) / 2;
var newHeight = height - 2 * mid;
var newWidth = width - 2 * mid;
setState(() {
isCorner = true;
height = newHeight > 0 ? newHeight : 0;
width = newWidth > 0 ? newWidth : 0;
top = top + mid;
left = left + mid;
});
},
handlerWidget: HandlerWidget.VERTICAL,
),
),
// top middle
Positioned(
top: top - ballDiameter / 2,
left: left + width / 2 - ballDiameter / 2,
child: ManipulatingBall(
onDrag: (dx, dy) {
var newHeight = height - dy;
setState(() {
isCorner = false;
height = newHeight > 0 ? newHeight : 0;
top = top + dy;
});
},
handlerWidget: HandlerWidget.HORIZONTAL,
),
),
// top right
Positioned(
top: top - ballDiameter / 2,
left: left + width - ballDiameter / 2,
child: ManipulatingBall(
onDrag: (dx, dy) {
var mid = (dx + (dy * -1)) / 2;
var newHeight = height + 2 * mid;
var newWidth = width + 2 * mid;
setState(() {
isCorner = true;
height = newHeight > 0 ? newHeight : 0;
width = newWidth > 0 ? newWidth : 0;
top = top - mid;
left = left - mid;
});
},
handlerWidget: HandlerWidget.VERTICAL,
),
),
// center right
Positioned(
top: top + height / 2 - ballDiameter / 2,
left: left + width - ballDiameter / 2,
child: ManipulatingBall(
onDrag: (dx, dy) {
var newWidth = width + dx;
setState(() {
isCorner = false;
width = newWidth > 0 ? newWidth : 0;
});
},
handlerWidget: HandlerWidget.HORIZONTAL,
),
),
// bottom right
Positioned(
top: top + height - ballDiameter / 2,
left: left + width - ballDiameter / 2,
child: ManipulatingBall(
onDrag: (dx, dy) {
var mid = (dx + dy) / 2;
var newHeight = height + 2 * mid;
var newWidth = width + 2 * mid;
setState(() {
isCorner = true;
height = newHeight > 0 ? newHeight : 0;
width = newWidth > 0 ? newWidth : 0;
top = top - mid;
left = left - mid;
});
},
handlerWidget: HandlerWidget.VERTICAL,
),
),
// bottom center
Positioned(
top: top + height - ballDiameter / 2,
left: left + width / 2 - ballDiameter / 2,
child: ManipulatingBall(
onDrag: (dx, dy) {
var newHeight = height + dy;
setState(() {
isCorner = false;
height = newHeight > 0 ? newHeight : 0;
});
},
handlerWidget: HandlerWidget.HORIZONTAL,
),
),
// bottom left
Positioned(
top: top + height - ballDiameter / 2,
left: left - ballDiameter / 2,
child: ManipulatingBall(
onDrag: (dx, dy) {
var mid = ((dx * -1) + dy) / 2;
var newHeight = height + 2 * mid;
var newWidth = width + 2 * mid;
setState(() {
isCorner = true;
height = newHeight > 0 ? newHeight : 0;
width = newWidth > 0 ? newWidth : 0;
top = top - mid;
left = left - mid;
});
},
handlerWidget: HandlerWidget.VERTICAL,
),
),
//left center
Positioned(
top: top + height / 2 - ballDiameter / 2,
left: left - ballDiameter / 2,
child: ManipulatingBall(
onDrag: (dx, dy) {
var newWidth = width - dx;
setState(() {
isCorner = false;
width = newWidth > 0 ? newWidth : 0;
left = left + dx;
});
},
handlerWidget: HandlerWidget.HORIZONTAL,
),
),
// center center
Positioned(
top: top + height / 2 - ballDiameter / 2,
left: left + width / 2 - ballDiameter / 2,
child: ManipulatingBall(
onDrag: (dx, dy) {
setState(() {
isCorner = false;
top = top + dy;
left = left + dx;
});
},
handlerWidget: HandlerWidget.VERTICAL,
),
),
],
);
}
}
class ManipulatingBall extends StatefulWidget {
ManipulatingBall({Key key, this.onDrag, this.handlerWidget});
final Function onDrag;
final HandlerWidget handlerWidget;
@override
_ManipulatingBallState createState() => _ManipulatingBallState();
}
enum HandlerWidget { HORIZONTAL, VERTICAL }
class _ManipulatingBallState extends State<ManipulatingBall> {
double initX;
double initY;
_handleDrag(details) {
setState(() {
initX = details.globalPosition.dx;
initY = details.globalPosition.dy;
});
}
_handleUpdate(details) {
var dx = details.globalPosition.dx - initX;
var dy = details.globalPosition.dy - initY;
initX = details.globalPosition.dx;
initY = details.globalPosition.dy;
widget.onDrag(dx, dy);
}
@override
Widget build(BuildContext context) {
return GestureDetector(
onPanStart: _handleDrag,
onPanUpdate: _handleUpdate,
child: Container(
width: ballDiameter,
height: ballDiameter,
decoration: BoxDecoration(
color: Colors.white,
shape: this.widget.handlerWidget == HandlerWidget.VERTICAL
? BoxShape.circle
: BoxShape.rectangle,
),
),
);
}
}
答案 0 :(得分:0)
在渲染之前无法确定小部件的大小。但是我可以看到您想知道文本的大小,以便您可以创建自己的小部件。您可以使用 TextPainter
执行此操作。在本示例中,我使用它来创建某种文本容器,借助 CustomPainter
,您可以以任何可能的方式对其进行样式设置。
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatefulWidget {
@override
State<StatefulWidget> createState() {
return _MyAppState();
}
}
class _MyAppState extends State<MyApp> {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
backgroundColor: Colors.white,
body: Center(child: TextContainer()),
),
);
}
}
class TextContainer extends StatelessWidget {
static String text = "TextPainter is amazing!!!!!!!!!!!!!!!!!";
static double padding =
20.0; // in case you want you text container to have padding.
@override
Widget build(BuildContext context) {
// to calculate the size of the text you need to create a TextPainter based on the text and
// its style
final TextPainter textPainter = TextPainter(
textDirection: TextDirection.ltr,
text: TextSpan(
text: text,
style: TextStyle(
color: Colors.white,
fontStyle: FontStyle.italic,
fontSize: 50,
)))
..layout(maxWidth: 300);
// in the layout of the TexPainter you set the maxWidth, layout is required.
return Container(
width: textPainter.width + padding,
height: textPainter.height + padding,
child: CustomPaint(
painter:
TextContainerPainter(textPainter: textPainter, padding: padding),
));
}
}
class TextContainerPainter extends CustomPainter {
TextContainerPainter({required this.textPainter, required this.padding});
final TextPainter textPainter;
final double padding;
@override
void paint(Canvas canvas, Size size) {
// ============================================== Container
final paint = Paint()..color = Colors.greenAccent;
final rect = Offset.zero &
Size(textPainter.width + padding, textPainter.height + padding);
canvas.drawRRect(RRect.fromRectAndRadius(rect, Radius.circular(15)), paint);
// ========================================== TextPainter
textPainter.paint(canvas, Offset(padding / 2, padding / 2));
// this offset is necessary so that the text is at the center of its container
}
@override
bool shouldRepaint(covariant CustomPainter oldDelegate) => true;
}
如下图所示,小部件具有我们指定的文本大小和内边距。