Since the standard (swipeable) ListTile has significant limitations, I'm currently trying to create a CustomWidget myself.
If I use the type “Widget” as the child variable, everything works. However, I can then only select icons as content in the editor.
When I change the child variable on WidgetBuilder, an empty error dialog comes up without any information, just that there was an error!?! (see image)
What else could I try? You can find my code at the bottom ...
Here are a few more thoughts about FlutterFlow:
FlutterFlow is actually a brilliant product! But how can it be that such fundamentally important things as a ListTile were designed so spartanly and even after 2 years there was still no update
that ensures that you can use this component? So it's junk and should only be used for small tests, and definitely not in an app that you want to pass on to a customer.
No arbitrary content possible, only titles and subtitles
The text hangs just below the icon, vertical distance cannot be adjusted.
If you then think: "I'll just leave out the text, just an icon!" then the icon hangs somewhere at the top, there is free space where the text was.
Of course, centering the icon or setting a margin isn't possible either. Icon size not at all ...
The ListTile opens when you swipe, but you can also close it again by swiping back.
But not with Actions, there is no "IsSwipeOpen true/false"
Why not? A decent developer could do that in 10 minutes max? ...If I open an item for deletion and select another item in the ListView, the previously selected one naturally remains open.
If you do this a few times it looks incredibly chic! (Just kidding, that looks pathetic).If there was only one property "IsOpen" I could close it myself in an action, but none of the FF developers want that, too much convenience for the user?
.
.
.
.
Here my code:
.
.
.
// Automatic FlutterFlow imports
import '/backend/schema/structs/index.dart';
import '/flutter_flow/flutter_flow_theme.dart';
import '/flutter_flow/flutter_flow_util.dart';
import '/custom_code/widgets/index.dart'; // Imports other custom widgets
import '/custom_code/actions/index.dart'; // Imports custom actions
import '/flutter_flow/custom_functions.dart'; // Imports custom functions
import 'package:flutter/material.dart';
// Begin custom widget code
// DO NOT REMOVE OR MODIFY THE CODE ABOVE!
import 'package:flutter_slidable/flutter_slidable.dart';
class ExpandableSwipeItem extends StatefulWidget {
const ExpandableSwipeItem({
Key? key,
this.width,
this.height,
this.title,
this.child,
}) : super(key: key);
final double? width;
final double? height;
final String? title;
final WidgetBuilder? child;
@override
State<ExpandableSwipeItem> createState() => _ExpandableSwipeItemState();
}
class _ExpandableSwipeItemState extends State<ExpandableSwipeItem>
with TickerProviderStateMixin {
bool _isExpanded = false;
@override
Widget build(BuildContext context) {
return SizedBox(
width: widget.width ?? double.infinity,
child: Slidable(
key: ValueKey(widget.title),
endActionPane: ActionPane(
motion: const DrawerMotion(),
children: [
SlidableAction(
onPressed: (context) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('${widget.title} deleted')),
);
},
icon: Icons.delete,
label: 'Delete',
backgroundColor: Colors.red,
foregroundColor: Colors.white,
),
],
),
child: GestureDetector(
onLongPress: () => setState(() => isExpanded = !isExpanded),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Container(
padding: const EdgeInsets.all(16),
decoration: BoxDecoration(
color: Theme.of(context).colorScheme.surfaceVariant,
borderRadius: BorderRadius.circular(12),
),
child: Row(
children: [
Expanded(
child: Text(
widget.title ?? '',
style: Theme.of(context).textTheme.titleMedium,
),
),
Icon(
isExpanded ? Icons.expandless : Icons.expand_more,
color: Theme.of(context).colorScheme.onSurfaceVariant,
),
],
),
),
AnimatedSize(
duration: const Duration(milliseconds: 300),
curve: Curves.easeInOut,
child: _isExpanded
? Padding(
padding: const EdgeInsets.only(top: 8),
child: widget.child?.call(context) ??
const SizedBox.shrink(),
)
: const SizedBox.shrink(),
),
],
),
),
),
);
}
}