mirror of
https://github.com/cake-tech/cake_wallet.git
synced 2025-06-28 12:29:51 +00:00
Cw 1038 filter transaction popup not scrollable (#2207)
* ui:make overflowing filter sections scrollable * Update pull_request_template.md
This commit is contained in:
parent
66e1745ad9
commit
ffe1c115fa
3 changed files with 164 additions and 112 deletions
1
.github/pull_request_template.md
vendored
1
.github/pull_request_template.md
vendored
|
@ -11,3 +11,4 @@ Please include a summary of the changes and which issue is fixed / feature is ad
|
|||
- [ ] Format code
|
||||
- [ ] Look for code duplication
|
||||
- [ ] Clear naming for variables and methods
|
||||
- [ ] Manual tests in accessibility mode (TalkBack on Android) passed
|
||||
|
|
|
@ -1,123 +1,178 @@
|
|||
import 'package:cake_wallet/src/widgets/alert_background.dart';
|
||||
import 'package:cake_wallet/src/widgets/alert_close_button.dart';
|
||||
import 'package:cake_wallet/themes/extensions/cake_text_theme.dart';
|
||||
import 'package:cake_wallet/src/screens/dashboard/widgets/filter_tile.dart';
|
||||
import 'package:cake_wallet/src/widgets/section_divider.dart';
|
||||
import 'package:cake_wallet/src/widgets/standard_checkbox.dart';
|
||||
import 'package:cake_wallet/themes/extensions/menu_theme.dart';
|
||||
import 'package:cake_wallet/view_model/dashboard/dropdown_filter_item.dart';
|
||||
import 'package:cake_wallet/view_model/dashboard/dropdown_filter_item_widget.dart';
|
||||
import 'package:cake_wallet/utils/responsive_layout_util.dart';
|
||||
import 'package:cake_wallet/view_model/dashboard/filter_item.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:cake_wallet/src/widgets/picker_wrapper_widget.dart';
|
||||
import 'package:cake_wallet/generated/i18n.dart';
|
||||
import 'package:flutter_mobx/flutter_mobx.dart';
|
||||
|
||||
//import 'package:date_range_picker/date_range_picker.dart' as date_rage_picker;
|
||||
import 'package:cake_wallet/themes/extensions/transaction_trade_theme.dart';
|
||||
|
||||
class FilterWidget extends StatelessWidget {
|
||||
FilterWidget({required this.filterItems});
|
||||
class FilterWidget extends StatefulWidget {
|
||||
const FilterWidget({required this.filterItems, this.onClose, Key? key}) : super(key: key);
|
||||
|
||||
final Map<String, List<FilterItem>> filterItems;
|
||||
final Function()? onClose;
|
||||
|
||||
@override
|
||||
_FilterWidgetState createState() => _FilterWidgetState();
|
||||
}
|
||||
|
||||
class _FilterWidgetState extends State<FilterWidget> {
|
||||
final ScrollController _scrollController = ScrollController();
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_scrollController.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
const sectionDivider = const HorizontalSectionDivider();
|
||||
return PickerWrapperWidget(
|
||||
children: [
|
||||
Padding(
|
||||
padding: EdgeInsets.only(left: 24, right: 24, top: 24),
|
||||
child: ClipRRect(
|
||||
borderRadius: BorderRadius.all(Radius.circular(24)),
|
||||
child: Container(
|
||||
color: Theme.of(context).extension<CakeMenuTheme>()!.backgroundColor,
|
||||
child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [
|
||||
Padding(
|
||||
padding: EdgeInsets.all(24.0),
|
||||
child: Text(
|
||||
S.of(context).filter_by,
|
||||
style: TextStyle(
|
||||
color:
|
||||
Theme.of(context).extension<TransactionTradeTheme>()!.detailsTitlesColor,
|
||||
fontSize: 16,
|
||||
fontFamily: 'Lato',
|
||||
decoration: TextDecoration.none,
|
||||
),
|
||||
),
|
||||
),
|
||||
sectionDivider,
|
||||
ListView.separated(
|
||||
padding: EdgeInsets.zero,
|
||||
shrinkWrap: true,
|
||||
physics: const NeverScrollableScrollPhysics(),
|
||||
itemCount: filterItems.length,
|
||||
separatorBuilder: (context, _) => sectionDivider,
|
||||
itemBuilder: (_, index1) {
|
||||
final title = filterItems.keys.elementAt(index1);
|
||||
final section = filterItems.values.elementAt(index1);
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
Padding(
|
||||
padding: EdgeInsets.only(top: 20, left: 24, right: 24),
|
||||
child: Text(
|
||||
title,
|
||||
style: TextStyle(
|
||||
color: Theme.of(context).extension<CakeTextTheme>()!.titleColor,
|
||||
fontSize: 16,
|
||||
fontFamily: 'Lato',
|
||||
fontWeight: FontWeight.bold,
|
||||
decoration: TextDecoration.none),
|
||||
),
|
||||
return AlertBackground(
|
||||
child: Column(
|
||||
children: [
|
||||
const Expanded(child: SizedBox()),
|
||||
Expanded(
|
||||
flex: responsiveLayoutUtil.shouldRenderTabletUI ? 16 : 8,
|
||||
child: LayoutBuilder(
|
||||
builder: (context, constraints) {
|
||||
double availableHeight = constraints.maxHeight;
|
||||
return _buildFilterContent(context, availableHeight);
|
||||
},
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: AlertCloseButton(
|
||||
key: const ValueKey('filter_wrapper_close_button_key'),
|
||||
isPositioned: false,
|
||||
onTap: widget.onClose,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 24),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildFilterContent(BuildContext context, double availableHeight) {
|
||||
const sectionDivider = HorizontalSectionDivider();
|
||||
|
||||
const double totalHeaderHeight = 73;
|
||||
const double filterTileMinHeight = 40;
|
||||
double availableHeightForItems = availableHeight - totalHeaderHeight;
|
||||
|
||||
return Center(
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(left: 24, right: 24, top: 24),
|
||||
child: ClipRRect(
|
||||
borderRadius: BorderRadius.circular(24),
|
||||
child: Container(
|
||||
color: Theme.of(context).extension<CakeMenuTheme>()!.backgroundColor,
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(24.0),
|
||||
child: Text(
|
||||
S.of(context).filter_by,
|
||||
style: TextStyle(
|
||||
color: Theme.of(context)
|
||||
.extension<TransactionTradeTheme>()!
|
||||
.detailsTitlesColor,
|
||||
fontSize: 16,
|
||||
fontFamily: 'Lato',
|
||||
decoration: TextDecoration.none,
|
||||
),
|
||||
ListView.builder(
|
||||
padding: EdgeInsets.symmetric(horizontal: 28.0),
|
||||
shrinkWrap: true,
|
||||
physics: const NeverScrollableScrollPhysics(),
|
||||
),
|
||||
),
|
||||
sectionDivider,
|
||||
ListView.separated(
|
||||
padding: EdgeInsets.zero,
|
||||
shrinkWrap: true,
|
||||
physics: const NeverScrollableScrollPhysics(),
|
||||
itemCount: widget.filterItems.length,
|
||||
separatorBuilder: (context, _) => sectionDivider,
|
||||
itemBuilder: (_, index1) {
|
||||
final title = widget.filterItems.keys.elementAt(index1);
|
||||
final section = widget.filterItems.values.elementAt(index1);
|
||||
|
||||
final double itemHeight =
|
||||
availableHeightForItems / widget.filterItems.length;
|
||||
|
||||
final isSectionScrollable =
|
||||
(itemHeight < (section.length * filterTileMinHeight));
|
||||
|
||||
final Widget sectionListView = ListView.builder(
|
||||
controller: isSectionScrollable ? _scrollController : null,
|
||||
padding: const EdgeInsets.symmetric(horizontal: 28.0),
|
||||
shrinkWrap: isSectionScrollable ? false : true,
|
||||
physics: isSectionScrollable
|
||||
? const BouncingScrollPhysics()
|
||||
: const NeverScrollableScrollPhysics(),
|
||||
itemCount: section.length,
|
||||
itemBuilder: (_, index2) {
|
||||
final item = section[index2];
|
||||
|
||||
if (item is DropdownFilterItem) {
|
||||
return Padding(
|
||||
padding: EdgeInsets.fromLTRB(8, 0, 8, 16),
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
border: Border(
|
||||
bottom: BorderSide(
|
||||
width: 1.0,
|
||||
color: Theme.of(context).extension<CakeTextTheme>()!.secondaryTextColor),
|
||||
),
|
||||
),
|
||||
child: DropdownFilterList(
|
||||
items: item.items,
|
||||
caption: item.caption,
|
||||
selectedItem: item.selectedItem,
|
||||
onItemSelected: item.onItemSelected,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
final content = Observer(
|
||||
builder: (_) => StandardCheckbox(
|
||||
value: item.value(),
|
||||
caption: item.caption,
|
||||
gradientBackground: true,
|
||||
borderColor: Theme.of(context).dividerColor,
|
||||
iconColor: Colors.white,
|
||||
onChanged: (value) => item.onChanged(),
|
||||
));
|
||||
return FilterTile(child: content);
|
||||
builder: (_) => StandardCheckbox(
|
||||
value: item.value(),
|
||||
caption: item.caption,
|
||||
gradientBackground: true,
|
||||
borderColor: Theme.of(context).dividerColor,
|
||||
iconColor: Colors.white,
|
||||
onChanged: (value) => item.onChanged(),
|
||||
),
|
||||
);
|
||||
return FilterTile(
|
||||
child: content,
|
||||
);
|
||||
},
|
||||
)
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 20, left: 24, right: 24),
|
||||
child: Text(
|
||||
title,
|
||||
style: TextStyle(
|
||||
color: Theme.of(context).extension<CakeTextTheme>()!.titleColor,
|
||||
fontSize: 16,
|
||||
fontFamily: 'Lato',
|
||||
fontWeight: FontWeight.bold,
|
||||
decoration: TextDecoration.none,
|
||||
),
|
||||
),
|
||||
),
|
||||
Container(
|
||||
height: isSectionScrollable ? itemHeight - totalHeaderHeight : null,
|
||||
child: isSectionScrollable
|
||||
? Scrollbar(
|
||||
controller: _scrollController,
|
||||
thumbVisibility: true,
|
||||
child: sectionListView,
|
||||
)
|
||||
: sectionListView,
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
]),
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
],
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ class AlertCloseButton extends StatelessWidget {
|
|||
this.image,
|
||||
this.bottom,
|
||||
this.onTap,
|
||||
this.isPositioned = true,
|
||||
super.key,
|
||||
});
|
||||
|
||||
|
@ -14,6 +15,7 @@ class AlertCloseButton extends StatelessWidget {
|
|||
|
||||
final Image? image;
|
||||
final double? bottom;
|
||||
final bool isPositioned;
|
||||
|
||||
final closeButton = Image.asset(
|
||||
'assets/images/close.png',
|
||||
|
@ -22,24 +24,18 @@ class AlertCloseButton extends StatelessWidget {
|
|||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Positioned(
|
||||
bottom: bottom ?? 60,
|
||||
child: GestureDetector(
|
||||
final button = GestureDetector(
|
||||
onTap: onTap ?? () => Navigator.of(context).pop(),
|
||||
child: Semantics(
|
||||
label: S.of(context).close,
|
||||
button: true,
|
||||
enabled: true,
|
||||
child: Container(
|
||||
height: 42,
|
||||
width: 42,
|
||||
decoration: BoxDecoration(color: Colors.white, shape: BoxShape.circle),
|
||||
child: Center(
|
||||
child: image ?? closeButton,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
label: S.of(context).close,
|
||||
button: true,
|
||||
enabled: true,
|
||||
child: Container(
|
||||
height: 42,
|
||||
width: 42,
|
||||
decoration: BoxDecoration(color: Colors.white, shape: BoxShape.circle),
|
||||
child: Center(child: image ?? closeButton))));
|
||||
|
||||
return isPositioned ? Positioned(bottom: bottom ?? 60, child: button) : button;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue