我一直在摸索很长一段时间,只是为了获得这种类型的 TextFormField 设计布局,但失败了!
注意反海峡线。我在 Internet 上对该布局的进一步搜索得出的结论是,我可以使用自定义剪辑器或剪辑路径来归档这种类型的布局。但我只是一个学习颤振的初学者,以前从未使用过自定义剪裁器,我不知道如何使用它。请帮忙。
我一直在摸索很长一段时间,只是为了获得这种类型的 TextFormField 设计布局,但失败了!
注意反海峡线。我在 Internet 上对该布局的进一步搜索得出的结论是,我可以使用自定义剪辑器或剪辑路径来归档这种类型的布局。但我只是一个学习颤振的初学者,以前从未使用过自定义剪裁器,我不知道如何使用它。请帮忙。
我认为您可以使用 CustomPainter :
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData.dark().copyWith(
scaffoldBackgroundColor: darkBlue,
),
debugShowCheckedModeBanner: false,
home: Scaffold(
body: Center(
child: CustomPaint(
painter: MyPainter(),
child: // your TextField with style so we don't see the borders etc...
),
),
),
);
}
}
class MyPainter extends CustomPainter {
@override
void paint(Canvas canvas, Size size) {
// draw your rectangle from points here
}
// no need to repaint it because your shape is static
@override
bool shouldRepaint(Sky oldDelegate) => false;
@override
bool shouldRebuildSemantics(Sky oldDelegate) => false;
}
这是 CustomPainter 基础知识的链接:link
这是带有显示 TextField 的小部件的书面代码,当然还有您的自定义形状:
class MainScreen extends StatefulWidget {
@override
_MainScreenState createState() => _MainScreenState();
}
class _MainScreenState extends State<MainScreen> {
// implementation of your custom active borders
bool emailActive = false;
FocusNode? emailNode;
@override
void initState() {
super.initState();
emailNode = FocusScopeNode()
..addListener(() {
setState(() {
emailActive = emailNode!.hasFocus;
});
print(emailActive);
});
}
@override
Widget build(BuildContext context) {
final Size size = MediaQuery.of(context).size;
final double width = size.width * 0.8;
final double height = width * 0.15;
return Scaffold(
appBar: AppBar(
title: Text('First screen'),
),
body: Center(
child: Container(
height: height,
width: width,
child: Stack(
children: [
Center(
// your shape
child: CustomPaint(
painter: _TextFieldPainter(width, height, emailActive),
),
),
Container(
height: height,
width: width,
padding: const EdgeInsets.symmetric(horizontal: 10.0),
child: Row(
children: [
Container(
width: 35,
padding: const EdgeInsets.only(
top: 5.0), // so it's aligned with the textfield
child: Icon(Icons.email_rounded),
),
Container(
width: width - 35 - 20, // width - iconSize - padding
child: TextField(
decoration: InputDecoration(
hintText: 'Email id',
focusedBorder: InputBorder
.none, // so there is no border below the text field
),
focusNode: emailNode,
),
),
],
),
),
],
),
),
),
);
}
}
class _TextFieldPainter extends CustomPainter {
final double width;
final double height;
final bool active;
_TextFieldPainter(this.width, this.height, this.active);
@override
void paint(Canvas canvas, Size size) {
// The starting values so it's centered properly
final double startX = width / -2;
final double startY = height / -2;
// Where you set the color etc...
final Paint paint = Paint()
..color = active
? Colors.green
: Colors.black // where you change the color wether it's active or not
..strokeWidth = 1.0;
// Drawing the shape
canvas.drawLine(
Offset(startX, startY + 5.0), Offset(startX + width, startY), paint);
canvas.drawLine(Offset(startX + width, startY),
Offset(startX + width, startY + height), paint);
canvas.drawLine(Offset(startX + width, startY + height),
Offset(startX - 5.0, startY + height), paint);
canvas.drawLine(Offset(startX - 5.0, startY + height),
Offset(startX, startY + 5.0), paint);
}
// no need to repaint it here since there is no dynamic values
@override
bool shouldRepaint(_TextFieldPainter oldDelegate) => false;
@override
bool shouldRebuildSemantics(_TextFieldPainter oldDelegate) => false;
}
您只需对密码 TextField 执行相同操作即可。
这是它的外观: