Anonymous
Как анимировать draggableScrollableSheet и его содержимое во флаттере?
Сообщение
Anonymous » 29 май 2024, 16:45
Я пытаюсь эмулировать этот нижний лист из приложения «Найти мой» на iOS.
Я использовал draggableScrollableSheet, но он работает не так хорошо, как тот, который находится в «Найти мой». .
Код: Выделить всё
class DraggableSheet extends StatefulWidget {
final Widget child;
final String title;
const DraggableSheet({super.key, required this.child, required this.title});
@override
State createState() => _DraggableSheetState();
}
class _DraggableSheetState extends State {
final sheet = GlobalKey();
final controller = DraggableScrollableController();
@override
void initState() {
super.initState();
controller.addListener(onChanged);
}
void onChanged() {
final currentSize = controller.size;
if (currentSize animateSheet(getSheet.snapSizes!.first);
void anchor() => animateSheet(getSheet.snapSizes!.last);
void expand() => animateSheet(getSheet.maxChildSize);
void hide() => animateSheet(getSheet.minChildSize);
void animateSheet(double size) {
controller.animateTo(
size,
duration: const Duration(milliseconds: 100),
curve: Curves.easeIn,
);
}
@override
void dispose() {
super.dispose();
controller.dispose();
}
DraggableScrollableSheet get getSheet =>
(sheet.currentWidget as DraggableScrollableSheet);
@override
Widget build(BuildContext context) {
return LayoutBuilder(builder: (context, constraints) {
return DraggableScrollableSheet(
key: sheet,
snapAnimationDuration: const Duration(milliseconds: 100),
initialChildSize: 0.157,
maxChildSize: 0.93,
minChildSize: 0,
expand: true,
snap: true,
snapSizes: const [
0.157,
0.4,
0.93,
],
controller: controller,
builder: (BuildContext context, ScrollController scrollController) {
return DecoratedBox(
decoration: BoxDecoration(
color: CupertinoTheme.of(context).scaffoldBackgroundColor,
boxShadow: const [
BoxShadow(
color: Colors.black12,
blurRadius: 10,
spreadRadius: 1,
offset: Offset(0, 1),
),
],
borderRadius: const BorderRadius.only(
topLeft: Radius.circular(10),
topRight: Radius.circular(10),
),
),
child: CustomScrollView(
controller: scrollController,
slivers: [
BottomSheetHeader(title: widget.title),
SliverToBoxAdapter(
child: widget.child,
),
],
),
);
},
);
});
}
}
В нем отсутствует анимация привязки отскока, и я не мог понять, как они отображают такие кнопки, как «Добавить элементы», при первом щелчке (до ~ половины экрана), а затем разворачиваются. от корпуса (оставляя кнопки внизу).
Код: Выделить всё
class BottomSheetHeader extends StatelessWidget {
final String title;
const BottomSheetHeader({super.key, required this.title});
@override
Widget build(BuildContext context) {
return SliverPersistentHeader(
pinned: true,
delegate: SliverAppBarDelegate(
minHeight: 52,
maxHeight: 52,
child: Container(
decoration: BoxDecoration(
color: CupertinoTheme.of(context).scaffoldBackgroundColor,
),
child: Column(
children: [
Center(
child: Wrap(
children: [
Container(
width: 36,
margin: const EdgeInsets.only(top: 4, bottom: 4),
height: 5,
decoration: const BoxDecoration(
color: Colors.black26,
shape: BoxShape.rectangle,
borderRadius: BorderRadius.all(Radius.circular(8.0)),
),
),
],
),
),
Row(
children: [
Padding(
padding: const EdgeInsets.symmetric(horizontal: 20.0),
child: Text(
title,
style: const TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold,
),
),
),
],
),
const SizedBox(height: 8.0),
const Divider(
height: 0,
),
],
),
),
),
);
}
}
class SliverAppBarDelegate extends SliverPersistentHeaderDelegate {
SliverAppBarDelegate({
required this.minHeight,
required this.maxHeight,
required this.child,
});
final double minHeight;
final double maxHeight;
final Widget child;
@override
double get minExtent => minHeight;
@override
double get maxExtent => max(maxHeight, minHeight);
@override
Widget build(
BuildContext context, double shrinkOffset, bool overlapsContent) {
return SizedBox.expand(child: child);
}
@override
bool shouldRebuild(SliverAppBarDelegate oldDelegate) {
return maxHeight != oldDelegate.maxHeight ||
minHeight != oldDelegate.minHeight ||
child != oldDelegate.child;
}
}
Есть ли лучший способ сделать это?
Подробнее здесь:
https://stackoverflow.com/questions/785 ... in-flutter
1716990315
Anonymous
[img]https://i.sstatic.net/QsuDvDDn.gif[/img] Я пытаюсь эмулировать этот нижний лист из приложения «Найти мой» на iOS. Я использовал draggableScrollableSheet, но он работает не так хорошо, как тот, который находится в «Найти мой». . [code] class DraggableSheet extends StatefulWidget { final Widget child; final String title; const DraggableSheet({super.key, required this.child, required this.title}); @override State createState() => _DraggableSheetState(); } class _DraggableSheetState extends State { final sheet = GlobalKey(); final controller = DraggableScrollableController(); @override void initState() { super.initState(); controller.addListener(onChanged); } void onChanged() { final currentSize = controller.size; if (currentSize animateSheet(getSheet.snapSizes!.first); void anchor() => animateSheet(getSheet.snapSizes!.last); void expand() => animateSheet(getSheet.maxChildSize); void hide() => animateSheet(getSheet.minChildSize); void animateSheet(double size) { controller.animateTo( size, duration: const Duration(milliseconds: 100), curve: Curves.easeIn, ); } @override void dispose() { super.dispose(); controller.dispose(); } DraggableScrollableSheet get getSheet => (sheet.currentWidget as DraggableScrollableSheet); @override Widget build(BuildContext context) { return LayoutBuilder(builder: (context, constraints) { return DraggableScrollableSheet( key: sheet, snapAnimationDuration: const Duration(milliseconds: 100), initialChildSize: 0.157, maxChildSize: 0.93, minChildSize: 0, expand: true, snap: true, snapSizes: const [ 0.157, 0.4, 0.93, ], controller: controller, builder: (BuildContext context, ScrollController scrollController) { return DecoratedBox( decoration: BoxDecoration( color: CupertinoTheme.of(context).scaffoldBackgroundColor, boxShadow: const [ BoxShadow( color: Colors.black12, blurRadius: 10, spreadRadius: 1, offset: Offset(0, 1), ), ], borderRadius: const BorderRadius.only( topLeft: Radius.circular(10), topRight: Radius.circular(10), ), ), child: CustomScrollView( controller: scrollController, slivers: [ BottomSheetHeader(title: widget.title), SliverToBoxAdapter( child: widget.child, ), ], ), ); }, ); }); } } [/code] В нем отсутствует анимация привязки отскока, и я не мог понять, как они отображают такие кнопки, как «Добавить элементы», при первом щелчке (до ~ половины экрана), а затем разворачиваются. от корпуса (оставляя кнопки внизу). [code]BottomSheetHeader[/code] [code]class BottomSheetHeader extends StatelessWidget { final String title; const BottomSheetHeader({super.key, required this.title}); @override Widget build(BuildContext context) { return SliverPersistentHeader( pinned: true, delegate: SliverAppBarDelegate( minHeight: 52, maxHeight: 52, child: Container( decoration: BoxDecoration( color: CupertinoTheme.of(context).scaffoldBackgroundColor, ), child: Column( children: [ Center( child: Wrap( children: [ Container( width: 36, margin: const EdgeInsets.only(top: 4, bottom: 4), height: 5, decoration: const BoxDecoration( color: Colors.black26, shape: BoxShape.rectangle, borderRadius: BorderRadius.all(Radius.circular(8.0)), ), ), ], ), ), Row( children: [ Padding( padding: const EdgeInsets.symmetric(horizontal: 20.0), child: Text( title, style: const TextStyle( fontSize: 20, fontWeight: FontWeight.bold, ), ), ), ], ), const SizedBox(height: 8.0), const Divider( height: 0, ), ], ), ), ), ); } } class SliverAppBarDelegate extends SliverPersistentHeaderDelegate { SliverAppBarDelegate({ required this.minHeight, required this.maxHeight, required this.child, }); final double minHeight; final double maxHeight; final Widget child; @override double get minExtent => minHeight; @override double get maxExtent => max(maxHeight, minHeight); @override Widget build( BuildContext context, double shrinkOffset, bool overlapsContent) { return SizedBox.expand(child: child); } @override bool shouldRebuild(SliverAppBarDelegate oldDelegate) { return maxHeight != oldDelegate.maxHeight || minHeight != oldDelegate.minHeight || child != oldDelegate.child; } } [/code] Есть ли лучший способ сделать это? Подробнее здесь: [url]https://stackoverflow.com/questions/78549934/how-to-animate-draggablescrollablesheet-and-its-contents-in-flutter[/url]