在 Flutter 中创建带有堆叠列表项的 ListView
Creating A ListView With Stacked List Items in Flutter
我在运球中偶然发现了这个设计
并尝试在 flutter 中实现它,我能够使用 clip Path 创建曲线。这就是我的
我正在尝试去除形状之间的 space 以便它们可以折叠。
这是我的 CurvedRectangleClipper:`
导入 'package:flutter/material.dart';
class CurvedRectangleClipper extends CustomClipper<Path> {
final double offset = 80;
@override
Path getClip(Size size) {
// TODO: implement getClip
Path path = Path();
path.lineTo(0, size.height - offset);
var firstEndpoint = Offset(offset, size.height);
path.arcToPoint(firstEndpoint, radius: Radius.circular(-offset),clockwise: false);
path.lineTo(size.width, size.height);
path.lineTo(size.width, offset);
path.lineTo(offset, offset);
var secondEndPoint = Offset(0,0);
path.arcToPoint(secondEndPoint, radius: Radius.circular(-offset),clockwise: true);
path.lineTo(0, 0);
path.close();
return path;
}
@override
bool shouldReclip(CustomClipper oldClipper) {
// TODO: implement shouldReclip
return true;
}
}
and this is my main.dart file:
导入 'package:devotion/CurvedRectangleClipper.dart';
导入 'package:flutter/material.dart';
void main() {
runApp(HomeScreen());
}
class HomeScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: MainScreen(),
title: 'Devotion',
theme: appTheme,
);
}
}
var appTheme =
ThemeData(fontFamily: 'Oxygen', primaryColor: Colors.purpleAccent);
class MainScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Devotion'),
),
body: ListView(
scrollDirection: Axis.vertical,
children: <Widget>[
CurvedListItem(
title: 'Yoga and Meditation for Beginners',
time: 'TODAY 5:30 PM'),
CurvedListItem(
title: 'Practice French, English And Chinese',
time: 'TUESDAY 5:30 PM',
),
CurvedListItem(
title: 'Adobe XD Live Event in Europe',
time: 'FRIDAY 6:00 PM',
),
],
),
);
}
}
class CurvedListItem extends StatelessWidget {
final String title;
final String time;
final String people;
final IconData icon;
CurvedListItem({this.title, this.time, this.icon, this.people});
@override
Widget build(BuildContext context) {
return ClipPath(
clipper: CurvedRectangleClipper(),
child: Container(
color: Colors.pink,
padding: EdgeInsets.only(
left: 32,
top: 100,
bottom: 50,
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
time,
style: TextStyle(color: Colors.white, fontSize: 12),
),
SizedBox(
height: 2,
),
Text(
title,
style: TextStyle(
color: Colors.white,
fontSize: 22,
fontWeight: FontWeight.bold),
),
Row(),
]),
),
);
}
}
`
我想如果物品彼此放置,则不需要顶部曲线,但我将其留在那里以了解实际形状。
也欢迎指正和评论。提前致谢。
AFAIK,您无法摆脱剪辑小部件之间的 space。您可以采用一种简单且不同的方法来解决此问题。
我会这样做:
void main() {
runApp(HomeScreen());
}
class HomeScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: MainScreen(),
title: 'Devotion',
theme: appTheme,
);
}
}
ThemeData appTheme = ThemeData(
fontFamily: 'Oxygen',
primaryColor: Colors.purpleAccent,
);
class MainScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Devotion'),
),
body: ListView(
scrollDirection: Axis.vertical,
children: <Widget>[
CurvedListItem(
title: 'Yoga and Meditation for Beginners',
time: 'TODAY 5:30 PM',
color: Colors.red,
nextColor: Colors.green,
),
CurvedListItem(
title: 'Practice French, English And Chinese',
time: 'TUESDAY 5:30 PM',
color: Colors.green,
nextColor: Colors.yellow,
),
CurvedListItem(
title: 'Adobe XD Live Event in Europe',
time: 'FRIDAY 6:00 PM',
color: Colors.yellow,
),
],
),
);
}
}
class CurvedListItem extends StatelessWidget {
const CurvedListItem({
this.title,
this.time,
this.icon,
this.people,
this.color,
this.nextColor,
});
final String title;
final String time;
final String people;
final IconData icon;
final Color color;
final Color nextColor;
@override
Widget build(BuildContext context) {
return Container(
color: nextColor,
child: Container(
decoration: BoxDecoration(
color: color,
borderRadius: const BorderRadius.only(
bottomLeft: Radius.circular(80.0),
),
),
padding: const EdgeInsets.only(
left: 32,
top: 80.0,
bottom: 50,
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
time,
style: TextStyle(color: Colors.white, fontSize: 12),
),
const SizedBox(
height: 2,
),
Text(
title,
style: TextStyle(
color: Colors.white,
fontSize: 22,
fontWeight: FontWeight.bold),
),
Row(),
]),
),
);
}
}
注意:我不认为它是最佳的,但仍然简单明了。
希望对您有所帮助!
使用对齐并设置 heightFactor: 0.75 和 alignment: Alignment.topCenter,
ListView(
children: [
Align(
heightFactor: 0.75,
alignment: Alignment.topCenter,
child: CurvedListItem(
title: 'Yoga and Meditation for Beginners',
time: 'TODAY 5:30 PM',
),
),
Align(
heightFactor: 0.75,
alignment: Alignment.topCenter,
child: CurvedListItem(
title: 'Practice French, English And Chinese',
time: 'TUESDAY 5:30 PM',
),
),
Align(
heightFactor: 0.75,
alignment: Alignment.topCenter,
child: CurvedListItem(
title: 'Adobe XD Live Event in Europe',
time: 'FRIDAY 6:00 PM',
),
)
],
);
我在运球中偶然发现了这个设计
并尝试在 flutter 中实现它,我能够使用 clip Path 创建曲线。这就是我的
我正在尝试去除形状之间的 space 以便它们可以折叠。
这是我的 CurvedRectangleClipper:` 导入 'package:flutter/material.dart';
class CurvedRectangleClipper extends CustomClipper<Path> {
final double offset = 80;
@override
Path getClip(Size size) {
// TODO: implement getClip
Path path = Path();
path.lineTo(0, size.height - offset);
var firstEndpoint = Offset(offset, size.height);
path.arcToPoint(firstEndpoint, radius: Radius.circular(-offset),clockwise: false);
path.lineTo(size.width, size.height);
path.lineTo(size.width, offset);
path.lineTo(offset, offset);
var secondEndPoint = Offset(0,0);
path.arcToPoint(secondEndPoint, radius: Radius.circular(-offset),clockwise: true);
path.lineTo(0, 0);
path.close();
return path;
}
@override
bool shouldReclip(CustomClipper oldClipper) {
// TODO: implement shouldReclip
return true;
}
}
and this is my main.dart file:
导入 'package:devotion/CurvedRectangleClipper.dart';
导入 'package:flutter/material.dart';
void main() {
runApp(HomeScreen());
}
class HomeScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: MainScreen(),
title: 'Devotion',
theme: appTheme,
);
}
}
var appTheme =
ThemeData(fontFamily: 'Oxygen', primaryColor: Colors.purpleAccent);
class MainScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Devotion'),
),
body: ListView(
scrollDirection: Axis.vertical,
children: <Widget>[
CurvedListItem(
title: 'Yoga and Meditation for Beginners',
time: 'TODAY 5:30 PM'),
CurvedListItem(
title: 'Practice French, English And Chinese',
time: 'TUESDAY 5:30 PM',
),
CurvedListItem(
title: 'Adobe XD Live Event in Europe',
time: 'FRIDAY 6:00 PM',
),
],
),
);
}
}
class CurvedListItem extends StatelessWidget {
final String title;
final String time;
final String people;
final IconData icon;
CurvedListItem({this.title, this.time, this.icon, this.people});
@override
Widget build(BuildContext context) {
return ClipPath(
clipper: CurvedRectangleClipper(),
child: Container(
color: Colors.pink,
padding: EdgeInsets.only(
left: 32,
top: 100,
bottom: 50,
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
time,
style: TextStyle(color: Colors.white, fontSize: 12),
),
SizedBox(
height: 2,
),
Text(
title,
style: TextStyle(
color: Colors.white,
fontSize: 22,
fontWeight: FontWeight.bold),
),
Row(),
]),
),
);
}
}
` 我想如果物品彼此放置,则不需要顶部曲线,但我将其留在那里以了解实际形状。 也欢迎指正和评论。提前致谢。
AFAIK,您无法摆脱剪辑小部件之间的 space。您可以采用一种简单且不同的方法来解决此问题。
我会这样做:
void main() {
runApp(HomeScreen());
}
class HomeScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: MainScreen(),
title: 'Devotion',
theme: appTheme,
);
}
}
ThemeData appTheme = ThemeData(
fontFamily: 'Oxygen',
primaryColor: Colors.purpleAccent,
);
class MainScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Devotion'),
),
body: ListView(
scrollDirection: Axis.vertical,
children: <Widget>[
CurvedListItem(
title: 'Yoga and Meditation for Beginners',
time: 'TODAY 5:30 PM',
color: Colors.red,
nextColor: Colors.green,
),
CurvedListItem(
title: 'Practice French, English And Chinese',
time: 'TUESDAY 5:30 PM',
color: Colors.green,
nextColor: Colors.yellow,
),
CurvedListItem(
title: 'Adobe XD Live Event in Europe',
time: 'FRIDAY 6:00 PM',
color: Colors.yellow,
),
],
),
);
}
}
class CurvedListItem extends StatelessWidget {
const CurvedListItem({
this.title,
this.time,
this.icon,
this.people,
this.color,
this.nextColor,
});
final String title;
final String time;
final String people;
final IconData icon;
final Color color;
final Color nextColor;
@override
Widget build(BuildContext context) {
return Container(
color: nextColor,
child: Container(
decoration: BoxDecoration(
color: color,
borderRadius: const BorderRadius.only(
bottomLeft: Radius.circular(80.0),
),
),
padding: const EdgeInsets.only(
left: 32,
top: 80.0,
bottom: 50,
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
time,
style: TextStyle(color: Colors.white, fontSize: 12),
),
const SizedBox(
height: 2,
),
Text(
title,
style: TextStyle(
color: Colors.white,
fontSize: 22,
fontWeight: FontWeight.bold),
),
Row(),
]),
),
);
}
}
注意:我不认为它是最佳的,但仍然简单明了。
希望对您有所帮助!
使用对齐并设置 heightFactor: 0.75 和 alignment: Alignment.topCenter,
ListView(
children: [
Align(
heightFactor: 0.75,
alignment: Alignment.topCenter,
child: CurvedListItem(
title: 'Yoga and Meditation for Beginners',
time: 'TODAY 5:30 PM',
),
),
Align(
heightFactor: 0.75,
alignment: Alignment.topCenter,
child: CurvedListItem(
title: 'Practice French, English And Chinese',
time: 'TUESDAY 5:30 PM',
),
),
Align(
heightFactor: 0.75,
alignment: Alignment.topCenter,
child: CurvedListItem(
title: 'Adobe XD Live Event in Europe',
time: 'FRIDAY 6:00 PM',
),
)
],
);