Skip to content

Commit

Permalink
Add country button style (#233)
Browse files Browse the repository at this point in the history
* saving

* slots

* saving

* saving

* country button style

* saving

* country button style
  • Loading branch information
cedvdb committed Mar 27, 2024
1 parent 218848c commit cfe5986
Show file tree
Hide file tree
Showing 10 changed files with 119 additions and 58 deletions.
8 changes: 6 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
## [9.1.1]
## [9.2.0]
- add missing translation messages
- add Hungarian localization messages
- fix RTL
- added `showDropdownIndicator`
- deprecate country button stylings properties in favor of one `countryButtonStyle` property
- add showDropdownIcon bool

## [9.1.0]

Expand Down Expand Up @@ -33,7 +37,7 @@
- Added some missing countries
- [Breaking] : no validation done by default
- [Breaking] : provided validators now require a context parameter
- [Breaking] : `LocalizedCountryRegistry` removed. If you were using it to localize a country name, you should use `PhoneFieldLocalization.of(context).countryName(isoCode)`.
- [Breaking] : `LocalizedCountryRegistry` removed. If you were using it to localize a country name, you should use `CountrySelectorLocalization.of(context).countryName(isoCode)`.
- [Deprecated] : `isCountryChipPersistent` in favor of `isCountryButtonPersistent`.
- [Deprecated] : `shouldFormat`, it is now always ON by default
- [Deprecated] : `defaultCountry`, you should now use either `initialValue` or provide a controller with an initial value.
Expand Down
8 changes: 6 additions & 2 deletions example/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,12 @@ class PhoneFieldView extends StatelessWidget {
hintText: withLabel ? '' : 'Phone',
),
enabled: true,
showIsoCodeInInput: false,
showFlagInInput: true,
countryButtonStyle: const CountryButtonStyle(
showFlag: true,
showIsoCode: false,
showDialCode: true,
showDropdownIcon: true,
),
validator: _getValidator(context),
autovalidateMode: AutovalidateMode.onUserInteraction,
cursorColor: Theme.of(context).colorScheme.primary,
Expand Down
6 changes: 3 additions & 3 deletions example/pubspec.lock
Original file line number Diff line number Diff line change
Expand Up @@ -222,15 +222,15 @@ packages:
path: ".."
relative: true
source: path
version: "9.0.5"
version: "9.1.1"
phone_numbers_parser:
dependency: transitive
description:
name: phone_numbers_parser
sha256: d0dad4f5b61c3d959b069df088ef7242ffed42a3cf74c7549fd7c324e1eb964e
sha256: ebe08725e63218a6ae2bf9129b7130332cb2ababa4988f07d6ddce48b0c21e06
url: "https://pub.dev"
source: hosted
version: "8.1.3"
version: "8.2.1"
sky_engine:
dependency: transitive
description: flutter
Expand Down
1 change: 1 addition & 0 deletions lib/phone_form_field.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ library phone_number_input;
export 'src/phone_form_field.dart';
export 'src/country_selector_navigator.dart';
export 'src/country_button.dart';
export 'src/country_button_style.dart';

export 'src/validation/phone_validator.dart';
export 'src/localization/localization.dart';
Expand Down
18 changes: 9 additions & 9 deletions lib/src/country_button.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,33 +8,33 @@ typedef CountryChip = CountryButton;
class CountryButton extends StatelessWidget {
final Function()? onTap;
final IsoCode isoCode;
final bool showFlag;
final bool showDialCode;
final TextStyle? textStyle;
final EdgeInsets padding;
final double flagSize;
final TextDirection? textDirection;
final bool showFlag;
final bool showDialCode;
final bool showIsoCode;
final bool showDropdownIcon;
final bool enabled;

const CountryButton({
super.key,
required this.isoCode,
required this.onTap,
this.textStyle,
this.showFlag = true,
this.showDialCode = true,
this.padding = const EdgeInsets.fromLTRB(12, 16, 4, 16),
this.flagSize = 20,
this.textDirection,
this.showFlag = true,
this.showDialCode = true,
this.showIsoCode = false,
this.showDropdownIcon = true,
this.enabled = true,
});

@override
Widget build(BuildContext context) {
final textStyle = this.textStyle ??
Theme.of(context).textTheme.labelMedium ??
Theme.of(context).textTheme.bodyMedium?.copyWith(fontSize: 16) ??
const TextStyle();
final countryLocalization = CountrySelectorLocalization.of(context) ??
CountrySelectorLocalizationEn();
Expand Down Expand Up @@ -71,10 +71,10 @@ class CountryButton extends StatelessWidget {
style: textStyle.copyWith(
color: enabled ? null : Theme.of(context).disabledColor,
),
textDirection: textDirection,
),
],
const ExcludeSemantics(child: Icon(Icons.arrow_drop_down)),
if (showDropdownIcon)
const ExcludeSemantics(child: Icon(Icons.arrow_drop_down)),
],
),
),
Expand Down
57 changes: 57 additions & 0 deletions lib/src/country_button_style.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import 'package:flutter/material.dart';

class CountryButtonStyle {
/// Text style of the country dial code inside the country button
final TextStyle? textStyle;

/// padding inside country button,
/// this can be used to align the country button with the phone number
/// and is mostly useful when using [isCountryButtonPersistent] as true.
final EdgeInsets? padding;

/// The radius of the flag in the country button
final double flagSize;

/// Wether to show the country flag in the country button
final bool showFlag;

/// Whether to show Dial Code in the country button
/// setting this to false will hide, for example, (+1)
final bool showDialCode;

/// Wether to show the country iso code in the country button
final bool showIsoCode;

/// Wether to show the dropdown icon in the country button
final bool showDropdownIcon;

const CountryButtonStyle({
this.textStyle,
this.padding,
this.flagSize = 20,
this.showFlag = true,
this.showDialCode = true,
this.showIsoCode = false,
this.showDropdownIcon = true,
});

CountryButtonStyle copyWith({
TextStyle? textStyle,
EdgeInsets? padding,
double? flagSize,
bool? showFlag,
bool? showDialCode,
bool? showIsoCode,
bool? showDropdownIcon,
}) {
return CountryButtonStyle(
textStyle: textStyle ?? this.textStyle,
padding: padding ?? this.padding,
flagSize: flagSize ?? this.flagSize,
showFlag: showFlag ?? this.showFlag,
showDialCode: showDialCode ?? this.showDialCode,
showIsoCode: showIsoCode ?? this.showIsoCode,
showDropdownIcon: showDropdownIcon ?? this.showDropdownIcon,
);
}
}
41 changes: 18 additions & 23 deletions lib/src/phone_form_field.dart
Original file line number Diff line number Diff line change
Expand Up @@ -49,11 +49,6 @@ class PhoneFormField extends FormField<PhoneNumber> {
/// how to display the country selection
final CountrySelectorNavigator countrySelectorNavigator;

/// padding inside country button,
/// this can be used to align the country button with the phone number
/// and is mostly useful when using [isCountryButtonPersistent] as true.
final EdgeInsets? countryButtonPadding;

/// whether the user can select a new country when pressing the country button
final bool isCountrySelectionEnabled;

Expand All @@ -63,24 +58,14 @@ class PhoneFormField extends FormField<PhoneNumber> {
/// the text field.
final bool isCountryButtonPersistent;

/// show Dial Code or not in the country button
final bool showDialCode;

/// show selected iso code or not in the country button
final bool showIsoCodeInInput;

/// The size of the flag inside the country button
final double flagSize;

/// whether the flag is shown inside the country button
final bool showFlagInInput;
/// The style of the country selector button
final CountryButtonStyle countryButtonStyle;

// textfield inputs
final InputDecoration decoration;
final TextInputType keyboardType;
final TextInputAction? textInputAction;
final TextStyle? style;
final TextStyle? countryCodeStyle;
final StrutStyle? strutStyle;
final TextAlign? textAlign;
final TextAlignVertical? textAlignVertical;
Expand Down Expand Up @@ -122,19 +107,22 @@ class PhoneFormField extends FormField<PhoneNumber> {
this.shouldFormat = true,
this.onChanged,
this.focusNode,
this.showFlagInInput = true,
this.countrySelectorNavigator = const CountrySelectorNavigator.page(),
@Deprecated(
'Use [initialValue] or [controller] to set the initial phone number')
this.defaultCountry = IsoCode.US,
this.flagSize = 16,
this.isCountrySelectionEnabled = true,
bool? isCountryButtonPersistent,
@Deprecated('Use [isCountryButtonPersistent]')
bool? isCountryChipPersistent,
this.showDialCode = true,
this.showIsoCodeInInput = false,
this.countryButtonPadding,
@Deprecated('Use [CountryButtonStyle] instead') bool? showFlagInInput,
@Deprecated('Use [CountryButtonStyle] instead') bool? showDialCode,
@Deprecated('Use [CountryButtonStyle] instead') bool? showIsoCodeInInput,
@Deprecated('Use [CountryButtonStyle] instead')
EdgeInsets? countryButtonPadding,
@Deprecated('Use [CountryButtonStyle] instead') double? flagSize,
@Deprecated('Use [CountryButtonStyle] instead') TextStyle? countryCodeStyle,
CountryButtonStyle countryButtonStyle = const CountryButtonStyle(),
// form field inputs
super.validator,
PhoneNumber? initialValue,
Expand All @@ -147,7 +135,6 @@ class PhoneFormField extends FormField<PhoneNumber> {
this.keyboardType = TextInputType.phone,
this.textInputAction,
this.style,
this.countryCodeStyle,
this.strutStyle,
@Deprecated('Has no effect, Change text directionality instead')
this.textAlign,
Expand Down Expand Up @@ -187,6 +174,14 @@ class PhoneFormField extends FormField<PhoneNumber> {
),
isCountryButtonPersistent =
isCountryButtonPersistent ?? isCountryChipPersistent ?? true,
countryButtonStyle = countryButtonStyle.copyWith(
showFlag: showFlagInInput,
showDialCode: showDialCode,
showIsoCode: showIsoCodeInInput,
padding: countryButtonPadding,
flagSize: flagSize,
textStyle: countryCodeStyle,
),
super(
builder: (state) => (state as PhoneFormFieldState).builder(),
initialValue: controller?.value ?? initialValue,
Expand Down
24 changes: 10 additions & 14 deletions lib/src/phone_form_field_state.dart
Original file line number Diff line number Diff line change
Expand Up @@ -175,16 +175,11 @@ class PhoneFormFieldState extends FormFieldState<PhoneNumber> {
isoCode: controller.value.isoCode,
onTap: widget.enabled ? _selectCountry : null,
padding: _computeCountryButtonPadding(context),
showFlag: widget.showFlagInInput,
showIsoCode: widget.showIsoCodeInInput,
showDialCode: widget.showDialCode,
textStyle: widget.countryCodeStyle ??
widget.decoration.labelStyle ??
TextStyle(
fontSize: 16,
color: Theme.of(context).textTheme.bodySmall?.color,
),
flagSize: widget.flagSize,
showFlag: widget.countryButtonStyle.showFlag,
showIsoCode: widget.countryButtonStyle.showIsoCode,
showDialCode: widget.countryButtonStyle.showDialCode,
textStyle: widget.countryButtonStyle.textStyle,
flagSize: widget.countryButtonStyle.flagSize,
enabled: widget.enabled,
),
),
Expand All @@ -201,7 +196,7 @@ class PhoneFormFieldState extends FormFieldState<PhoneNumber> {
/// - is country button shown as a prefix or prefixIcon (isCountryChipPersistent)
/// - text direction
EdgeInsets _computeCountryButtonPadding(BuildContext context) {
final countryButtonPadding = widget.countryButtonPadding;
final userDefinedPadding = widget.countryButtonStyle.padding;
final isUnderline = widget.decoration.border is UnderlineInputBorder;
final hasLabel =
widget.decoration.label != null || widget.decoration.labelText != null;
Expand All @@ -210,9 +205,10 @@ class PhoneFormFieldState extends FormFieldState<PhoneNumber> {
EdgeInsets padding = isLtr
? const EdgeInsets.fromLTRB(12, 16, 4, 16)
: const EdgeInsets.fromLTRB(4, 16, 12, 16);
if (countryButtonPadding != null) {
padding = countryButtonPadding;
} else if (!widget.isCountryButtonPersistent) {
if (userDefinedPadding != null) {
return userDefinedPadding;
}
if (!widget.isCountryButtonPersistent) {
padding = isLtr
? const EdgeInsets.only(right: 4, left: 12)
: const EdgeInsets.only(left: 4, right: 12);
Expand Down
2 changes: 1 addition & 1 deletion pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name: phone_form_field
description: Flutter phone input integrated with flutter internationalization
version: 9.1.1
version: 9.2.0
homepage: https://github.com/cedvdb/phone_form_field

environment:
Expand Down
12 changes: 8 additions & 4 deletions test/phone_form_field_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,10 @@ void main() {
onChanged: onChanged,
onSaved: onSaved,
onTapOutside: onTapOutside,
showFlagInInput: showFlagInInput,
showDialCode: showDialCode,
countryButtonStyle: CountryButtonStyle(
showFlag: showFlagInInput,
showDialCode: showDialCode,
),
controller: controller,
validator: validatorBuilder?.call(context),
enabled: enabled,
Expand Down Expand Up @@ -167,13 +169,15 @@ void main() {
);
});

testWidgets('Should get value of controller as initial value', (tester) async {
testWidgets('Should get value of controller as initial value',
(tester) async {
final controller = PhoneController();
final phoneNumber = PhoneNumber.parse('+33488997722');
controller.value = phoneNumber;
await tester.pumpWidget(getWidget(controller: controller));

final PhoneFormFieldState phoneFieldState = tester.state(find.byType(PhoneFormField));
final PhoneFormFieldState phoneFieldState =
tester.state(find.byType(PhoneFormField));
expect(phoneFieldState.value, equals(phoneNumber));
});

Expand Down

0 comments on commit cfe5986

Please sign in to comment.