This commit is contained in:
2026-03-29 14:26:48 +03:00
parent 31dc972e52
commit 0020c65d1e
2 changed files with 233 additions and 193 deletions
+30 -8
View File
@@ -37,6 +37,7 @@ class AddTransactionScreen extends ConsumerStatefulWidget {
class _AddTransactionScreenState extends ConsumerState<AddTransactionScreen> class _AddTransactionScreenState extends ConsumerState<AddTransactionScreen>
with SingleTickerProviderStateMixin { with SingleTickerProviderStateMixin {
final _formKey = GlobalKey<FormState>(); final _formKey = GlobalKey<FormState>();
final _stackKey = GlobalKey();
final _amountController = TextEditingController(); final _amountController = TextEditingController();
final _noteController = TextEditingController(); final _noteController = TextEditingController();
final _fromAccountIndicatorKey = GlobalKey(); final _fromAccountIndicatorKey = GlobalKey();
@@ -507,6 +508,7 @@ class _AddTransactionScreenState extends ConsumerState<AddTransactionScreen>
child: Form( child: Form(
key: _formKey, key: _formKey,
child: Stack( child: Stack(
key: _stackKey,
children: [ children: [
ListView( ListView(
padding: const EdgeInsets.all(20), padding: const EdgeInsets.all(20),
@@ -685,6 +687,7 @@ class _AddTransactionScreenState extends ConsumerState<AddTransactionScreen>
onClose: () => onClose: () =>
setState(() => _showFromAccountDropdown = false), setState(() => _showFromAccountDropdown = false),
triggerKey: _fromAccountIndicatorKey, triggerKey: _fromAccountIndicatorKey,
stackKey: _stackKey,
), ),
if (_showToAccountDropdown) if (_showToAccountDropdown)
Positioned.fill( Positioned.fill(
@@ -699,6 +702,7 @@ class _AddTransactionScreenState extends ConsumerState<AddTransactionScreen>
initial: widget.initial, initial: widget.initial,
onClose: () => setState(() => _showToAccountDropdown = false), onClose: () => setState(() => _showToAccountDropdown = false),
triggerKey: _toAccountIndicatorKey, triggerKey: _toAccountIndicatorKey,
stackKey: _stackKey,
), ),
], ],
), ),
@@ -839,11 +843,13 @@ class _ToAccountDropdownOverlay extends ConsumerWidget {
final Transaction? initial; final Transaction? initial;
final VoidCallback onClose; final VoidCallback onClose;
final GlobalKey? triggerKey; final GlobalKey? triggerKey;
final GlobalKey? stackKey;
const _ToAccountDropdownOverlay({ const _ToAccountDropdownOverlay({
required this.initial, required this.initial,
required this.onClose, required this.onClose,
this.triggerKey, this.triggerKey,
this.stackKey,
}); });
@override @override
@@ -857,20 +863,33 @@ class _ToAccountDropdownOverlay extends ConsumerWidget {
// Calculate position from trigger key // Calculate position from trigger key
double top = 340; double top = 340;
double left = 20; double left = 20;
double triggerWidth = 200; // fallback width
if (triggerKey?.currentContext != null) { if (triggerKey?.currentContext != null) {
final renderBox = final triggerBox =
triggerKey!.currentContext!.findRenderObject() as RenderBox; triggerKey!.currentContext!.findRenderObject() as RenderBox;
final offset = renderBox.localToGlobal(Offset.zero); final triggerOffset = triggerBox.localToGlobal(Offset.zero);
final size = renderBox.size; final triggerSize = triggerBox.size;
top = offset.dy + size.height + 4; triggerWidth = triggerSize.width;
left = offset.dx;
double stackDy = 0;
double stackDx = 0;
if (stackKey?.currentContext != null) {
final stackBox =
stackKey!.currentContext!.findRenderObject() as RenderBox;
final stackOffset = stackBox.localToGlobal(Offset.zero);
stackDy = stackOffset.dy;
stackDx = stackOffset.dx;
}
top = triggerOffset.dy - stackDy + triggerSize.height + 4;
left = triggerOffset.dx - stackDx;
} }
return Positioned( return Positioned(
top: top, top: top,
left: left, left: left,
child: IntrinsicWidth( width: triggerWidth,
child: Material( child: Material(
elevation: 8, elevation: 8,
borderRadius: BorderRadius.circular(12), borderRadius: BorderRadius.circular(12),
@@ -930,6 +949,8 @@ class _ToAccountDropdownOverlay extends ConsumerWidget {
Expanded( Expanded(
child: Text( child: Text(
account.name, account.name,
overflow: TextOverflow.ellipsis,
maxLines: 1,
style: TextStyle( style: TextStyle(
fontSize: 14, fontSize: 14,
fontWeight: isSelected fontWeight: isSelected
@@ -941,13 +962,15 @@ class _ToAccountDropdownOverlay extends ConsumerWidget {
), ),
), ),
), ),
if (isSelected) if (isSelected) ...[
const SizedBox(width: 10),
const Icon( const Icon(
Icons.check_rounded, Icons.check_rounded,
size: 16, size: 16,
color: Color(0xFF7C6DED), color: Color(0xFF7C6DED),
), ),
], ],
],
), ),
), ),
); );
@@ -959,7 +982,6 @@ class _ToAccountDropdownOverlay extends ConsumerWidget {
), ),
), ),
), ),
),
); );
} }
} }
@@ -120,12 +120,14 @@ class AccountDropdownOverlay extends ConsumerWidget {
final Transaction? initial; final Transaction? initial;
final VoidCallback onClose; final VoidCallback onClose;
final GlobalKey? triggerKey; final GlobalKey? triggerKey;
final GlobalKey? stackKey;
const AccountDropdownOverlay({ const AccountDropdownOverlay({
super.key, super.key,
required this.initial, required this.initial,
required this.onClose, required this.onClose,
this.triggerKey, this.triggerKey,
this.stackKey,
}); });
@override @override
@@ -136,20 +138,33 @@ class AccountDropdownOverlay extends ConsumerWidget {
// Calculate position from trigger key // Calculate position from trigger key
double top = 76; double top = 76;
double left = 20; double left = 20;
double triggerWidth = 200; // fallback width
if (triggerKey?.currentContext != null) { if (triggerKey?.currentContext != null) {
final renderBox = final triggerBox =
triggerKey!.currentContext!.findRenderObject() as RenderBox; triggerKey!.currentContext!.findRenderObject() as RenderBox;
final offset = renderBox.localToGlobal(Offset.zero); final triggerOffset = triggerBox.localToGlobal(Offset.zero);
final size = renderBox.size; final triggerSize = triggerBox.size;
top = offset.dy + size.height + 4; triggerWidth = triggerSize.width;
left = offset.dx;
double stackDy = 0;
double stackDx = 0;
if (stackKey?.currentContext != null) {
final stackBox =
stackKey!.currentContext!.findRenderObject() as RenderBox;
final stackOffset = stackBox.localToGlobal(Offset.zero);
stackDy = stackOffset.dy;
stackDx = stackOffset.dx;
}
top = triggerOffset.dy - stackDy + triggerSize.height + 4;
left = triggerOffset.dx - stackDx;
} }
return Positioned( return Positioned(
top: top, top: top,
left: left, left: left,
child: IntrinsicWidth( width: triggerWidth,
child: Material( child: Material(
elevation: 8, elevation: 8,
borderRadius: BorderRadius.circular(12), borderRadius: BorderRadius.circular(12),
@@ -226,6 +241,8 @@ class AccountDropdownOverlay extends ConsumerWidget {
Expanded( Expanded(
child: Text( child: Text(
account.name, account.name,
overflow: TextOverflow.ellipsis,
maxLines: 1,
style: TextStyle( style: TextStyle(
fontSize: 14, fontSize: 14,
fontWeight: isSelected fontWeight: isSelected
@@ -237,13 +254,15 @@ class AccountDropdownOverlay extends ConsumerWidget {
), ),
), ),
), ),
if (isSelected) if (isSelected) ...[
const SizedBox(width: 10),
const Icon( const Icon(
Icons.check_rounded, Icons.check_rounded,
size: 16, size: 16,
color: Color(0xFF7C6DED), color: Color(0xFF7C6DED),
), ),
], ],
],
), ),
), ),
); );
@@ -255,7 +274,6 @@ class AccountDropdownOverlay extends ConsumerWidget {
), ),
), ),
), ),
),
); );
} }
} }