I'm trying to make the phone number field in the design. I'm using the intl_phone_number_input package for this but I couldn't do it like in my design.
I would be glad if you can help with this.
My design:
My Output:
My code:
InternationalPhoneNumberInput(
hintText: 'Telefon Numarası',
onInputChanged: (PhoneNumber number) {
print(number.phoneNumber);
},
onInputValidated: (bool value) {
print(value);
},
ignoreBlank: false,
autoValidateMode: AutovalidateMode.disabled,
selectorTextStyle: TextStyle(
color: Colors.black,
backgroundColor: Colors.grey,
),
selectorConfig: const SelectorConfig(
selectorType: PhoneInputSelectorType.DROPDOWN,
setSelectorButtonAsPrefixIcon: true,
leadingPadding: 0,
showFlags: false,
trailingSpace: false),
initialValue: PhoneNumber(isoCode: 'TR'),
textFieldController: TextEditingController(),
formatInput: false,
keyboardType: TextInputType.numberWithOptions(
signed: true, decimal: true),
inputBorder: UnderlineInputBorder(),
inputDecoration: InputDecoration(
floatingLabelAlignment: FloatingLabelAlignment.start,
labelText: 'Telefon Numarası',
),
textStyle: AppTextStyle().getSfProDisplayMedium(Colors.black),
onSaved: (PhoneNumber number) {
print('On Saved: $number');
},
),
I think we can use a combination of two types widget, I try use Stack
And this is my UI:
My code:
Padding(
padding: const EdgeInsets.all(20.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text(
'Telefon Numarası',
style: TextStyle(color: Colors.grey),
),
Container(
decoration: const BoxDecoration(
border: Border(bottom: BorderSide(width: 1, color: Colors.grey))
),
child: Stack(
children: [
Positioned(
bottom: 10,
top: 10,
left: 0,
child: Container(
height: 30,
width: 80,
decoration: BoxDecoration(
color: Colors.grey.shade300,
borderRadius: BorderRadius.circular(5),
),
child: Row(
children: const [
Spacer(),
Icon(CupertinoIcons.chevron_down, size: 16,),
SizedBox(width: 5,),
],
),
),
),
SizedBox(
height: 50,
child: InternationalPhoneNumberInput(
hintText: 'Telefon Numarası',
onInputChanged: (PhoneNumber number) {
print(number.phoneNumber);
},
onInputValidated: (bool value) {
print(value);
},
ignoreBlank: false,
autoValidateMode: AutovalidateMode.disabled,
selectorTextStyle: const TextStyle(
color: Colors.black,
),
selectorConfig: const SelectorConfig(
selectorType: PhoneInputSelectorType.BOTTOM_SHEET,
setSelectorButtonAsPrefixIcon: false,
leadingPadding: 10,
showFlags: false,
trailingSpace: true,
),
initialValue: PhoneNumber(isoCode: 'TR'),
textFieldController: TextEditingController(),
formatInput: false,
keyboardType: TextInputType.numberWithOptions(
signed: true, decimal: true),
inputDecoration: const InputDecoration(
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(color: Colors.transparent)
),
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(color: Colors.transparent)
),
floatingLabelAlignment: FloatingLabelAlignment.start,
// labelText: 'Telefon Numarası',
),
textStyle: const TextStyle(color: Colors.black),
onSaved: (PhoneNumber number) {
print('On Saved: $number');
},
),
),
],
),
),
],
),
),
Related
I am using country_picker for drop-down-menu.
And I need to reduce height of this menu. How can I do this?
And how to get border to showCountryPicker?
This is what I want
And this what I get
I tried to add bottomSheetHeight, but it hides my bottom buttons.
And without bottomSheetHeigh the drop-down-menu is in full screen mode
This is my code:
Expanded(
child: Padding(
padding: const EdgeInsets.only(left: 12, right: 12),
child: TextFormField(
controller: _country,
readOnly: true,
onTap: () {
showCountryPicker(
context: context,
showWorldWide: false,
showPhoneCode: false,
showSearch: false,
countryListTheme: CountryListThemeData(
backgroundColor: AppColors.backgroundColor,
borderRadius: BorderRadius.circular(8),
bottomSheetHeight: 380,
flagSize: 0,
textStyle: TextStyle(
color: AppColors.grayA0A0A0,
fontSize: 18,
height: 2.0
)
),
onSelect: (Country country) {
log(country.toString());
}
);
},
decoration: InputDecoration(
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(10.0),
borderSide: const BorderSide(width: 0)),
focusedBorder: OutlineInputBorder(
borderSide: const BorderSide(width: 1, color: AppColors.darkGray),
borderRadius: BorderRadius.circular(10)),
hintText: "Choose a country",
hintStyle: const TextStyle(
color: AppColors.grayA0A0A0, fontWeight: FontWeight.w500),
filled: true,
fillColor: AppColors.lightDark,
contentPadding:
const EdgeInsets.only(left: 8, bottom: 20, top: 20),
prefixIcon: InkWell(
child: SvgPicture.asset(
"assets/icons/Country.svg",
color: AppColors.grayA0A0A0,
height: 14,
width: 18,
fit: BoxFit.scaleDown,
),
),
suffixIcon: InkWell(
child: SvgPicture.asset(
"assets/icons/arrow_down.svg",
color: AppColors.grayA0A0A0,
height: 14,
width: 18,
fit: BoxFit.scaleDown,
),
)
),
),
),
),
Row(
children: <Widget>[
Expanded(
flex: 1,
//SizedBox(height: 20.0),
child: CountryPicker(
dense: true,
showFlag: false, //displays flag, true by default
showDialingCode:
true, //displays dialing code, false by default
showName: true, //displays country name, true by default
showCurrency: false, //eg. 'British pound'
showCurrencyISO: false,
onChanged: (Country country) {
setState(() => _selected = country);
print(country.dialingCode);
countryCode = country.dialingCode;
},
selectedCountry: _selected,
),
),
Expanded(
flex: 3,
//SizedBox(height: 20.0),
child: TextFormField(
decoration: InputDecoration(
labelText: 'Mobile no.',
border: OutlineInputBorder(),
),
validator: (val) => val.length != 10
? 'Enter a mobile number of 10 digits'
: null,
onChanged: (val) {
setState(() => phone = val);
phoneno = phone;
},
),
),
],
),
I'm trying to get the image in the picture. However, the problem is: I can't show the error message below the line. When I show the error message, it looks like this and gives an error.
What properties can I use to achieve this to get the image in the design? I would be glad if you help
Can we change the position of the error message in Flutter? Can you help me with this?
DESIGN;
My Code:
Padding(
padding: const EdgeInsets.all(20.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text(
'Telefon Numarası',
style: TextStyle(color: Colors.grey),
),
Container(
decoration: const BoxDecoration(
border: Border(bottom: BorderSide(width: 1, color: Colors.grey))
),
child: Stack(
children: [
Positioned(
bottom: 10,
top: 10,
left: 0,
child: Container(
height: 30,
width: 80,
decoration: BoxDecoration(
color: Colors.grey.shade300,
borderRadius: BorderRadius.circular(5),
),
child: Row(
children: const [
Spacer(),
Icon(CupertinoIcons.chevron_down, size: 16,),
SizedBox(width: 5,),
],
),
),
),
SizedBox(
height: 50,
child: InternationalPhoneNumberInput(
hintText: 'Telefon Numarası',
onInputChanged: (PhoneNumber number) {
print(number.phoneNumber);
},
onInputValidated: (bool value) {
print(value);
},
ignoreBlank: false,
autoValidateMode: AutovalidateMode.disabled,
selectorTextStyle: const TextStyle(
color: Colors.black,
),
selectorConfig: const SelectorConfig(
selectorType: PhoneInputSelectorType.BOTTOM_SHEET,
setSelectorButtonAsPrefixIcon: false,
leadingPadding: 10,
showFlags: false,
trailingSpace: true,
),
initialValue: PhoneNumber(isoCode: 'TR'),
textFieldController: TextEditingController(),
formatInput: false,
keyboardType: TextInputType.numberWithOptions(
signed: true, decimal: true),
inputDecoration: const InputDecoration(
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(color: Colors.transparent)
),
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(color: Colors.transparent)
),
floatingLabelAlignment: FloatingLabelAlignment.start,
// labelText: 'Telefon Numarası',
),
textStyle: const TextStyle(color: Colors.black),
onSaved: (PhoneNumber number) {
print('On Saved: $number');
},
),
),
],
),
),
],
),
),
MY OUTPUT;
here the error message should come under the line at the bottom
DropdownSearch<T>(
dropdownBuilder: (context, data) {
return AutoSizeText(
displayProperty(data) ?? "",
maxLines: 1,
style: const TextStyle(fontWeight: FontWeight.w400, fontSize: 16),
);
},
popupProps: PopupProps.menu(
fit: FlexFit.loose,
// showSelectedItems: true,
// interceptCallBacks: true,
itemBuilder: popupItemBuilder ??
(context, data, selected) {
return Container(
margin: const EdgeInsets.symmetric(horizontal: 8),
decoration: const BoxDecoration(
border: Border(bottom: BorderSide(color: Colors.black12)),
),
child: ListTile(
title: Text(
displayProperty(data) ?? "",
maxLines: 1,
style: AppTheme.subtitle1,
),
),
);
},
showSearchBox: showSearchBox,
emptyBuilder: (context, data) => Padding(
padding: const EdgeInsets.all(8.0),
child: Center(
child: Text("No Data in $label was found."),
),
),
),
asyncItems: (String? data) => getData(),
// focusNode: focusNode,
onSaved: onSaved,
selectedItem: value,
validator: !isRequired
? null
: validator ??
(value) => value == null ? "$label can't be empty" : null,
// mode: Mode.MENU,
// showClearButton: enable,
key: keyX,
enabled: enable,
// maxHeight: maxHeight,
dropdownDecoratorProps: DropDownDecoratorProps(
dropdownSearchDecoration: InputDecoration(
labelText: label,
errorMaxLines: 2,
isDense: false,
enabledBorder: const OutlineInputBorder(
borderSide: BorderSide(color: Colors.black45)),
// border: const OutlineInputBorder(),
errorBorder: const OutlineInputBorder(
borderSide: BorderSide(color: Colors.red),
),
focusedBorder: const OutlineInputBorder(
borderSide: BorderSide(color: Colors.lightGreen),
),
),
),
itemAsString: (data) => displayProperty(data) ?? "",
onChanged: onChanged,
);
I added mine like this and it worked.
DropdownSearch<dynamic>(
popupProps: const PopupProps.menu(
showSearchBox: true,
searchFieldProps: TextFieldProps(
decoration: InputDecoration(
border: OutlineInputBorder(),
contentPadding:
EdgeInsets.fromLTRB(12, 12, 8, 0),
hintText: "search staff...",
),
)),
its empty because you build the field with empty string.
displayProperty(data) ?? "", this is return empty string when data is null.
DropdownSearch<T>(
dropdownBuilder: (context, data) {
return AutoSizeText(
displayProperty(data) ?? "your Hint Text here",
maxLines: 1,
style: const TextStyle(fontWeight: FontWeight.w400, fontSize: 16),
);
},
.......
UPDATE
if you want to add hint text on popup search field you can add this to you code
searchBoxDecoration: InputDecoration(
border: OutlineInputBorder(),
contentPadding: EdgeInsets.fromLTRB(12, 12, 8, 0),
hintText: "hint goes here",
)
you can found it from plugin owner : https://github.com/salim-lachdhaf/searchable_dropdown/issues/138#issuecomment-808702346
I have a login system working with Flutter, PHP, and SQL but I want to be able to display the errors (if any) as a Flushbar. The controller receives the error as (res["message"]) and i would like this to be displayed on the register page but i cant seem to get it to work
Here is the controller that is called on click
void register() async {
try {
var response = await http
.post(Uri.parse("http://noddospls/untitled/authentication/register.php"), body: {
"name" : nameTE.text,
"username": emailTE.text,
"password": passwordTE.text
});
print(response.body);
var res = json.decode(response.body);
var success = (res["success"]);
print (success);
if (formKey.currentState!.validate()) {
if (success == "false"){
//display error from api (res["message"])
} else if (success == "true") {
Navigator.of(context, rootNavigator: true).push(
MaterialPageRoute(
builder: (context) => LogInScreen(),
),
);
}
}
}catch(e){
print(e);
}
}
and here is my page that the controller is called from
Widget build(BuildContext context) {
return FxBuilder<RegisterController>(
controller: controller,
builder: (controller) {
return Scaffold(
body: Padding(
padding: FxSpacing.fromLTRB(
20, FxSpacing.safeAreaTop(context) + 20, 20, 20),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
FxText.h3(
'Sign up',
fontWeight: 700,
),
FxSpacing.height(20),
Form(
key: controller.formKey,
child: Column(
children: [
TextFormField(
style: FxTextStyle.b2(),
decoration: InputDecoration(
floatingLabelBehavior:
FloatingLabelBehavior.never,
filled: true,
isDense: true,
fillColor: customTheme.card,
prefixIcon: Icon(
FeatherIcons.user,
color: theme.colorScheme.onBackground,
),
hintText: "Name",
enabledBorder: outlineInputBorder,
focusedBorder: outlineInputBorder,
border: outlineInputBorder,
contentPadding: FxSpacing.all(16),
hintStyle: FxTextStyle.b2(),
isCollapsed: true),
maxLines: 1,
controller: controller.nameTE,
validator: controller.validateName,
cursorColor: theme.colorScheme.onBackground,
),
FxSpacing.height(20),
TextFormField(
style: FxTextStyle.b2(),
decoration: InputDecoration(
floatingLabelBehavior:
FloatingLabelBehavior.never,
filled: true,
isDense: true,
fillColor: customTheme.card,
prefixIcon: Icon(
FeatherIcons.mail,
color: theme.colorScheme.onBackground,
),
hintText: "Email Address",
enabledBorder: outlineInputBorder,
focusedBorder: outlineInputBorder,
border: outlineInputBorder,
contentPadding: FxSpacing.all(16),
hintStyle: FxTextStyle.b2(),
isCollapsed: true),
maxLines: 1,
controller: controller.emailTE,
validator: controller.validateEmail,
cursorColor: theme.colorScheme.onBackground,
),
FxSpacing.height(20),
TextFormField(
style: FxTextStyle.b2(),
decoration: InputDecoration(
floatingLabelBehavior:
FloatingLabelBehavior.never,
filled: true,
isDense: true,
fillColor: customTheme.card,
prefixIcon: Icon(
FeatherIcons.lock,
color: theme.colorScheme.onBackground,
),
hintText: "Password",
enabledBorder: outlineInputBorder,
focusedBorder: outlineInputBorder,
border: outlineInputBorder,
contentPadding: FxSpacing.all(16),
hintStyle: FxTextStyle.b2(),
isCollapsed: true),
maxLines: 1,
controller: controller.passwordTE,
validator: controller.validatePassword,
cursorColor: theme.colorScheme.onBackground,
),
FxSpacing.height(20),
TextFormField(
style: FxTextStyle.b2(),
decoration: InputDecoration(
floatingLabelBehavior:
FloatingLabelBehavior.never,
filled: true,
isDense: true,
fillColor: customTheme.card,
prefixIcon: Icon(
FeatherIcons.lock,
color: theme.colorScheme.onBackground,
),
hintText: "Re-type Password",
enabledBorder: outlineInputBorder,
focusedBorder: outlineInputBorder,
border: outlineInputBorder,
contentPadding: FxSpacing.all(16),
hintStyle: FxTextStyle.b2(),
isCollapsed: true),
maxLines: 1,
controller: controller.password2TE,
validator: controller.validatePassword,
cursorColor: theme.colorScheme.onBackground,
),
],
),
),
FxSpacing.height(24),
Row(
children: [
FxText.b3(
'By Signing up, you agree to our ',
fontSize: 11,
),
FxText.b3(
'Terms & Conditions',
color: customTheme.fitnessPrimary,
fontSize: 11,
),
],
),
FxSpacing.height(24),
Row(
children: [
FxButton(
padding: FxSpacing.xy(16, 12),
onPressed: () {
controller.register();
},
backgroundColor: customTheme.card,
splashColor:
theme.colorScheme.onBackground.withAlpha(40),
elevation: 0,
borderRadiusAll: 4,
child: Row(
children: [
Image(
image: AssetImage(Images.google),
height: 17,
width: 17,
),
FxSpacing.width(20),
FxText.l2(
'Login with Google',
fontWeight: 600,
color: theme.colorScheme.onBackground,
),
],
)),
FxSpacing.width(20),
Expanded(
child: FxButton(
padding: FxSpacing.y(12),
onPressed: () {
controller.register();
},
backgroundColor: customTheme.fitnessPrimary,
elevation: 0,
borderRadiusAll: 4,
child: FxText.b2(
'Continue',
color: customTheme.fitnessOnPrimary,
fontWeight: 600,
),
),
),
],
),
FxSpacing.height(20),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
FxText.b3(
'Already have an account? ',
),
InkWell(
onTap: () {
controller.goToLogInScreen();
},
child: FxText.b3(
'Log In',
color: customTheme.fitnessPrimary,
)),
],
),
],
),
),
);
});
}
}
Any help appreciated
This is what I have currently:
My design / what I want it to be:
This is my code and this sized box is a part of a column which is a part of a form:
SizedBox(
height: 80.0,
child: Stack(alignment: Alignment.centerRight, children: [
TextFormField(
controller: null,
style: const TextStyle(color: Colors.white),
maxLength: 2,
decoration: InputDecoration(
fillColor: const Color(0xff353251),
filled: true,
hintText: 'ex. 5 hours',
contentPadding: const EdgeInsets.all(20.0),
hintStyle: const TextStyle(color: Colors.white24),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(15.0)))),
DropdownButton(
value: goalValue,
dropdownColor: const Color(0xff403A4F),
style: const TextStyle(color: Colors.white),
onChanged: (String? value) {
setState(() {
goalValue = value!;
});
},
items: <String>['Per Week', 'Per Day', 'Per Month']
.map<DropdownMenuItem<String>>((String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(value),
);
}).toList()),
]),
),
Thanks in advance!
Instead of Stack, I am using Container for outer decoration and Row for placing two widgets. There are many changes occur during styling the property and used random color, play with styling.
Now The result is
Container(
alignment: Alignment.center,
padding: const EdgeInsets.only(left: 16),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(15.0),
color: Color(0xff353251),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
const Flexible(
flex: 2,
child: TextField(
controller: null,
style: TextStyle(color: Colors.white),
maxLength: 2,
buildCounter: null,
decoration: InputDecoration(
fillColor: Color(0xff353251),
filled: true,
counterText: "",
hintText: 'ex. 5 hours',
contentPadding: EdgeInsets.only(right: 4),
hintStyle: TextStyle(color: Colors.white24),
border: InputBorder.none,
focusedBorder: InputBorder.none,
enabledBorder: InputBorder.none,
errorBorder: InputBorder.none,
),
),
),
Flexible(
flex: 1,
child: Container(
padding: EdgeInsets.only(right: 16, left: 16),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(15.0),
color: Colors.purpleAccent,
),
child: Theme(
data: Theme.of(context).copyWith(
canvasColor: Colors.purpleAccent,
),
child: DropdownButton(
borderRadius: BorderRadius.circular(15.0),
underline: const SizedBox(),
icon: const SizedBox(),
value: goalValue,
style: const TextStyle(color: Colors.white),
hint: const Text(
"select",
style: TextStyle(color: Colors.white),
),
onChanged: (String? value) {
setState(() {
goalValue = value!;
});
},
items: <String>['Per Week', 'Per Day', 'Per Month']
.map<DropdownMenuItem<String>>((String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(value),
);
}).toList()),
),
),
),
],
),
),