一个带自动下滑的菜单,共有3个layer, 在往下滑动的时候,中间图层会慢慢融化掉。
import 'package:flutter/material.dart';
void main(List<String> args) {
runApp(const MaterialApp(
home: HomePage(),
));
}
class HomePage extends StatefulWidget {
const HomePage({super.key});
@override
State<HomePage> createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
@override
Widget build(BuildContext context) {
return const Scaffold(
body: LayerWidget(),
);
}
}
class LayerWidget extends StatefulWidget {
const LayerWidget({super.key});
@override
State<LayerWidget> createState() => _LayerWidgetState();
}
class DropdownMenuClipper extends CustomClipper<Rect> {
late double startPos;
DropdownMenuClipper(this.startPos);
@override
Rect getClip(Size size) {
return Rect.fromLTRB(0, startPos, size.width, size.height);
}
@override
bool shouldReclip(covariant CustomClipper<Rect> oldClipper) {
return this != oldClipper;
}
}
class _LayerWidgetState extends State<LayerWidget> {
bool move = false; // 是否已经按下
double y = 0; // 滑动距离
bool down = false; // 是否越过中线,如果已经越过中线,则本次滑动认为已经可以自动滑到底部
void releaseDropAction() {
move = false;
if (down) {
setState(() {
y = 700;
});
} else {
setState(() {
y = 0;
});
}
}
@override
Widget build(BuildContext context) {
return Container(
constraints: const BoxConstraints.tightFor(width: 1280, height: 720),
child: Stack(
fit: StackFit.expand,
children: [
// background
Container(
constraints: const BoxConstraints.expand(),
child: ListView.builder(
itemBuilder: (context, index) {
return Container(
alignment: Alignment.centerRight,
height: 30,
color: Colors.primaries[index % Colors.primaries.length]
.withOpacity(0.8),
child: Text(
"BACKGROUND -- $index -- BACKGROUND",
style: const TextStyle(color: Colors.white60),
),
);
},
),
),
// middle layer
Container(
constraints:
const BoxConstraints.tightFor(width: 1280, height: 720),
child: ClipRect(
clipper: DropdownMenuClipper(y),
child: Opacity(
opacity: 0.6,
child: Image.network(
"https://ts1.cn.mm.bing.net/th/id/R-C.e51b145d53c430c25c12f6f85bf948a2?rik=InKJPw4ksMoeMw&riu=http%3a%2f%2fwallpaperping.com%2fwp-content%2fuploads%2f2018%2f12%2fBluebirdTotemMeaning.jpg&ehk=NSr%2bPl1FfAgYVt%2fBU4xF%2fsd0p8%2fm6SuScV%2fN59zvKwI%3d&risl=&pid=ImgRaw&r=0",
fit: BoxFit.fitWidth,
),
),
),
),
//uplayer
Positioned(
top: -700 + y,
child: GestureDetector(
onPanDown: (details) => move = true,
onPanCancel: () => releaseDropAction(),
onPanEnd: (_) => releaseDropAction(),
onPanUpdate: (details) {
setState(() {
y = y + details.delta.dy;
if (y > 720) {
y = 720;
}
if (y > 720 / 2) {
down = true;
} else {
down = false;
}
});
},
child: Container(
constraints:
const BoxConstraints.tightFor(width: 1280, height: 720),
child: ListView.builder(
itemBuilder: (context, index) {
return ListTile(
title: Center(
child: Text("UPPER_LAYER -- $index -- UPPER_LAYER"),
),
);
},
itemCount: 200,
),
),
),
)
],
),
);
}
}