mirror of
https://github.com/cake-tech/cake_wallet.git
synced 2025-01-29 22:16:05 +00:00
CW-338: Currency picker UI when keyboard is showing (#854)
* fix: Currency picker UI when keyboard is showing * refactor: move picker logic into the common Picker widget - CurrencyPicker uses the common Picker widget in grid mode - SeedLanguagePicker uses the common Picker widget in grid mode - Added logic for keyboard showing UI into Picker widget - Added `softWrap: true` to the item text, so it doesn't overflow * fix: remove subPickerItemsList * fix: add final * fix: move function out of initState() * fix: keep build functions separate to remove boolean comparisons * fix: remove onItemSelected from already selected item * fix: change Expanded for Flexible widget
This commit is contained in:
parent
c5477e4f9e
commit
ff7a217d84
6 changed files with 429 additions and 438 deletions
|
@ -1,13 +1,8 @@
|
|||
import 'package:cake_wallet/src/screens/exchange/widgets/currency_picker_item_widget.dart';
|
||||
import 'package:cake_wallet/src/screens/exchange/widgets/picker_item.dart';
|
||||
import 'package:cake_wallet/src/widgets/alert_close_button.dart';
|
||||
import 'package:cake_wallet/utils/responsive_layout_util.dart';
|
||||
import 'package:cw_core/currency.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:cake_wallet/src/screens/exchange/widgets/picker_item.dart';
|
||||
import 'package:cw_core/crypto_currency.dart';
|
||||
import 'package:cake_wallet/src/widgets/alert_background.dart';
|
||||
import 'package:cake_wallet/palette.dart';
|
||||
import 'currency_picker_widget.dart';
|
||||
import 'package:cake_wallet/src/widgets/picker.dart';
|
||||
import 'package:cw_core/currency.dart';
|
||||
|
||||
class CurrencyPicker extends StatefulWidget {
|
||||
CurrencyPicker(
|
||||
|
@ -19,7 +14,7 @@ class CurrencyPicker extends StatefulWidget {
|
|||
this.isMoneroWallet = false,
|
||||
this.isConvertFrom = false});
|
||||
|
||||
int selectedAtIndex;
|
||||
final int selectedAtIndex;
|
||||
final List<Currency> items;
|
||||
final String? title;
|
||||
final Function(Currency) onItemSelected;
|
||||
|
@ -35,144 +30,39 @@ class CurrencyPickerState extends State<CurrencyPicker> {
|
|||
CurrencyPickerState(this.items)
|
||||
: isSearchBarActive = false,
|
||||
textFieldValue = '',
|
||||
subPickerItemsList = items,
|
||||
appBarTextStyle =
|
||||
TextStyle(fontSize: 20, fontFamily: 'Lato', backgroundColor: Colors.transparent, color: Colors.white),
|
||||
pickerItemsList = <PickerItem<Currency>>[];
|
||||
appBarTextStyle = TextStyle(
|
||||
fontSize: 20,
|
||||
fontFamily: 'Lato',
|
||||
backgroundColor: Colors.transparent,
|
||||
color: Colors.white),
|
||||
pickerItemsList = <PickerItem<CryptoCurrency>>[];
|
||||
|
||||
List<PickerItem<Currency>> pickerItemsList;
|
||||
List<Currency> items;
|
||||
bool isSearchBarActive;
|
||||
String textFieldValue;
|
||||
List<Currency> subPickerItemsList;
|
||||
TextStyle appBarTextStyle;
|
||||
|
||||
void cleanSubPickerItemsList() => subPickerItemsList = items;
|
||||
|
||||
void currencySearchBySubstring(String subString) {
|
||||
setState(() {
|
||||
if (subString.isNotEmpty) {
|
||||
subPickerItemsList = items
|
||||
.where((element) =>
|
||||
element.name.toLowerCase().contains(subString.toLowerCase()) ||
|
||||
(element.tag != null ? element.tag!.toLowerCase().contains(subString.toLowerCase()) : false) ||
|
||||
(element.fullName != null ? element.fullName!.toLowerCase().contains(subString.toLowerCase()) : false))
|
||||
.toList();
|
||||
return;
|
||||
}
|
||||
cleanSubPickerItemsList();
|
||||
});
|
||||
bool currencySearchBySubstring(Currency currency, String subString) {
|
||||
return currency.name.toLowerCase().contains(subString.toLowerCase()) ||
|
||||
(currency.tag != null
|
||||
? currency.tag!.toLowerCase().contains(subString.toLowerCase())
|
||||
: false) ||
|
||||
(currency.fullName != null
|
||||
? currency.fullName!.toLowerCase().contains(subString.toLowerCase())
|
||||
: false);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return AlertBackground(
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: <Widget>[
|
||||
if (widget.title?.isNotEmpty ?? false)
|
||||
Container(
|
||||
padding: EdgeInsets.symmetric(horizontal: 24),
|
||||
child: Text(
|
||||
widget.title!,
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontSize: 18,
|
||||
fontFamily: 'Lato',
|
||||
fontWeight: FontWeight.bold,
|
||||
decoration: TextDecoration.none,
|
||||
color: Colors.white,
|
||||
),
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: EdgeInsets.only(left: 24, right: 24, top: 24),
|
||||
child: ClipRRect(
|
||||
borderRadius: BorderRadius.all(Radius.circular(30)),
|
||||
child: Container(
|
||||
color: Theme.of(context).accentTextTheme.headline6!.color!,
|
||||
child: ConstrainedBox(
|
||||
constraints: BoxConstraints(
|
||||
maxHeight: MediaQuery.of(context).size.height * 0.65,
|
||||
maxWidth: ResponsiveLayoutUtil.kPopupWidth
|
||||
),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
if (widget.hintText != null)
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: TextFormField(
|
||||
style: TextStyle(color: Palette.darkBlueCraiola),
|
||||
decoration: InputDecoration(
|
||||
hintText: widget.hintText,
|
||||
prefixIcon: Image.asset("assets/images/search_icon.png"),
|
||||
filled: true,
|
||||
fillColor: const Color(0xffF2F0FA),
|
||||
alignLabelWithHint: false,
|
||||
contentPadding: const EdgeInsets.symmetric(vertical: 4, horizontal: 16),
|
||||
enabledBorder: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(14),
|
||||
borderSide: const BorderSide(
|
||||
color: Colors.transparent,
|
||||
)),
|
||||
focusedBorder: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(14),
|
||||
borderSide: const BorderSide(
|
||||
color: Colors.transparent,
|
||||
)),
|
||||
),
|
||||
onChanged: (value) {
|
||||
this.textFieldValue = value;
|
||||
cleanSubPickerItemsList();
|
||||
currencySearchBySubstring(textFieldValue);
|
||||
},
|
||||
),
|
||||
),
|
||||
Divider(
|
||||
color: Theme.of(context).accentTextTheme.headline6!.backgroundColor!,
|
||||
height: 1,
|
||||
),
|
||||
if (widget.selectedAtIndex != -1)
|
||||
AspectRatio(
|
||||
aspectRatio: 6,
|
||||
child: PickerItemWidget(
|
||||
title: items[widget.selectedAtIndex].name,
|
||||
iconPath: items[widget.selectedAtIndex].iconPath,
|
||||
isSelected: true,
|
||||
tag: items[widget.selectedAtIndex].tag,
|
||||
),
|
||||
),
|
||||
Flexible(
|
||||
child: CurrencyPickerWidget(
|
||||
crossAxisCount: 2,
|
||||
selectedAtIndex: widget.selectedAtIndex,
|
||||
pickerItemsList: subPickerItemsList,
|
||||
pickListItem: (int index) {
|
||||
setState(() {
|
||||
widget.selectedAtIndex = index;
|
||||
});
|
||||
widget.onItemSelected(subPickerItemsList[index]);
|
||||
if (widget.isConvertFrom &&
|
||||
!widget.isMoneroWallet &&
|
||||
(subPickerItemsList[index] == CryptoCurrency.xmr)) {
|
||||
} else {
|
||||
Navigator.of(context).pop();
|
||||
}
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
SizedBox(height: ResponsiveLayoutUtil.kPopupSpaceHeight),
|
||||
AlertCloseButton(),
|
||||
],
|
||||
),
|
||||
return Picker(
|
||||
selectedAtIndex: widget.selectedAtIndex,
|
||||
items: items,
|
||||
isGridView: true,
|
||||
title: widget.title,
|
||||
hintText: widget.hintText,
|
||||
matchingCriteria: currencySearchBySubstring,
|
||||
onItemSelected: widget.onItemSelected,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -113,16 +113,10 @@ class WalletRestoreFromSeedFormState extends State<WalletRestoreFromSeedForm> {
|
|||
if (widget.displayLanguageSelector)
|
||||
GestureDetector(
|
||||
onTap: () async {
|
||||
final selected = await showPopUp<String>(
|
||||
await showPopUp<void>(
|
||||
context: context,
|
||||
builder: (BuildContext context) =>
|
||||
SeedLanguagePicker(selected: language));
|
||||
|
||||
if (selected == null || selected.isEmpty) {
|
||||
return;
|
||||
}
|
||||
|
||||
_changeLanguage(selected);
|
||||
builder: (_) => SeedLanguagePicker(
|
||||
selected: language, onItemSelected: _changeLanguage));
|
||||
},
|
||||
child: Container(
|
||||
color: Colors.transparent,
|
||||
|
|
|
@ -1,9 +1,6 @@
|
|||
import 'dart:ui';
|
||||
import 'package:cake_wallet/src/widgets/alert_background.dart';
|
||||
import 'package:cake_wallet/src/widgets/alert_close_button.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:cake_wallet/palette.dart';
|
||||
import 'package:cake_wallet/src/widgets/picker.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:cake_wallet/generated/i18n.dart';
|
||||
|
||||
List<Image> flagImages = [
|
||||
|
@ -50,138 +47,40 @@ const List<String> seedLanguages = [
|
|||
enum Places { topLeft, topRight, bottomLeft, bottomRight, inside }
|
||||
|
||||
class SeedLanguagePicker extends StatefulWidget {
|
||||
SeedLanguagePicker({
|
||||
Key? key,
|
||||
this.selected = defaultSeedLanguage})
|
||||
SeedLanguagePicker(
|
||||
{Key? key,
|
||||
this.selected = defaultSeedLanguage,
|
||||
required this.onItemSelected})
|
||||
: super(key: key);
|
||||
|
||||
final String selected;
|
||||
final Function(String) onItemSelected;
|
||||
|
||||
@override
|
||||
SeedLanguagePickerState createState() =>
|
||||
SeedLanguagePickerState(selected: selected);
|
||||
SeedLanguagePickerState createState() => SeedLanguagePickerState(
|
||||
selected: selected, onItemSelected: onItemSelected);
|
||||
}
|
||||
|
||||
class SeedLanguagePickerState extends State<SeedLanguagePicker> {
|
||||
SeedLanguagePickerState({required this.selected});
|
||||
SeedLanguagePickerState(
|
||||
{required this.selected, required this.onItemSelected});
|
||||
|
||||
final closeButton = Image.asset('assets/images/close.png');
|
||||
String selected;
|
||||
final String selected;
|
||||
final Function(String) onItemSelected;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return AlertBackground(
|
||||
child: Stack(
|
||||
alignment: Alignment.center,
|
||||
children: <Widget>[
|
||||
Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: <Widget>[
|
||||
Container(
|
||||
padding: EdgeInsets.only(left: 24, right: 24),
|
||||
child: Text(
|
||||
S.of(context).seed_choose,
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontSize: 18,
|
||||
fontWeight: FontWeight.bold,
|
||||
fontFamily: 'Lato',
|
||||
decoration: TextDecoration.none,
|
||||
color: Colors.white),
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: EdgeInsets.only(top: 24),
|
||||
child: ClipRRect(
|
||||
borderRadius: BorderRadius.all(Radius.circular(14)),
|
||||
child: Container(
|
||||
height: 300,
|
||||
width: 300,
|
||||
color:
|
||||
Theme.of(context).accentTextTheme!.headline6!.backgroundColor!,
|
||||
child: GridView.count(
|
||||
padding: EdgeInsets.all(0),
|
||||
shrinkWrap: true,
|
||||
crossAxisCount: 3,
|
||||
childAspectRatio: 4 / 3,
|
||||
physics: const NeverScrollableScrollPhysics(),
|
||||
crossAxisSpacing: 1,
|
||||
mainAxisSpacing: 1,
|
||||
children: List.generate(11, (index) {
|
||||
if (index == 10) {
|
||||
return gridTile(
|
||||
isCurrent: false,
|
||||
image: null,
|
||||
text: '',
|
||||
onTap: () {});
|
||||
}
|
||||
|
||||
final code = languageCodes[index];
|
||||
final flag = flagImages[index];
|
||||
final isCurrent =
|
||||
index == seedLanguages.indexOf(selected);
|
||||
|
||||
return gridTile(
|
||||
isCurrent: isCurrent,
|
||||
image: flag,
|
||||
text: code,
|
||||
onTap: () {
|
||||
selected = seedLanguages[index];
|
||||
Navigator.of(context).pop(selected);
|
||||
});
|
||||
}),
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
AlertCloseButton(image: closeButton)
|
||||
],
|
||||
));
|
||||
}
|
||||
|
||||
Widget gridTile(
|
||||
{required bool isCurrent,
|
||||
required String text,
|
||||
required VoidCallback onTap,
|
||||
Image? image}) {
|
||||
final color = isCurrent
|
||||
? Theme.of(context).textTheme!.bodyText1!.color!
|
||||
: Theme.of(context).accentTextTheme!.headline6!.color!;
|
||||
final textColor = isCurrent
|
||||
? Palette.blueCraiola
|
||||
: Theme.of(context).primaryTextTheme!.headline6!.color!;
|
||||
|
||||
return GestureDetector(
|
||||
onTap: onTap,
|
||||
child: Container(
|
||||
padding: EdgeInsets.all(10),
|
||||
color: color,
|
||||
child: Center(
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: <Widget>[
|
||||
image ?? Offstage(),
|
||||
Padding(
|
||||
padding: image != null
|
||||
? EdgeInsets.only(left: 10)
|
||||
: EdgeInsets.only(left: 0),
|
||||
child: Text(
|
||||
text,
|
||||
style: TextStyle(
|
||||
fontSize: 18,
|
||||
fontWeight: FontWeight.w600,
|
||||
fontFamily: 'Lato',
|
||||
decoration: TextDecoration.none,
|
||||
color: textColor),
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
));
|
||||
return Picker(
|
||||
selectedAtIndex: seedLanguages.indexOf(selected),
|
||||
items: seedLanguages,
|
||||
images: flagImages,
|
||||
isGridView: true,
|
||||
title: S.of(context).seed_choose,
|
||||
hintText: S.of(context).seed_choose,
|
||||
matchingCriteria: (String language, String searchText) {
|
||||
return language.toLowerCase().contains(searchText);
|
||||
},
|
||||
onItemSelected: onItemSelected,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,9 +2,10 @@ import 'package:cake_wallet/palette.dart';
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
class AlertCloseButton extends StatelessWidget {
|
||||
AlertCloseButton({this.image});
|
||||
AlertCloseButton({this.image, this.bottom});
|
||||
|
||||
final Image? image;
|
||||
final double? bottom;
|
||||
|
||||
final closeButton = Image.asset(
|
||||
'assets/images/close.png',
|
||||
|
@ -13,7 +14,9 @@ class AlertCloseButton extends StatelessWidget {
|
|||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return GestureDetector(
|
||||
return Positioned(
|
||||
bottom: bottom ?? 60,
|
||||
child: GestureDetector(
|
||||
onTap: () => Navigator.of(context).pop(),
|
||||
child: Container(
|
||||
height: 42,
|
||||
|
@ -26,6 +29,6 @@ class AlertCloseButton extends StatelessWidget {
|
|||
child: image ?? closeButton,
|
||||
),
|
||||
),
|
||||
);
|
||||
));
|
||||
}
|
||||
}
|
|
@ -4,6 +4,7 @@ import 'package:cake_wallet/utils/responsive_layout_util.dart';
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:cake_wallet/src/widgets/alert_background.dart';
|
||||
import 'package:cake_wallet/src/widgets/alert_close_button.dart';
|
||||
import 'package:cw_core/currency.dart';
|
||||
|
||||
class Picker<Item> extends StatefulWidget {
|
||||
Picker({
|
||||
|
@ -37,7 +38,8 @@ class Picker<Item> extends StatefulWidget {
|
|||
final bool Function(Item, String)? matchingCriteria;
|
||||
|
||||
@override
|
||||
_PickerState<Item> createState() => _PickerState<Item>(items, images, onItemSelected);
|
||||
_PickerState<Item> createState() =>
|
||||
_PickerState<Item>(items, images, onItemSelected);
|
||||
}
|
||||
|
||||
class _PickerState<Item> extends State<Picker<Item>> {
|
||||
|
@ -46,132 +48,235 @@ class _PickerState<Item> extends State<Picker<Item>> {
|
|||
final Function(Item) onItemSelected;
|
||||
List<Item> items;
|
||||
List<Image> images;
|
||||
List<Item> filteredItems = [];
|
||||
List<Image> filteredImages = [];
|
||||
|
||||
final TextEditingController searchController = TextEditingController();
|
||||
|
||||
ScrollController controller = ScrollController();
|
||||
|
||||
void clearFilteredItemsList() {
|
||||
filteredItems = List.from(
|
||||
items,
|
||||
growable: true,
|
||||
);
|
||||
filteredImages = List.from(
|
||||
images,
|
||||
growable: true,
|
||||
);
|
||||
|
||||
if (widget.selectedAtIndex != -1) {
|
||||
if (widget.selectedAtIndex < filteredItems.length) {
|
||||
filteredItems.removeAt(widget.selectedAtIndex);
|
||||
}
|
||||
|
||||
if (widget.selectedAtIndex < filteredImages.length) {
|
||||
filteredImages.removeAt(widget.selectedAtIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
|
||||
clearFilteredItemsList();
|
||||
|
||||
searchController.addListener(() {
|
||||
items = [];
|
||||
images = [];
|
||||
for (int i=0;i<widget.items.length;i++) {
|
||||
if (widget.matchingCriteria?.call(widget.items[i], searchController.text) ?? true) {
|
||||
items.add(widget.items[i]);
|
||||
images.add(widget.images[i]);
|
||||
}
|
||||
}
|
||||
setState(() {});
|
||||
clearFilteredItemsList();
|
||||
|
||||
setState(() {
|
||||
filteredItems = List.from(items.where((element) {
|
||||
if (widget.selectedAtIndex != items.indexOf(element) &&
|
||||
(widget.matchingCriteria?.call(element, searchController.text) ??
|
||||
true)) {
|
||||
if (images.isNotEmpty) {
|
||||
filteredImages.add(images[items.indexOf(element)]);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if (filteredImages.isNotEmpty) {
|
||||
filteredImages.remove(images[items.indexOf(element)]);
|
||||
}
|
||||
return false;
|
||||
}), growable: true);
|
||||
|
||||
return;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final double padding = 24;
|
||||
|
||||
final mq = MediaQuery.of(context);
|
||||
final bottom = mq.viewInsets.bottom;
|
||||
final height = mq.size.height - bottom;
|
||||
final screenCenter = height / 2;
|
||||
|
||||
double closeButtonBottom = 60;
|
||||
double containerHeight = height * 0.65;
|
||||
if (bottom > 0) {
|
||||
// increase a bit or it gets too squished in the top
|
||||
containerHeight = height * 0.75;
|
||||
|
||||
final containerCenter = containerHeight / 2;
|
||||
final containerBottom = screenCenter - containerCenter;
|
||||
|
||||
final hasTitle = widget.title == null || widget.title!.isEmpty;
|
||||
|
||||
// position the close button right below the search container
|
||||
closeButtonBottom = closeButtonBottom -
|
||||
containerBottom +
|
||||
(hasTitle ? padding : padding / 1.5);
|
||||
}
|
||||
|
||||
return AlertBackground(
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: <Widget>[
|
||||
if (widget.title?.isNotEmpty ?? false)
|
||||
Container(
|
||||
padding: EdgeInsets.symmetric(horizontal: 24),
|
||||
child: Text(
|
||||
widget.title!,
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontSize: 18,
|
||||
fontFamily: 'Lato',
|
||||
fontWeight: FontWeight.bold,
|
||||
decoration: TextDecoration.none,
|
||||
color: Colors.white,
|
||||
),
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: EdgeInsets.only(left: 24, right: 24, top: 24),
|
||||
child: ClipRRect(
|
||||
borderRadius: BorderRadius.all(Radius.circular(30)),
|
||||
child: Container(
|
||||
color: Theme.of(context).accentTextTheme.headline6!.color!,
|
||||
child: ConstrainedBox(
|
||||
constraints: BoxConstraints(
|
||||
maxHeight: MediaQuery.of(context).size.height * 0.65,
|
||||
maxWidth: ResponsiveLayoutUtil.kPopupWidth,
|
||||
),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
if (widget.hintText != null)
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: TextFormField(
|
||||
controller: searchController,
|
||||
style: TextStyle(color: Theme.of(context).primaryTextTheme.headline6!.color!),
|
||||
decoration: InputDecoration(
|
||||
hintText: widget.hintText,
|
||||
prefixIcon: Image.asset("assets/images/search_icon.png"),
|
||||
filled: true,
|
||||
fillColor: Theme.of(context).accentTextTheme.headline3!.color!,
|
||||
alignLabelWithHint: false,
|
||||
contentPadding: const EdgeInsets.symmetric(vertical: 4, horizontal: 16),
|
||||
enabledBorder: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(14),
|
||||
borderSide: const BorderSide(
|
||||
color: Colors.transparent,
|
||||
)),
|
||||
focusedBorder: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(14),
|
||||
borderSide: const BorderSide(
|
||||
color: Colors.transparent,
|
||||
)),
|
||||
),
|
||||
children: [
|
||||
Expanded(
|
||||
flex: 1,
|
||||
child: Stack(
|
||||
alignment: Alignment.center,
|
||||
children: <Widget>[
|
||||
Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: <Widget>[
|
||||
if (widget.title?.isNotEmpty ?? false)
|
||||
Container(
|
||||
padding: EdgeInsets.symmetric(horizontal: padding),
|
||||
child: Text(
|
||||
widget.title!,
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontSize: 18,
|
||||
fontFamily: 'Lato',
|
||||
fontWeight: FontWeight.bold,
|
||||
decoration: TextDecoration.none,
|
||||
color: Colors.white,
|
||||
),
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: EdgeInsets.symmetric(horizontal: padding),
|
||||
child: ClipRRect(
|
||||
borderRadius: BorderRadius.all(Radius.circular(30)),
|
||||
child: Container(
|
||||
color: Theme.of(context)
|
||||
.accentTextTheme
|
||||
.headline6!
|
||||
.color!,
|
||||
child: ConstrainedBox(
|
||||
constraints: BoxConstraints(
|
||||
maxHeight: containerHeight,
|
||||
maxWidth: ResponsiveLayoutUtil.kPopupWidth,
|
||||
),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
if (widget.hintText != null)
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: TextFormField(
|
||||
controller: searchController,
|
||||
style: TextStyle(
|
||||
color: Theme.of(context)
|
||||
.primaryTextTheme
|
||||
.headline6!
|
||||
.color!),
|
||||
decoration: InputDecoration(
|
||||
hintText: widget.hintText,
|
||||
prefixIcon: Image.asset(
|
||||
"assets/images/search_icon.png"),
|
||||
filled: true,
|
||||
fillColor: Theme.of(context)
|
||||
.accentTextTheme
|
||||
.headline3!
|
||||
.color!,
|
||||
alignLabelWithHint: false,
|
||||
contentPadding:
|
||||
const EdgeInsets.symmetric(
|
||||
vertical: 4, horizontal: 16),
|
||||
enabledBorder: OutlineInputBorder(
|
||||
borderRadius:
|
||||
BorderRadius.circular(14),
|
||||
borderSide: const BorderSide(
|
||||
color: Colors.transparent,
|
||||
)),
|
||||
focusedBorder: OutlineInputBorder(
|
||||
borderRadius:
|
||||
BorderRadius.circular(14),
|
||||
borderSide: const BorderSide(
|
||||
color: Colors.transparent,
|
||||
)),
|
||||
),
|
||||
),
|
||||
),
|
||||
Divider(
|
||||
color: Theme.of(context)
|
||||
.accentTextTheme
|
||||
.headline6!
|
||||
.backgroundColor!,
|
||||
height: 1,
|
||||
),
|
||||
if (widget.selectedAtIndex != -1)
|
||||
buildSelectedItem(widget.selectedAtIndex),
|
||||
Flexible(
|
||||
child: Stack(
|
||||
alignment: Alignment.center,
|
||||
children: <Widget>[
|
||||
filteredItems.length > 3
|
||||
? Scrollbar(
|
||||
controller: controller,
|
||||
child: itemsList(),
|
||||
)
|
||||
: itemsList(),
|
||||
(widget.description?.isNotEmpty ?? false)
|
||||
? Positioned(
|
||||
bottom: padding,
|
||||
left: padding,
|
||||
right: padding,
|
||||
child: Text(
|
||||
widget.description!,
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.w500,
|
||||
fontFamily: 'Lato',
|
||||
decoration:
|
||||
TextDecoration.none,
|
||||
color: Theme.of(context)
|
||||
.primaryTextTheme
|
||||
.headline6!
|
||||
.color!,
|
||||
),
|
||||
),
|
||||
)
|
||||
: Offstage(),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Divider(
|
||||
color: Theme.of(context).accentTextTheme.headline6!.backgroundColor!,
|
||||
height: 1,
|
||||
),
|
||||
if (widget.selectedAtIndex != -1) buildSelectedItem(),
|
||||
Flexible(
|
||||
child: Stack(
|
||||
alignment: Alignment.center,
|
||||
children: <Widget>[
|
||||
items.length > 3 ? Scrollbar(
|
||||
controller: controller,
|
||||
child: itemsList(),
|
||||
) : itemsList(),
|
||||
(widget.description?.isNotEmpty ?? false)
|
||||
? Positioned(
|
||||
bottom: 24,
|
||||
left: 24,
|
||||
right: 24,
|
||||
child: Text(
|
||||
widget.description!,
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.w500,
|
||||
fontFamily: 'Lato',
|
||||
decoration: TextDecoration.none,
|
||||
color: Theme.of(context).primaryTextTheme.headline6!.color!,
|
||||
),
|
||||
),
|
||||
)
|
||||
: Offstage(),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
SizedBox(height: ResponsiveLayoutUtil.kPopupSpaceHeight),
|
||||
AlertCloseButton(bottom: closeButtonBottom),
|
||||
],
|
||||
),
|
||||
),
|
||||
SizedBox(height: ResponsiveLayoutUtil.kPopupSpaceHeight),
|
||||
AlertCloseButton(),
|
||||
// gives the extra spacing using MediaQuery.viewInsets.bottom
|
||||
// to simulate a keyboard area
|
||||
SizedBox(
|
||||
height: bottom,
|
||||
)
|
||||
],
|
||||
),
|
||||
);
|
||||
|
@ -185,7 +290,7 @@ class _PickerState<Item> extends State<Picker<Item>> {
|
|||
padding: EdgeInsets.zero,
|
||||
controller: controller,
|
||||
shrinkWrap: true,
|
||||
itemCount: items.isEmpty ? 0 : items.length,
|
||||
itemCount: filteredItems.isEmpty ? 0 : filteredItems.length,
|
||||
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
|
||||
crossAxisCount: 2,
|
||||
crossAxisSpacing: 2,
|
||||
|
@ -199,34 +304,42 @@ class _PickerState<Item> extends State<Picker<Item>> {
|
|||
shrinkWrap: true,
|
||||
separatorBuilder: (context, index) => widget.isSeparated
|
||||
? Divider(
|
||||
color: Theme.of(context).accentTextTheme.headline6!.backgroundColor!,
|
||||
color: Theme.of(context)
|
||||
.accentTextTheme
|
||||
.headline6!
|
||||
.backgroundColor!,
|
||||
height: 1,
|
||||
)
|
||||
: const SizedBox(),
|
||||
itemCount: items.isEmpty ? 0 : items.length,
|
||||
itemCount: filteredItems.isEmpty ? 0 : filteredItems.length,
|
||||
itemBuilder: (context, index) => buildItem(index),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget buildItem(int index) {
|
||||
/// don't show selected item in the list view
|
||||
if (widget.items[widget.selectedAtIndex] == items[index] && !widget.isGridView) {
|
||||
return const SizedBox();
|
||||
}
|
||||
final item = filteredItems[index];
|
||||
final tag = item is Currency ? item.tag : null;
|
||||
|
||||
final item = items[index];
|
||||
final image = images.isNotEmpty ? images[index] : null;
|
||||
final icon = item is Currency && item.iconPath != null
|
||||
? Image.asset(
|
||||
item.iconPath!,
|
||||
height: 20.0,
|
||||
width: 20.0,
|
||||
)
|
||||
: null;
|
||||
|
||||
final image = images.isNotEmpty ? filteredImages[index] : icon;
|
||||
|
||||
return GestureDetector(
|
||||
onTap: () {
|
||||
Navigator.of(context).pop();
|
||||
onItemSelected(item);
|
||||
onItemSelected(item!);
|
||||
},
|
||||
child: Container(
|
||||
height: 55,
|
||||
color: Theme.of(context).accentTextTheme.headline6!.color!,
|
||||
padding: EdgeInsets.only(left: 24, right: 24),
|
||||
padding: EdgeInsets.symmetric(horizontal: 24),
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
mainAxisAlignment: widget.mainAxisAlignment,
|
||||
|
@ -236,15 +349,53 @@ class _PickerState<Item> extends State<Picker<Item>> {
|
|||
Expanded(
|
||||
child: Padding(
|
||||
padding: EdgeInsets.only(left: image != null ? 12 : 0),
|
||||
child: Text(
|
||||
widget.displayItem?.call(item) ?? item.toString(),
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
fontFamily: 'Lato',
|
||||
fontWeight: FontWeight.w600,
|
||||
color: Theme.of(context).primaryTextTheme.headline6!.color!,
|
||||
decoration: TextDecoration.none,
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
Flexible(
|
||||
child: Text(
|
||||
widget.displayItem?.call(item) ?? item.toString(),
|
||||
softWrap: true,
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
fontFamily: 'Lato',
|
||||
fontWeight: FontWeight.w600,
|
||||
color: Theme.of(context)
|
||||
.primaryTextTheme
|
||||
.headline6!
|
||||
.color!,
|
||||
decoration: TextDecoration.none,
|
||||
),
|
||||
),
|
||||
),
|
||||
if (tag != null)
|
||||
Align(
|
||||
alignment: Alignment.topCenter,
|
||||
child: Container(
|
||||
width: 35.0,
|
||||
height: 18.0,
|
||||
child: Center(
|
||||
child: Text(
|
||||
tag,
|
||||
style: TextStyle(
|
||||
fontSize: 7.0,
|
||||
fontFamily: 'Lato',
|
||||
color: Theme.of(context)
|
||||
.textTheme
|
||||
.bodyText2!
|
||||
.color!),
|
||||
),
|
||||
),
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(6.0),
|
||||
//border: Border.all(color: ),
|
||||
color: Theme.of(context)
|
||||
.textTheme
|
||||
.bodyText2!
|
||||
.decorationColor!,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
|
@ -254,37 +405,91 @@ class _PickerState<Item> extends State<Picker<Item>> {
|
|||
);
|
||||
}
|
||||
|
||||
Widget buildSelectedItem() {
|
||||
final item = widget.items[widget.selectedAtIndex];
|
||||
final image = images.isNotEmpty ? widget.images[widget.selectedAtIndex] : null;
|
||||
Widget buildSelectedItem(int index) {
|
||||
final item = items[index];
|
||||
final tag = item is Currency ? item.tag : null;
|
||||
|
||||
return Container(
|
||||
height: 55,
|
||||
color: Theme.of(context).accentTextTheme.headline6!.color!,
|
||||
padding: EdgeInsets.only(left: 24, right: 24),
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
mainAxisAlignment: widget.mainAxisAlignment,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: <Widget>[
|
||||
image ?? Offstage(),
|
||||
Expanded(
|
||||
child: Padding(
|
||||
padding: EdgeInsets.only(left: image != null ? 12 : 0),
|
||||
child: Text(
|
||||
widget.displayItem?.call(item) ?? item.toString(),
|
||||
style: TextStyle(
|
||||
fontSize: 16,
|
||||
fontFamily: 'Lato',
|
||||
fontWeight: FontWeight.w700,
|
||||
color: Theme.of(context).primaryTextTheme.headline6!.color!,
|
||||
decoration: TextDecoration.none,
|
||||
final icon = item is Currency && item.iconPath != null
|
||||
? Image.asset(
|
||||
item.iconPath!,
|
||||
height: 20.0,
|
||||
width: 20.0,
|
||||
)
|
||||
: null;
|
||||
|
||||
final image = images.isNotEmpty ? images[index] : icon;
|
||||
|
||||
return GestureDetector(
|
||||
onTap: () {
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
child: Container(
|
||||
height: 55,
|
||||
color: Theme.of(context).accentTextTheme.headline6!.color!,
|
||||
padding: EdgeInsets.symmetric(horizontal: 24),
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
mainAxisAlignment: widget.mainAxisAlignment,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: <Widget>[
|
||||
image ?? Offstage(),
|
||||
Expanded(
|
||||
child: Padding(
|
||||
padding: EdgeInsets.only(left: image != null ? 12 : 0),
|
||||
child: Row(
|
||||
children: [
|
||||
Flexible(
|
||||
child: Text(
|
||||
widget.displayItem?.call(item) ?? item.toString(),
|
||||
softWrap: true,
|
||||
style: TextStyle(
|
||||
fontSize: 16,
|
||||
fontFamily: 'Lato',
|
||||
fontWeight: FontWeight.w700,
|
||||
color: Theme.of(context)
|
||||
.primaryTextTheme
|
||||
.headline6!
|
||||
.color!,
|
||||
decoration: TextDecoration.none,
|
||||
),
|
||||
),
|
||||
),
|
||||
if (tag != null)
|
||||
Align(
|
||||
alignment: Alignment.topCenter,
|
||||
child: Container(
|
||||
width: 35.0,
|
||||
height: 18.0,
|
||||
child: Center(
|
||||
child: Text(
|
||||
tag,
|
||||
style: TextStyle(
|
||||
fontSize: 7.0,
|
||||
fontFamily: 'Lato',
|
||||
color: Theme.of(context)
|
||||
.textTheme
|
||||
.bodyText2!
|
||||
.color!),
|
||||
),
|
||||
),
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(6.0),
|
||||
//border: Border.all(color: ),
|
||||
color: Theme.of(context)
|
||||
.textTheme
|
||||
.bodyText2!
|
||||
.decorationColor!,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
Icon(Icons.check_circle, color: Theme.of(context).accentTextTheme.bodyText1!.color!),
|
||||
],
|
||||
Icon(Icons.check_circle,
|
||||
color: Theme.of(context).accentTextTheme.bodyText1!.color!),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
|
|
@ -5,7 +5,8 @@ import 'package:cake_wallet/src/screens/new_wallet/widgets/select_button.dart';
|
|||
import 'package:cake_wallet/src/screens/seed_language/widgets/seed_language_picker.dart';
|
||||
|
||||
class SeedLanguageSelector extends StatefulWidget {
|
||||
SeedLanguageSelector({Key? key, required this.initialSelected}) : super(key: key);
|
||||
SeedLanguageSelector({Key? key, required this.initialSelected})
|
||||
: super(key: key);
|
||||
|
||||
final String initialSelected;
|
||||
|
||||
|
@ -30,21 +31,20 @@ class SeedLanguageSelectorState extends State<SeedLanguageSelector> {
|
|||
S.current.seed_language_italian,
|
||||
];
|
||||
String selected;
|
||||
final _pickerKey = GlobalKey<SeedLanguagePickerState>();
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return SelectButton(
|
||||
image: null,
|
||||
text: seedLocales[seedLanguages.indexOf(selected)],
|
||||
onTap: () async {
|
||||
final selected = await showPopUp<String>(
|
||||
context: context,
|
||||
builder: (BuildContext context) =>
|
||||
SeedLanguagePicker(key: _pickerKey, selected: this.selected));
|
||||
if (selected != null) {
|
||||
setState(() => this.selected = selected);
|
||||
}
|
||||
});
|
||||
image: null,
|
||||
text: seedLocales[seedLanguages.indexOf(selected)],
|
||||
onTap: () async {
|
||||
await showPopUp<String>(
|
||||
context: context,
|
||||
builder: (_) => SeedLanguagePicker(
|
||||
selected: this.selected,
|
||||
onItemSelected: (String selected) =>
|
||||
setState(() => this.selected = selected)));
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue