From 57e164caabfffc3a6be25462695b5ef22ef776c7 Mon Sep 17 00:00:00 2001 From: CocaPepsi Date: Sat, 22 May 2021 15:04:44 +0700 Subject: [PATCH 1/2] custom country code picker --- lib/country_codes.dart | 2427 ++++++++--------- lib/flag_phone_number.dart | 235 ++ lib/flag_phone_number_bottom_sheet.dart | 271 ++ .../bottom_sheet_component.dart | 77 + .../bottom_sheet_service.dart | 60 + .../bottom_sheet_widget.dart | 227 ++ 6 files changed, 2061 insertions(+), 1236 deletions(-) create mode 100644 lib/flag_phone_number.dart create mode 100644 lib/flag_phone_number_bottom_sheet.dart create mode 100644 lib/widget/bottom_sheet_service/bottom_sheet_component.dart create mode 100644 lib/widget/bottom_sheet_service/bottom_sheet_service.dart create mode 100644 lib/widget/bottom_sheet_service/bottom_sheet_widget.dart diff --git a/lib/country_codes.dart b/lib/country_codes.dart index 993be09c..3c721083 100644 --- a/lib/country_codes.dart +++ b/lib/country_codes.dart @@ -1,1237 +1,1192 @@ List> codes = [ - { - "name": "افغانستان", - "code": "AF", - "dial_code": "+93", - }, - { - "name": "Åland", - "code": "AX", - "dial_code": "+358", - }, - { - "name": "Shqipëria", - "code": "AL", - "dial_code": "+355", - }, - { - "name": "الجزائر", - "code": "DZ", - "dial_code": "+213", - }, - { - "name": "American Samoa", - "code": "AS", - "dial_code": "+1684", - }, - { - "name": "Andorra", - "code": "AD", - "dial_code": "+376", - }, - { - "name": "Angola", - "code": "AO", - "dial_code": "+244", - }, - { - "name": "Anguilla", - "code": "AI", - "dial_code": "+1264", - }, - { - "name": "Antarctica", - "code": "AQ", - "dial_code": "+672", - }, - { - "name": "Antigua and Barbuda", - "code": "AG", - "dial_code": "+1268", - }, - { - "name": "Argentina", - "code": "AR", - "dial_code": "+54", - }, - { - "name": "Հայաստան", - "code": "AM", - "dial_code": "+374", - }, - { - "name": "Aruba", - "code": "AW", - "dial_code": "+297", - }, - { - "name": "Australia", - "code": "AU", - "dial_code": "+61", - }, - { - "name": "Österreich", - "code": "AT", - "dial_code": "+43", - }, - { - "name": "Azərbaycan", - "code": "AZ", - "dial_code": "+994", - }, - { - "name": "Bahamas", - "code": "BS", - "dial_code": "+1242", - }, - { - "name": "‏البحرين", - "code": "BH", - "dial_code": "+973", - }, - { - "name": "Bangladesh", - "code": "BD", - "dial_code": "+880", - }, - { - "name": "Barbados", - "code": "BB", - "dial_code": "+1246", - }, - { - "name": "Белару́сь", - "code": "BY", - "dial_code": "+375", - }, - { - "name": "België", - "code": "BE", - "dial_code": "+32", - }, - { - "name": "Belize", - "code": "BZ", - "dial_code": "+501", - }, - { - "name": "Bénin", - "code": "BJ", - "dial_code": "+229", - }, - { - "name": "Bermuda", - "code": "BM", - "dial_code": "+1441", - }, - { - "name": "ʼbrug-yul", - "code": "BT", - "dial_code": "+975", - }, - { - "name": "Bolivia", - "code": "BO", - "dial_code": "+591", - }, - { - "name": "Bosna i Hercegovina", - "code": "BA", - "dial_code": "+387", - }, - { - "name": "Botswana", - "code": "BW", - "dial_code": "+267", - }, - { - "name": "Bouvetøya", - "code": "BV", - "dial_code": "+47", - }, - { - "name": "Brasil", - "code": "BR", - "dial_code": "+55", - }, - { - "name": "British Indian Ocean Territory", - "code": "IO", - "dial_code": "+246", - }, - { - "name": "Negara Brunei Darussalam", - "code": "BN", - "dial_code": "+673", - }, - { - "name": "България", - "code": "BG", - "dial_code": "+359", - }, - { - "name": "Burkina Faso", - "code": "BF", - "dial_code": "+226", - }, - { - "name": "Burundi", - "code": "BI", - "dial_code": "+257", - }, - { - "name": "Cambodia", - "code": "KH", - "dial_code": "+855", - }, - { - "name": "Cameroon", - "code": "CM", - "dial_code": "+237", - }, - { - "name": "Canada", - "code": "CA", - "dial_code": "+1", - }, - { - "name": "Cabo Verde", - "code": "CV", - "dial_code": "+238", - }, - { - "name": "Cayman Islands", - "code": "KY", - "dial_code": "+1345", - }, - { - "name": "Ködörösêse tî Bêafrîka", - "code": "CF", - "dial_code": "+236", - }, - { - "name": "Tchad", - "code": "TD", - "dial_code": "+235", - }, - { - "name": "Chile", - "code": "CL", - "dial_code": "+56", - }, - { - "name": "中国", - "code": "CN", - "dial_code": "+86", - }, - { - "name": "Christmas Island", - "code": "CX", - "dial_code": "+61", - }, - { - "name": "Cocos (Keeling) Islands", - "code": "CC", - "dial_code": "+61", - }, - { - "name": "Colombia", - "code": "CO", - "dial_code": "+57", - }, - { - "name": "Komori", - "code": "KM", - "dial_code": "+269", - }, - { - "name": "République du Congo", - "code": "CG", - "dial_code": "+242", - }, - { - "name": "République démocratique du Congo", - "code": "CD", - "dial_code": "+243", - }, - { - "name": "Cook Islands", - "code": "CK", - "dial_code": "+682", - }, - { - "name": "Costa Rica", - "code": "CR", - "dial_code": "+506", - }, - { - "name": "Côte d'Ivoire", - "code": "CI", - "dial_code": "+225", - }, - { - "name": "Hrvatska", - "code": "HR", - "dial_code": "+385", - }, - { - "name": "Cuba", - "code": "CU", - "dial_code": "+53", - }, - { - "name": "Κύπρος", - "code": "CY", - "dial_code": "+357", - }, - { - "name": "Česká republika", - "code": "CZ", - "dial_code": "+420", - }, - { - "name": "Danmark", - "code": "DK", - "dial_code": "+45", - }, - { - "name": "Djibouti", - "code": "DJ", - "dial_code": "+253", - }, - { - "name": "Dominica", - "code": "DM", - "dial_code": "+1767", - }, - { - "name": "República Dominicana", - "code": "DO", - "dial_code": "+1", - }, - { - "name": "Ecuador", - "code": "EC", - "dial_code": "+593", - }, - { - "name": "مصر‎", - "code": "EG", - "dial_code": "+20", - }, - { - "name": "El Salvador", - "code": "SV", - "dial_code": "+503", - }, - { - "name": "Guinea Ecuatorial", - "code": "GQ", - "dial_code": "+240", - }, - { - "name": "ኤርትራ", - "code": "ER", - "dial_code": "+291", - }, - { - "name": "Eesti", - "code": "EE", - "dial_code": "+372", - }, - { - "name": "ኢትዮጵያ", - "code": "ET", - "dial_code": "+251", - }, - { - "name": "Falkland Islands", - "code": "FK", - "dial_code": "+500", - }, - { - "name": "Føroyar", - "code": "FO", - "dial_code": "+298", - }, - { - "name": "Fiji", - "code": "FJ", - "dial_code": "+679", - }, - { - "name": "Suomi", - "code": "FI", - "dial_code": "+358", - }, - { - "name": "France", - "code": "FR", - "dial_code": "+33", - }, - { - "name": "Guyane française", - "code": "GF", - "dial_code": "+594", - }, - { - "name": "Polynésie française", - "code": "PF", - "dial_code": "+689", - }, - { - "name": "Territoire des Terres australes et antarctiques fr", - "code": "TF", - "dial_code": "+262", - }, - { - "name": "Gabon", - "code": "GA", - "dial_code": "+241", - }, - { - "name": "Gambia", - "code": "GM", - "dial_code": "+220", - }, - { - "name": "საქართველო", - "code": "GE", - "dial_code": "+995", - }, - { - "name": "Deutschland", - "code": "DE", - "dial_code": "+49", - }, - { - "name": "Ghana", - "code": "GH", - "dial_code": "+233", - }, - { - "name": "Gibraltar", - "code": "GI", - "dial_code": "+350", - }, - { - "name": "Ελλάδα", - "code": "GR", - "dial_code": "+30", - }, - { - "name": "Kalaallit Nunaat", - "code": "GL", - "dial_code": "+299", - }, - { - "name": "Grenada", - "code": "GD", - "dial_code": "+1473", - }, - { - "name": "Guadeloupe", - "code": "GP", - "dial_code": "+590", - }, - { - "name": "Guam", - "code": "GU", - "dial_code": "+1671", - }, - { - "name": "Guatemala", - "code": "GT", - "dial_code": "+502", - }, - { - "name": "Guernsey", - "code": "GG", - "dial_code": "+44", - }, - { - "name": "Guinée", - "code": "GN", - "dial_code": "+224", - }, - { - "name": "Guiné-Bissau", - "code": "GW", - "dial_code": "+245", - }, - { - "name": "Guyana", - "code": "GY", - "dial_code": "+592", - }, - { - "name": "Haïti", - "code": "HT", - "dial_code": "+509", - }, - { - "name": "Heard Island and McDonald Islands", - "code": "HM", - "dial_code": "+0", - }, - { - "name": "Vaticano", - "code": "VA", - "dial_code": "+379", - }, - { - "name": "Honduras", - "code": "HN", - "dial_code": "+504", - }, - { - "name": "香港", - "code": "HK", - "dial_code": "+852", - }, - { - "name": "Magyarország", - "code": "HU", - "dial_code": "+36", - }, - { - "name": "Ísland", - "code": "IS", - "dial_code": "+354", - }, - { - "name": "भारत", - "code": "IN", - "dial_code": "+91", - }, - { - "name": "Indonesia", - "code": "ID", - "dial_code": "+62", - }, - { - "name": "ایران", - "code": "IR", - "dial_code": "+98", - }, - { - "name": "العراق", - "code": "IQ", - "dial_code": "+964", - }, - { - "name": "Éire", - "code": "IE", - "dial_code": "+353", - }, - { - "name": "Isle of Man", - "code": "IM", - "dial_code": "+44", - }, - { - "name": "ישראל", - "code": "IL", - "dial_code": "+972", - }, - { - "name": "Italia", - "code": "IT", - "dial_code": "+39", - }, - { - "name": "Jamaica", - "code": "JM", - "dial_code": "+1876", - }, - { - "name": "日本", - "code": "JP", - "dial_code": "+81", - }, - { - "name": "Jersey", - "code": "JE", - "dial_code": "+44", - }, - { - "name": "الأردن", - "code": "JO", - "dial_code": "+962", - }, - { - "name": "Қазақстан", - "code": "KZ", - "dial_code": "+7", - }, - { - "name": "Kenya", - "code": "KE", - "dial_code": "+254", - }, - { - "name": "Kiribati", - "code": "KI", - "dial_code": "+686", - }, - { - "name": "북한", - "code": "KP", - "dial_code": "+850", - }, - { - "name": "대한민국", - "code": "KR", - "dial_code": "+82", - }, - { - "name": "Republika e Kosovës", - "code": "XK", - "dial_code": "+383", - }, - { - "name": "الكويت", - "code": "KW", - "dial_code": "+965", - }, - { - "name": "Кыргызстан", - "code": "KG", - "dial_code": "+996", - }, - { - "name": "ສປປລາວ", - "code": "LA", - "dial_code": "+856", - }, - { - "name": "Latvija", - "code": "LV", - "dial_code": "+371", - }, - { - "name": "لبنان", - "code": "LB", - "dial_code": "+961", - }, - { - "name": "Lesotho", - "code": "LS", - "dial_code": "+266", - }, - { - "name": "Liberia", - "code": "LR", - "dial_code": "+231", - }, - { - "name": "‏ليبيا", - "code": "LY", - "dial_code": "+218", - }, - { - "name": "Liechtenstein", - "code": "LI", - "dial_code": "+423", - }, - { - "name": "Lietuva", - "code": "LT", - "dial_code": "+370", - }, - { - "name": "Luxembourg", - "code": "LU", - "dial_code": "+352", - }, - { - "name": "澳門", - "code": "MO", - "dial_code": "+853", - }, - { - "name": "Македонија", - "code": "MK", - "dial_code": "+389", - }, - { - "name": "Madagasikara", - "code": "MG", - "dial_code": "+261", - }, - { - "name": "Malawi", - "code": "MW", - "dial_code": "+265", - }, - { - "name": "Malaysia", - "code": "MY", - "dial_code": "+60", - }, - { - "name": "Maldives", - "code": "MV", - "dial_code": "+960", - }, - { - "name": "Mali", - "code": "ML", - "dial_code": "+223", - }, - { - "name": "Malta", - "code": "MT", - "dial_code": "+356", - }, - { - "name": "M̧ajeļ", - "code": "MH", - "dial_code": "+692", - }, - { - "name": "Martinique", - "code": "MQ", - "dial_code": "+596", - }, - { - "name": "موريتانيا", - "code": "MR", - "dial_code": "+222", - }, - { - "name": "Maurice", - "code": "MU", - "dial_code": "+230", - }, - { - "name": "Mayotte", - "code": "YT", - "dial_code": "+262", - }, - { - "name": "México", - "code": "MX", - "dial_code": "+52", - }, - { - "name": "Micronesia", - "code": "FM", - "dial_code": "+691", - }, - { - "name": "Moldova", - "code": "MD", - "dial_code": "+373", - }, - { - "name": "Monaco", - "code": "MC", - "dial_code": "+377", - }, - { - "name": "Монгол улс", - "code": "MN", - "dial_code": "+976", - }, - { - "name": "Црна Гора", - "code": "ME", - "dial_code": "+382", - }, - { - "name": "Montserrat", - "code": "MS", - "dial_code": "+1664", - }, - { - "name": "المغرب", - "code": "MA", - "dial_code": "+212", - }, - { - "name": "Moçambique", - "code": "MZ", - "dial_code": "+258", - }, - { - "name": "Myanmar", - "code": "MM", - "dial_code": "+95", - }, - { - "name": "Namibia", - "code": "NA", - "dial_code": "+264", - }, - { - "name": "Nauru", - "code": "NR", - "dial_code": "+674", - }, - { - "name": "नपल", - "code": "NP", - "dial_code": "+977", - }, - { - "name": "Nederland", - "code": "NL", - "dial_code": "+31", - }, - { - "name": "Netherlands Antilles", - "code": "AN", - "dial_code": "+599", - }, - { - "name": "Nouvelle-Calédonie", - "code": "NC", - "dial_code": "+687", - }, - { - "name": "New Zealand", - "code": "NZ", - "dial_code": "+64", - }, - { - "name": "Nicaragua", - "code": "NI", - "dial_code": "+505", - }, - { - "name": "Niger", - "code": "NE", - "dial_code": "+227", - }, - { - "name": "Nigeria", - "code": "NG", - "dial_code": "+234", - }, - { - "name": "Niuē", - "code": "NU", - "dial_code": "+683", - }, - { - "name": "Norfolk Island", - "code": "NF", - "dial_code": "+672", - }, - { - "name": "Northern Mariana Islands", - "code": "MP", - "dial_code": "+1670", - }, - { - "name": "Norge", - "code": "NO", - "dial_code": "+47", - }, - { - "name": "عمان", - "code": "OM", - "dial_code": "+968", - }, - { - "name": "Pakistan", - "code": "PK", - "dial_code": "+92", - }, - { - "name": "Palau", - "code": "PW", - "dial_code": "+680", - }, - { - "name": "فلسطين", - "code": "PS", - "dial_code": "+970", - }, - { - "name": "Panamá", - "code": "PA", - "dial_code": "+507", - }, - { - "name": "Papua Niugini", - "code": "PG", - "dial_code": "+675", - }, - { - "name": "Paraguay", - "code": "PY", - "dial_code": "+595", - }, - { - "name": "Perú", - "code": "PE", - "dial_code": "+51", - }, - { - "name": "Pilipinas", - "code": "PH", - "dial_code": "+63", - }, - { - "name": "Pitcairn Islands", - "code": "PN", - "dial_code": "+64", - }, - { - "name": "Polska", - "code": "PL", - "dial_code": "+48", - }, - { - "name": "Portugal", - "code": "PT", - "dial_code": "+351", - }, - { - "name": "Puerto Rico", - "code": "PR", - "dial_code": "+1939", - }, - { - "name": "Puerto Rico", - "code": "PR", - "dial_code": "+1787", - }, - { - "name": "قطر", - "code": "QA", - "dial_code": "+974", - }, - { - "name": "România", - "code": "RO", - "dial_code": "+40", - }, - { - "name": "Россия", - "code": "RU", - "dial_code": "+7", - }, - { - "name": "Rwanda", - "code": "RW", - "dial_code": "+250", - }, - { - "name": "La Réunion", - "code": "RE", - "dial_code": "+262", - }, - { - "name": "Saint-Barthélemy", - "code": "BL", - "dial_code": "+590", - }, - { - "name": "Saint Helena", - "code": "SH", - "dial_code": "+290", - }, - { - "name": "Saint Kitts and Nevis", - "code": "KN", - "dial_code": "+1869", - }, - { - "name": "Saint Lucia", - "code": "LC", - "dial_code": "+1758", - }, - { - "name": "Saint-Martin", - "code": "MF", - "dial_code": "+590", - }, - { - "name": "Saint-Pierre-et-Miquelon", - "code": "PM", - "dial_code": "+508", - }, - { - "name": "Saint Vincent and the Grenadines", - "code": "VC", - "dial_code": "+1784", - }, - { - "name": "Samoa", - "code": "WS", - "dial_code": "+685", - }, - { - "name": "San Marino", - "code": "SM", - "dial_code": "+378", - }, - { - "name": "São Tomé e Príncipe", - "code": "ST", - "dial_code": "+239", - }, - { - "name": "العربية السعودية", - "code": "SA", - "dial_code": "+966", - }, - { - "name": "Sénégal", - "code": "SN", - "dial_code": "+221", - }, - { - "name": "Србија", - "code": "RS", - "dial_code": "+381", - }, - { - "name": "Seychelles", - "code": "SC", - "dial_code": "+248", - }, - { - "name": "Sierra Leone", - "code": "SL", - "dial_code": "+232", - }, - { - "name": "Singapore", - "code": "SG", - "dial_code": "+65", - }, - { - "name": "Slovensko", - "code": "SK", - "dial_code": "+421", - }, - { - "name": "Slovenija", - "code": "SI", - "dial_code": "+386", - }, - { - "name": "Solomon Islands", - "code": "SB", - "dial_code": "+677", - }, - { - "name": "Soomaaliya", - "code": "SO", - "dial_code": "+252", - }, - { - "name": "South Africa", - "code": "ZA", - "dial_code": "+27", - }, - { - "name": "South Sudan", - "code": "SS", - "dial_code": "+211", - }, - { - "name": "South Georgia", - "code": "GS", - "dial_code": "+500", - }, - { - "name": "España", - "code": "ES", - "dial_code": "+34", - }, - { - "name": "Sri Lanka", - "code": "LK", - "dial_code": "+94", - }, - { - "name": "السودان", - "code": "SD", - "dial_code": "+249", - }, - { - "name": "Suriname", - "code": "SR", - "dial_code": "+597", - }, - { - "name": "Svalbard og Jan Mayen", - "code": "SJ", - "dial_code": "+47", - }, - { - "name": "Swaziland", - "code": "SZ", - "dial_code": "+268", - }, - { - "name": "Sverige", - "code": "SE", - "dial_code": "+46", - }, - { - "name": "Schweiz", - "code": "CH", - "dial_code": "+41", - }, - { - "name": "سوريا", - "code": "SY", - "dial_code": "+963", - }, - { - "name": "臺灣", - "code": "TW", - "dial_code": "+886", - }, - { - "name": "Тоҷикистон", - "code": "TJ", - "dial_code": "+992", - }, - { - "name": "Tanzania", - "code": "TZ", - "dial_code": "+255", - }, - { - "name": "ประเทศไทย", - "code": "TH", - "dial_code": "+66", - }, - { - "name": "Timor-Leste", - "code": "TL", - "dial_code": "+670", - }, - { - "name": "Togo", - "code": "TG", - "dial_code": "+228", - }, - { - "name": "Tokelau", - "code": "TK", - "dial_code": "+690", - }, - { - "name": "Tonga", - "code": "TO", - "dial_code": "+676", - }, - { - "name": "Trinidad and Tobago", - "code": "TT", - "dial_code": "+1868", - }, - { - "name": "تونس", - "code": "TN", - "dial_code": "+216", - }, - { - "name": "Türkiye", - "code": "TR", - "dial_code": "+90", - }, - { - "name": "Türkmenistan", - "code": "TM", - "dial_code": "+993", - }, - { - "name": "Turks and Caicos Islands", - "code": "TC", - "dial_code": "+1649", - }, - { - "name": "Tuvalu", - "code": "TV", - "dial_code": "+688", - }, - { - "name": "Uganda", - "code": "UG", - "dial_code": "+256", - }, - { - "name": "Україна", - "code": "UA", - "dial_code": "+380", - }, - { - "name": "دولة الإمارات العربية المتحدة", - "code": "AE", - "dial_code": "+971", - }, - { - "name": "United Kingdom", - "code": "GB", - "dial_code": "+44", - }, - { - "name": "United States", - "code": "US", - "dial_code": "+1", - }, - { - "name": "Uruguay", - "code": "UY", - "dial_code": "+598", - }, - { - "name": "O‘zbekiston", - "code": "UZ", - "dial_code": "+998", - }, - { - "name": "Vanuatu", - "code": "VU", - "dial_code": "+678", - }, - { - "name": "Venezuela", - "code": "VE", - "dial_code": "+58", - }, - { - "name": "Việt Nam", - "code": "VN", - "dial_code": "+84", - }, - { - "name": "British Virgin Islands", - "code": "VG", - "dial_code": "+1284", - }, - { - "name": "United States Virgin Islands", - "code": "VI", - "dial_code": "+1340", - }, - { - "name": "Wallis et Futuna", - "code": "WF", - "dial_code": "+681", - }, - { - "name": "اليَمَن", - "code": "YE", - "dial_code": "+967", - }, - { - "name": "Zambia", - "code": "ZM", - "dial_code": "+260", - }, - { - "name": "Zimbabwe", - "code": "ZW", - "dial_code": "+263", - }, -]; + { + "name": "Afghanistan", + "dial_code": "+93", + "code": "AF" + }, + { + "name": "Aland Islands", + "dial_code": "+358", + "code": "AX" + }, + { + "name": "Albania", + "dial_code": "+355", + "code": "AL" + }, + { + "name": "Algeria", + "dial_code": "+213", + "code": "DZ" + }, + { + "name": "AmericanSamoa", + "dial_code": "+1", + "code": "AS" + }, + { + "name": "Andorra", + "dial_code": "+376", + "code": "AD" + }, + { + "name": "Angola", + "dial_code": "+244", + "code": "AO" + }, + { + "name": "Anguilla", + "dial_code": "+1", + "code": "AI" + }, + { + "name": "Antigua and Barbuda", + "dial_code": "+1", + "code": "AG" + }, + { + "name": "Argentina", + "dial_code": "+54", + "code": "AR" + }, + { + "name": "Armenia", + "dial_code": "+374", + "code": "AM" + }, + { + "name": "Aruba", + "dial_code": "+297", + "code": "AW" + }, + { + "name": "Australia", + "dial_code": "+61", + "code": "AU" + }, + { + "name": "Austria", + "dial_code": "+43", + "code": "AT" + }, + { + "name": "Azerbaijan", + "dial_code": "+994", + "code": "AZ" + }, + { + "name": "Bahamas", + "dial_code": "+1", + "code": "BS" + }, + { + "name": "Bahrain", + "dial_code": "+973", + "code": "BH" + }, + { + "name": "Bangladesh", + "dial_code": "+880", + "code": "BD" + }, + { + "name": "Barbados", + "dial_code": "+1", + "code": "BB" + }, + { + "name": "Belarus", + "dial_code": "+375", + "code": "BY" + }, + { + "name": "Belgium", + "dial_code": "+32", + "code": "BE" + }, + { + "name": "Belize", + "dial_code": "+501", + "code": "BZ" + }, + { + "name": "Benin", + "dial_code": "+229", + "code": "BJ" + }, + { + "name": "Bermuda", + "dial_code": "+1", + "code": "BM" + }, + { + "name": "Bhutan", + "dial_code": "+975", + "code": "BT" + }, + { + "name": "Bolivia, Plurinational State of", + "dial_code": "+591", + "code": "BO" + }, + { + "name": "Bosnia and Herzegovina", + "dial_code": "+387", + "code": "BA" + }, + { + "name": "Botswana", + "dial_code": "+267", + "code": "BW" + }, + { + "name": "Brazil", + "dial_code": "+55", + "code": "BR" + }, + { + "name": "British Indian Ocean Territory", + "dial_code": "+246", + "code": "IO" + }, + { + "name": "Brunei Darussalam", + "dial_code": "+673", + "code": "BN" + }, + { + "name": "Bulgaria", + "dial_code": "+359", + "code": "BG" + }, + { + "name": "Burkina Faso", + "dial_code": "+226", + "code": "BF" + }, + { + "name": "Burundi", + "dial_code": "+257", + "code": "BI" + }, + { + "name": "Cambodia", + "dial_code": "+855", + "code": "KH" + }, + { + "name": "Cameroon", + "dial_code": "+237", + "code": "CM" + }, + { + "name": "Canada", + "dial_code": "+1", + "code": "CA" + }, + { + "name": "Cape Verde", + "dial_code": "+238", + "code": "CV" + }, + { + "name": "Cayman Islands", + "dial_code": "+1", + "code": "KY" + }, + { + "name": "Central African Republic", + "dial_code": "+236", + "code": "CF" + }, + { + "name": "Chad", + "dial_code": "+235", + "code": "TD" + }, + { + "name": "Chile", + "dial_code": "+56", + "code": "CL" + }, + { + "name": "China", + "dial_code": "+86", + "code": "CN" + }, + { + "name": "Christmas Island", + "dial_code": "+61", + "code": "CX" + }, + { + "name": "Cocos (Keeling) Islands", + "dial_code": "+61", + "code": "CC" + }, + { + "name": "Colombia", + "dial_code": "+57", + "code": "CO" + }, + { + "name": "Comoros", + "dial_code": "+269", + "code": "KM" + }, + { + "name": "Congo", + "dial_code": "+242", + "code": "CG" + }, + { + "name": "Congo, The Democratic Republic of the Congo", + "dial_code": "+243", + "code": "CD" + }, + { + "name": "Cook Islands", + "dial_code": "+682", + "code": "CK" + }, + { + "name": "Costa Rica", + "dial_code": "+506", + "code": "CR" + }, + { + "name": "Cote d'Ivoire", + "dial_code": "+225", + "code": "CI" + }, + { + "name": "Croatia", + "dial_code": "+385", + "code": "HR" + }, + { + "name": "Cuba", + "dial_code": "+53", + "code": "CU" + }, + { + "name": "Cyprus", + "dial_code": "+357", + "code": "CY" + }, + { + "name": "Czech Republic", + "dial_code": "+420", + "code": "CZ" + }, + { + "name": "Denmark", + "dial_code": "+45", + "code": "DK" + }, + { + "name": "Djibouti", + "dial_code": "+253", + "code": "DJ" + }, + { + "name": "Dominica", + "dial_code": "+1", + "code": "DM" + }, + { + "name": "Dominican Republic", + "dial_code": "+1", + "code": "DO" + }, + { + "name": "Ecuador", + "dial_code": "+593", + "code": "EC" + }, + { + "name": "Egypt", + "dial_code": "+20", + "code": "EG" + }, + { + "name": "El Salvador", + "dial_code": "+503", + "code": "SV" + }, + { + "name": "Equatorial Guinea", + "dial_code": "+240", + "code": "GQ" + }, + { + "name": "Eritrea", + "dial_code": "+291", + "code": "ER" + }, + { + "name": "Estonia", + "dial_code": "+372", + "code": "EE" + }, + { + "name": "Ethiopia", + "dial_code": "+251", + "code": "ET" + }, + { + "name": "Falkland Islands (Malvinas)", + "dial_code": "+500", + "code": "FK" + }, + { + "name": "Faroe Islands", + "dial_code": "+298", + "code": "FO" + }, + { + "name": "Fiji", + "dial_code": "+679", + "code": "FJ" + }, + { + "name": "Finland", + "dial_code": "+358", + "code": "FI" + }, + { + "name": "France", + "dial_code": "+33", + "code": "FR" + }, + { + "name": "French Guiana", + "dial_code": "+594", + "code": "GF" + }, + { + "name": "French Polynesia", + "dial_code": "+689", + "code": "PF" + }, + { + "name": "Gabon", + "dial_code": "+241", + "code": "GA" + }, + { + "name": "Gambia", + "dial_code": "+220", + "code": "GM" + }, + { + "name": "Georgia", + "dial_code": "+995", + "code": "GE" + }, + { + "name": "Germany", + "dial_code": "+49", + "code": "DE" + }, + { + "name": "Ghana", + "dial_code": "+233", + "code": "GH" + }, + { + "name": "Gibraltar", + "dial_code": "+350", + "code": "GI" + }, + { + "name": "Greece", + "dial_code": "+30", + "code": "GR" + }, + { + "name": "Greenland", + "dial_code": "+299", + "code": "GL" + }, + { + "name": "Grenada", + "dial_code": "+1", + "code": "GD" + }, + { + "name": "Guadeloupe", + "dial_code": "+590", + "code": "GP" + }, + { + "name": "Guam", + "dial_code": "+1", + "code": "GU" + }, + { + "name": "Guatemala", + "dial_code": "+502", + "code": "GT" + }, + { + "name": "Guernsey", + "dial_code": "+44", + "code": "GG" + }, + { + "name": "Guinea", + "dial_code": "+224", + "code": "GN" + }, + { + "name": "Guinea-Bissau", + "dial_code": "+245", + "code": "GW" + }, + { + "name": "Guyana", + "dial_code": "+592", + "code": "GY" + }, + { + "name": "Haiti", + "dial_code": "+509", + "code": "HT" + }, + { + "name": "Holy See (Vatican City State)", + "dial_code": "+39", + "code": "VA" + }, + { + "name": "Honduras", + "dial_code": "+504", + "code": "HN" + }, + { + "name": "Hong Kong", + "dial_code": "+852", + "code": "HK" + }, + { + "name": "Hungary", + "dial_code": "+36", + "code": "HU" + }, + { + "name": "Iceland", + "dial_code": "+354", + "code": "IS" + }, + { + "name": "India", + "dial_code": "+91", + "code": "IN" + }, + { + "name": "Indonesia", + "dial_code": "+62", + "code": "ID" + }, + { + "name": "Iran, Islamic Republic of Persian Gulf", + "dial_code": "+98", + "code": "IR" + }, + { + "name": "Iraq", + "dial_code": "+964", + "code": "IQ" + }, + { + "name": "Ireland", + "dial_code": "+353", + "code": "IE" + }, + { + "name": "Isle of Man", + "dial_code": "+44", + "code": "IM" + }, + { + "name": "Israel", + "dial_code": "+972", + "code": "IL" + }, + { + "name": "Italy", + "dial_code": "+39", + "code": "IT" + }, + { + "name": "Jamaica", + "dial_code": "+1", + "code": "JM" + }, + { + "name": "Japan", + "dial_code": "+81", + "code": "JP" + }, + { + "name": "Jersey", + "dial_code": "+44", + "code": "JE" + }, + { + "name": "Jordan", + "dial_code": "+962", + "code": "JO" + }, + { + "name": "Kazakhstan", + "dial_code": "+7", + "code": "KZ" + }, + { + "name": "Kenya", + "dial_code": "+254", + "code": "KE" + }, + { + "name": "Kiribati", + "dial_code": "+686", + "code": "KI" + }, + { + "name": "Korea, Democratic People's Republic of Korea", + "dial_code": "+850", + "code": "KP" + }, + { + "name": "Korea, Republic of South Korea", + "dial_code": "+82", + "code": "KR" + }, + { + "name": "Kuwait", + "dial_code": "+965", + "code": "KW" + }, + { + "name": "Kyrgyzstan", + "dial_code": "+996", + "code": "KG" + }, + { + "name": "Laos", + "dial_code": "+856", + "code": "LA" + }, + { + "name": "Latvia", + "dial_code": "+371", + "code": "LV" + }, + { + "name": "Lebanon", + "dial_code": "+961", + "code": "LB" + }, + { + "name": "Lesotho", + "dial_code": "+266", + "code": "LS" + }, + { + "name": "Liberia", + "dial_code": "+231", + "code": "LR" + }, + { + "name": "Libyan Arab Jamahiriya", + "dial_code": "+218", + "code": "LY" + }, + { + "name": "Liechtenstein", + "dial_code": "+423", + "code": "LI" + }, + { + "name": "Lithuania", + "dial_code": "+370", + "code": "LT" + }, + { + "name": "Luxembourg", + "dial_code": "+352", + "code": "LU" + }, + { + "name": "Macao", + "dial_code": "+853", + "code": "MO" + }, + { + "name": "Macedonia", + "dial_code": "+389", + "code": "MK" + }, + { + "name": "Madagascar", + "dial_code": "+261", + "code": "MG" + }, + { + "name": "Malawi", + "dial_code": "+265", + "code": "MW" + }, + { + "name": "Malaysia", + "dial_code": "+60", + "code": "MY" + }, + { + "name": "Maldives", + "dial_code": "+960", + "code": "MV" + }, + { + "name": "Mali", + "dial_code": "+223", + "code": "ML" + }, + { + "name": "Malta", + "dial_code": "+356", + "code": "MT" + }, + { + "name": "Marshall Islands", + "dial_code": "+692", + "code": "MH" + }, + { + "name": "Martinique", + "dial_code": "+596", + "code": "MQ" + }, + { + "name": "Mauritania", + "dial_code": "+222", + "code": "MR" + }, + { + "name": "Mauritius", + "dial_code": "+230", + "code": "MU" + }, + { + "name": "Mayotte", + "dial_code": "+262", + "code": "YT" + }, + { + "name": "Mexico", + "dial_code": "+52", + "code": "MX" + }, + { + "name": "Micronesia, Federated States of Micronesia", + "dial_code": "+691", + "code": "FM" + }, + { + "name": "Moldova", + "dial_code": "+373", + "code": "MD" + }, + { + "name": "Monaco", + "dial_code": "+377", + "code": "MC" + }, + { + "name": "Mongolia", + "dial_code": "+976", + "code": "MN" + }, + { + "name": "Montenegro", + "dial_code": "+382", + "code": "ME" + }, + { + "name": "Montserrat", + "dial_code": "+1", + "code": "MS" + }, + { + "name": "Morocco", + "dial_code": "+212", + "code": "MA" + }, + { + "name": "Mozambique", + "dial_code": "+258", + "code": "MZ" + }, + { + "name": "Myanmar", + "dial_code": "+95", + "code": "MM" + }, + { + "name": "Namibia", + "dial_code": "+264", + "code": "NA" + }, + { + "name": "Nauru", + "dial_code": "+674", + "code": "NR" + }, + { + "name": "Nepal", + "dial_code": "+977", + "code": "NP" + }, + { + "name": "Netherlands", + "dial_code": "+31", + "code": "NL" + }, + { + "name": "New Caledonia", + "dial_code": "+687", + "code": "NC" + }, + { + "name": "New Zealand", + "dial_code": "+64", + "code": "NZ" + }, + { + "name": "Nicaragua", + "dial_code": "+505", + "code": "NI" + }, + { + "name": "Niger", + "dial_code": "+227", + "code": "NE" + }, + { + "name": "Nigeria", + "dial_code": "+234", + "code": "NG" + }, + { + "name": "Niue", + "dial_code": "+683", + "code": "NU" + }, + { + "name": "Norfolk Island", + "dial_code": "+672", + "code": "NF" + }, + { + "name": "Northern Mariana Islands", + "dial_code": "+1", + "code": "MP" + }, + { + "name": "Norway", + "dial_code": "+47", + "code": "NO" + }, + { + "name": "Oman", + "dial_code": "+968", + "code": "OM" + }, + { + "name": "Pakistan", + "dial_code": "+92", + "code": "PK" + }, + { + "name": "Palau", + "dial_code": "+680", + "code": "PW" + }, + { + "name": "Palestinian Territory, Occupied", + "dial_code": "+970", + "code": "PS" + }, + { + "name": "Panama", + "dial_code": "+507", + "code": "PA" + }, + { + "name": "Papua New Guinea", + "dial_code": "+675", + "code": "PG" + }, + { + "name": "Paraguay", + "dial_code": "+595", + "code": "PY" + }, + { + "name": "Peru", + "dial_code": "+51", + "code": "PE" + }, + { + "name": "Philippines", + "dial_code": "+63", + "code": "PH" + }, + { + "name": "Poland", + "dial_code": "+48", + "code": "PL" + }, + { + "name": "Portugal", + "dial_code": "+351", + "code": "PT" + }, + { + "name": "Puerto Rico", + "dial_code": "+1", + "code": "PR" + }, + { + "name": "Qatar", + "dial_code": "+974", + "code": "QA" + }, + { + "name": "Romania", + "dial_code": "+40", + "code": "RO" + }, + { + "name": "Russia", + "dial_code": "+7", + "code": "RU" + }, + { + "name": "Rwanda", + "dial_code": "+250", + "code": "RW" + }, + { + "name": "Reunion", + "dial_code": "+262", + "code": "RE" + }, + { + "name": "Saint Barthelemy", + "dial_code": "+590", + "code": "BL" + }, + { + "name": "Saint Helena, Ascension and Tristan Da Cunha", + "dial_code": "+290", + "code": "SH" + }, + { + "name": "Saint Kitts and Nevis", + "dial_code": "+1", + "code": "KN" + }, + { + "name": "Saint Lucia", + "dial_code": "+1", + "code": "LC" + }, + { + "name": "Saint Martin", + "dial_code": "+590", + "code": "MF" + }, + { + "name": "Saint Pierre and Miquelon", + "dial_code": "+508", + "code": "PM" + }, + { + "name": "Saint Vincent and the Grenadines", + "dial_code": "+1", + "code": "VC" + }, + { + "name": "Samoa", + "dial_code": "+685", + "code": "WS" + }, + { + "name": "San Marino", + "dial_code": "+378", + "code": "SM" + }, + { + "name": "Sao Tome and Principe", + "dial_code": "+239", + "code": "ST" + }, + { + "name": "Saudi Arabia", + "dial_code": "+966", + "code": "SA" + }, + { + "name": "Senegal", + "dial_code": "+221", + "code": "SN" + }, + { + "name": "Serbia", + "dial_code": "+381", + "code": "RS" + }, + { + "name": "Seychelles", + "dial_code": "+248", + "code": "SC" + }, + { + "name": "Sierra Leone", + "dial_code": "+232", + "code": "SL" + }, + { + "name": "Singapore", + "dial_code": "+65", + "code": "SG" + }, + { + "name": "Slovakia", + "dial_code": "+421", + "code": "SK" + }, + { + "name": "Slovenia", + "dial_code": "+386", + "code": "SI" + }, + { + "name": "Solomon Islands", + "dial_code": "+677", + "code": "SB" + }, + { + "name": "Somalia", + "dial_code": "+252", + "code": "SO" + }, + { + "name": "South Africa", + "dial_code": "+27", + "code": "ZA" + }, + { + "name": "South Sudan", + "dial_code": "+211", + "code": "SS" + }, + { + "name": "Spain", + "dial_code": "+34", + "code": "ES" + }, + { + "name": "Sri Lanka", + "dial_code": "+94", + "code": "LK" + }, + { + "name": "Sudan", + "dial_code": "+249", + "code": "SD" + }, + { + "name": "Suriname", + "dial_code": "+597", + "code": "SR" + }, + { + "name": "Svalbard and Jan Mayen", + "dial_code": "+47", + "code": "SJ" + }, + { + "name": "Swaziland", + "dial_code": "+268", + "code": "SZ" + }, + { + "name": "Sweden", + "dial_code": "+46", + "code": "SE" + }, + { + "name": "Switzerland", + "dial_code": "+41", + "code": "CH" + }, + { + "name": "Syrian Arab Republic", + "dial_code": "+963", + "code": "SY" + }, + { + "name": "Taiwan", + "dial_code": "+886", + "code": "TW" + }, + { + "name": "Tajikistan", + "dial_code": "+992", + "code": "TJ" + }, + { + "name": "Tanzania, United Republic of Tanzania", + "dial_code": "+255", + "code": "TZ" + }, + { + "name": "Thailand", + "dial_code": "+66", + "code": "TH" + }, + { + "name": "Timor-Leste", + "dial_code": "+670", + "code": "TL" + }, + { + "name": "Togo", + "dial_code": "+228", + "code": "TG" + }, + { + "name": "Tokelau", + "dial_code": "+690", + "code": "TK" + }, + { + "name": "Tonga", + "dial_code": "+676", + "code": "TO" + }, + { + "name": "Trinidad and Tobago", + "dial_code": "+1", + "code": "TT" + }, + { + "name": "Tunisia", + "dial_code": "+216", + "code": "TN" + }, + { + "name": "Turkey", + "dial_code": "+90", + "code": "TR" + }, + { + "name": "Turkmenistan", + "dial_code": "+993", + "code": "TM" + }, + { + "name": "Turks and Caicos Islands", + "dial_code": "+1", + "code": "TC" + }, + { + "name": "Tuvalu", + "dial_code": "+688", + "code": "TV" + }, + { + "name": "Uganda", + "dial_code": "+256", + "code": "UG" + }, + { + "name": "Ukraine", + "dial_code": "+380", + "code": "UA" + }, + { + "name": "United Arab Emirates", + "dial_code": "+971", + "code": "AE" + }, + { + "name": "United Kingdom", + "dial_code": "+44", + "code": "GB" + }, + { + "name": "United States", + "dial_code": "+1", + "code": "US" + }, + { + "name": "Uruguay", + "dial_code": "+598", + "code": "UY" + }, + { + "name": "Uzbekistan", + "dial_code": "+998", + "code": "UZ" + }, + { + "name": "Vanuatu", + "dial_code": "+678", + "code": "VU" + }, + { + "name": "Venezuela, Bolivarian Republic of Venezuela", + "dial_code": "+58", + "code": "VE" + }, + { + "name": "Vietnam", + "dial_code": "+84", + "code": "VN" + }, + { + "name": "Virgin Islands, British", + "dial_code": "+1", + "code": "VG" + }, + { + "name": "Virgin Islands, U.S.", + "dial_code": "+1", + "code": "VI" + }, + { + "name": "Wallis and Futuna", + "dial_code": "+681", + "code": "WF" + }, + { + "name": "Yemen", + "dial_code": "+967", + "code": "YE" + }, + { + "name": "Zambia", + "dial_code": "+260", + "code": "ZM" + }, + { + "name": "Zimbabwe", + "dial_code": "+263", + "code": "ZW" + } + ]; diff --git a/lib/flag_phone_number.dart b/lib/flag_phone_number.dart new file mode 100644 index 00000000..1f4768b8 --- /dev/null +++ b/lib/flag_phone_number.dart @@ -0,0 +1,235 @@ +library country_code_picker; + +import 'package:collection/collection.dart' show IterableExtension; +import 'package:country_code_picker/widget/bottom_sheet_service/bottom_sheet_service.dart'; +import 'package:country_code_picker/country_code.dart'; +import 'package:country_code_picker/country_codes.dart'; +import 'package:country_code_picker/flag_phone_number_bottom_sheet.dart'; +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; + +export 'country_code.dart'; + +class FlagPhoneNumber extends StatefulWidget { + final ValueChanged? onChanged; + final ValueChanged? onInit; + final String? initialSelection; + final List favorite; + final TextStyle? textStyle; + final EdgeInsetsGeometry padding; + final InputDecoration searchDecoration; + final TextStyle? searchStyle; + final WidgetBuilder? emptySearchBuilder; + final bool disable; + final TextOverflow textOverflow; + final List? countryFilter; + final bool showOnlyCountryWhenClosed; + final EdgeInsets margin; + final bool showFlag; + final bool hideText; + final bool showFlagBottomSheet; + final double flagWidth; + final Comparator? comparator; + final bool hideSearch; + final Decoration? flagDecoration; + final String? placeholder; + + FlagPhoneNumber({ + // Custom Button + this.onChanged, + this.onInit, + this.countryFilter, + this.initialSelection, + this.comparator, + this.favorite = const [], + this.disable = false, + this.hideText = false, + this.showFlag = true, + this.showOnlyCountryWhenClosed = false, + this.textOverflow = TextOverflow.ellipsis, + this.padding = const EdgeInsets.all(8.0), + this.margin = const EdgeInsets.only(right: 8.0), + // Custom Flag on Button Sheet + this.textStyle, + this.searchStyle, + this.placeholder, + this.flagDecoration, + this.flagWidth = 32.0, + this.emptySearchBuilder, + this.hideSearch = false, + this.showFlagBottomSheet = true, + this.searchDecoration = const InputDecoration(), + Key? key, + }) : super(key: key); + + @override + State createState() { + List jsonList = codes; + + List elements = jsonList + .map((json) => CountryCode.fromJson(json as Map)) + .toList(); + + if (comparator != null) { + elements.sort(comparator); + } + + if (countryFilter != null && countryFilter!.isNotEmpty) { + final uppercaseCustomList = + countryFilter!.map((c) => c.toUpperCase()).toList(); + elements = elements + .where((c) => + uppercaseCustomList.contains(c.code) || + uppercaseCustomList.contains(c.name) || + uppercaseCustomList.contains(c.dialCode)) + .toList(); + } + + return FlagPhoneNumberState(elements); + } +} + +class FlagPhoneNumberState extends State { + CountryCode? selectedItem; + List elements = []; + List favoriteElements = []; + FlagPhoneNumberState(this.elements); + + @override + void initState() { + super.initState(); + + if (widget.initialSelection != null) { + selectedItem = elements.firstWhere( + (e) => + (e.code!.toUpperCase() == + widget.initialSelection!.toUpperCase()) || + (e.dialCode == widget.initialSelection) || + (e.name!.toUpperCase() == widget.initialSelection!.toUpperCase()), + orElse: () => elements[0]); + } else { + selectedItem = elements[0]; + } + + favoriteElements = elements + .where((e) => + widget.favorite.firstWhereOrNull((f) => + e.code!.toUpperCase() == f.toUpperCase() || + e.dialCode == f || + e.name!.toUpperCase() == f.toUpperCase()) != + null) + .toList(); + } + + @override + void didChangeDependencies() { + super.didChangeDependencies(); + + this.elements = elements.map((e) => e.localize(context)).toList(); + _onInit(selectedItem); + } + + @override + void didUpdateWidget(FlagPhoneNumber oldWidget) { + super.didUpdateWidget(oldWidget); + + if (oldWidget.initialSelection != widget.initialSelection) { + if (widget.initialSelection != null) { + selectedItem = elements.firstWhere( + (e) => + (e.code!.toUpperCase() == + widget.initialSelection!.toUpperCase()) || + (e.dialCode == widget.initialSelection) || + (e.name!.toUpperCase() == + widget.initialSelection!.toUpperCase()), + orElse: () => elements[0]); + } else { + selectedItem = elements[0]; + } + _onInit(selectedItem); + } + } + + void _onInit(CountryCode? e) { + if (widget.onInit != null) { + widget.onInit!(e); + } + } + + @override + Widget build(BuildContext context) { + return TextButton( + style: ButtonStyle( + foregroundColor: MaterialStateProperty.all(Colors.blue), + overlayColor: MaterialStateProperty.resolveWith( + (Set states) { + return Colors.transparent; + }, + ), + ), + child: Padding( + padding: widget.padding, + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + if(widget.showFlag) + Container( + clipBehavior: widget.flagDecoration == null + ? Clip.none + : Clip.hardEdge, + decoration: widget.flagDecoration, + margin: widget.margin, + child: Image.asset( + selectedItem!.flagUri!, + package: 'country_code_picker', + width: widget.flagWidth, + ), + ), + if(!widget.hideText) + Text( + widget.showOnlyCountryWhenClosed + ? selectedItem!.toCountryStringOnly() + : selectedItem.toString(), + style: + widget.textStyle ?? Theme.of(context).textTheme.button, + overflow: widget.textOverflow, + ), + ] + ), + ), + onPressed: widget.disable ? null : () async { + final countryCode = await BottomSheetService.show( + context, + isScrollControlled: true, + maxWidth: 420, + builder: FlagPhoneNumberBottomSheet( + elements: elements, + flagWidth: widget.flagWidth, + textStyle: widget.textStyle, + hideSearch: widget.hideSearch, + searchStyle: widget.searchStyle, + placeholder: widget.placeholder, + favoriteElements: favoriteElements, + showFlag: widget.showFlagBottomSheet, + flagDecoration: widget.flagDecoration, + searchDecoration: widget.searchDecoration, + emptySearchBuilder: widget.emptySearchBuilder, + ), + ); + + if(countryCode != null) { + setState(() { + selectedItem = countryCode; + }); + _publishSelection(countryCode); + } + }, + ); + } + + void _publishSelection(CountryCode e) { + if (widget.onChanged != null) { + widget.onChanged!(e); + } + } +} diff --git a/lib/flag_phone_number_bottom_sheet.dart b/lib/flag_phone_number_bottom_sheet.dart new file mode 100644 index 00000000..93f3a2e9 --- /dev/null +++ b/lib/flag_phone_number_bottom_sheet.dart @@ -0,0 +1,271 @@ + +import 'package:country_code_picker/widget/bottom_sheet_service/bottom_sheet_component.dart'; +import 'package:country_code_picker/widget/bottom_sheet_service/bottom_sheet_service.dart'; +import 'package:flutter/material.dart'; + +class FlagPhoneNumberBottomSheet extends StatefulWidget { + FlagPhoneNumberBottomSheet({ + Key? key, + this.elements, + this.showFlag = true, + this.hideSearch = false, + this.flagWidth = 32.0, + this.heightBottomSheet = 0.8, // <= 1.0 + this.textStyle, + this.searchStyle, + this.flagDecoration, + this.searchDecoration, + this.emptySearchBuilder, + this.favoriteElements, + this.placeholder = 'Tìm tên nước', + }) : super(key: key); + + final List? elements; + final bool hideSearch; + final bool showFlag; + final double flagWidth; + final String? placeholder; + final double heightBottomSheet; + final TextStyle? textStyle; + final TextStyle? searchStyle; + final Decoration? flagDecoration; + final WidgetBuilder? emptySearchBuilder; + final InputDecoration? searchDecoration; + final List? favoriteElements; + + @override + _FlagPhoneNumberBottomSheetState createState() => _FlagPhoneNumberBottomSheetState(); +} + +class _FlagPhoneNumberBottomSheetState extends State { + bool showIconClear = false; + TextEditingController? controllerFilterFormField; + List? filteredElements; + + @override + void initState() { + filteredElements = widget.elements!; + controllerFilterFormField = TextEditingController(); + super.initState(); + } + + @override + void dispose() { + controllerFilterFormField!.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + + final sizeScreen = MediaQuery.of(context).size; + + return BottomSheetComponent.container( + context, + child: ConstrainedBox( + constraints: BoxConstraints( + minHeight: sizeScreen.height * widget.heightBottomSheet, + maxHeight: sizeScreen.height * widget.heightBottomSheet, + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + BottomSheetComponent.draggableEdge(context), + const SizedBox(height: 24.0), + if (!widget.hideSearch) + Padding( + padding: const EdgeInsets.symmetric(horizontal: 8), + child: TextField( + controller: controllerFilterFormField, + style: widget.searchStyle, + decoration: InputDecoration( + prefixIcon: Icon( + Icons.search, + color: Colors.grey.withOpacity(0.4), + size: 18, + ), + suffixIcon: showIconClear ? IconButton( + hoverColor: Colors.transparent, + splashColor: Colors.transparent, + icon: Icon( + Icons.clear, + size: 16.0, + color: Colors.black.withOpacity(0.4), + ), + onPressed: () { + setState(() { + filteredElements = widget.elements!; + }); + controllerFilterFormField!.text = ''; + } + ) : null, + counterText: '', + errorText: null, + filled: true, + fillColor: Colors.grey.withOpacity(0.14), + focusedBorder: OutlineInputBorder( + borderSide: BorderSide( + color: Colors.grey.withOpacity(0.14), + width: 0, + ), + borderRadius: const BorderRadius.all(Radius.circular(5)), + ), + errorBorder: OutlineInputBorder( + borderSide: BorderSide( + color: Colors.grey.withOpacity(0.14), + width: 0, + ), + borderRadius: const BorderRadius.all(Radius.circular(0)), + ), + enabledBorder: OutlineInputBorder( + borderSide: BorderSide( + color: Colors.grey.withOpacity(0.14), + width: 0, + ), + borderRadius: const BorderRadius.all(Radius.circular(10)), + ), + disabledBorder: OutlineInputBorder( + borderSide: BorderSide( + color: Colors.grey.withOpacity(0.14), + width: 0, + ), + borderRadius: const BorderRadius.all(Radius.circular(0)), + ), + contentPadding: const EdgeInsets.only( + left: 8.0, + right: 8.0, + bottom: 8.0, + top: 8.0, + ), + hintStyle: TextStyle( + color: Colors.grey, + ), + hintText: widget.placeholder!, + ), + onChanged: _filterElements, + ), + ), + const SizedBox(height: 16.0), + Expanded( + child: ListView( + children: [ + widget.favoriteElements!.isEmpty + ? const DecoratedBox(decoration: BoxDecoration()) + : Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + ...widget.favoriteElements!.map( + (f) => _buildOption(f), + ), + const Divider(), + ], + ), + if (filteredElements!.isEmpty) + _buildEmptySearchWidget(context) + else + ...filteredElements!.map( + (e) => _buildOption(e), + ), + ], + ), + ), + ], + ), + ), + ); + } + + Widget _buildEmptySearchWidget(BuildContext context) { + if (widget.emptySearchBuilder != null) { + return widget.emptySearchBuilder!(context); + } + + return Center( + child: Text('No country found'), + ); + } + + Widget _buildOption(CountryCode e) { + return Container( + decoration: BoxDecoration( + border: Border( + bottom: BorderSide( + width: 1.0, + color: Colors.grey.withOpacity(0.1), + ), + ), + ), + child: InkWell( + onTap: () { + return _selectItem(e); + }, + child: Padding( + padding: EdgeInsets.symmetric( + horizontal: 8.0, + vertical: 12.0, + ), + child: Row( + children: [ + if (widget.showFlag) + Container( + margin: const EdgeInsets.only(right: 16.0), + decoration: widget.flagDecoration, + clipBehavior: + widget.flagDecoration == null ? Clip.none : Clip.hardEdge, + child: Image.asset( + e.flagUri!, + package: 'country_code_picker', + width: widget.flagWidth, + ), + ), + Expanded( + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + e.toCountryStringOnly(), + overflow: TextOverflow.fade, + style: widget.textStyle, + ), + Text( + '${e.dialCode}', + overflow: TextOverflow.fade, + style: widget.textStyle, + ), + ], + ), + ), + ], + ), + ), + ), + ); + } + + void _selectItem(CountryCode e) { + Navigator.pop(context, e); + } + + void _filterElements(String s) { + if (s.isNotEmpty) { + setState(() { + showIconClear = true; + }); + } else { + setState(() { + showIconClear = false; + }); + } + + s = s.toUpperCase(); + setState(() { + filteredElements = widget.elements! + .where((e) => + e.code!.contains(s) || + e.dialCode!.contains(s) || + e.name!.toUpperCase().contains(s)) + .toList(); + }); + } +} diff --git a/lib/widget/bottom_sheet_service/bottom_sheet_component.dart b/lib/widget/bottom_sheet_service/bottom_sheet_component.dart new file mode 100644 index 00000000..5a572789 --- /dev/null +++ b/lib/widget/bottom_sheet_service/bottom_sheet_component.dart @@ -0,0 +1,77 @@ + +import 'package:flutter/material.dart'; + +class BottomSheetComponent { + static ShapeBorder shape() { + return const RoundedRectangleBorder( + borderRadius: BorderRadius.only( + topLeft: Radius.circular(32.0), + topRight: Radius.circular(32.0), + ), + ); + } + + static Widget container(BuildContext context, {@required Widget? child}) { + return Padding( + padding: EdgeInsets.only( + top: 8.0, + left: 16.0, + right: 16.0, + ), + child: child, + ); + } + + static Widget content( + BuildContext context, { + double minHeight = 0.35, + double maxHeight = 0.55, + Widget? header, + Widget? footer, + @required Widget? body, + }) { + final size = MediaQuery.of(context).size; + + return ConstrainedBox( + constraints: BoxConstraints( + maxWidth: 420, + minHeight: size.height * minHeight, + maxHeight: size.height * maxHeight, + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + if (header != null) ...[ + header, + SizedBox(height: 24.0), + ], + Expanded( + child: SingleChildScrollView( + physics: const ClampingScrollPhysics(), + child: body, + ), + ), + if (footer != null) ...[ + SizedBox(height: 24.0), + footer, + ], + SizedBox(height: 16.0), + ], + ), + ); + } + + static Widget draggableEdge(BuildContext context) { + + return Center( + child: Container( + width: 131.0, + height: 8.0, + decoration: BoxDecoration( + color: Colors.grey, + borderRadius: BorderRadius.circular(5.0), + ), + ), + ); + } +} diff --git a/lib/widget/bottom_sheet_service/bottom_sheet_service.dart b/lib/widget/bottom_sheet_service/bottom_sheet_service.dart new file mode 100644 index 00000000..8de89b09 --- /dev/null +++ b/lib/widget/bottom_sheet_service/bottom_sheet_service.dart @@ -0,0 +1,60 @@ +import 'package:flutter/material.dart'; +import 'package:country_code_picker/widget/bottom_sheet_service/bottom_sheet_widget.dart'; +import 'bottom_sheet_component.dart'; + +import 'package:flutter/foundation.dart'; + +export '../../country_code.dart'; + +class BottomSheetService { + static Future show( + BuildContext context, { + @required Widget? builder, + Color? backgroundColor, + double? elevation, + bool persistent = true, + ShapeBorder? shape, + Clip? clipBehavior, + Color? barrierColor, + bool? ignoreSafeArea, + bool isScrollControlled = false, + bool useRootNavigator = false, + bool isDismissible = true, + bool enableDrag = true, + double maxWidth = double.infinity, + RouteSettings? settings, + Duration? enterBottomSheetDuration, + Duration? exitBottomSheetDuration, + }) async { + assert(builder != null); + assert(persistent != null); + assert(isScrollControlled != null); + assert(useRootNavigator != null); + assert(isDismissible != null); + assert(enableDrag != null); + + return await Navigator.of( + context, + rootNavigator: useRootNavigator, + ).push( + BottomSheetWidgetRoute( + builder: (_) => builder!, + isPersistent: persistent, + maxWidth: maxWidth, + isScrollControlled: isScrollControlled, + barrierLabel: + MaterialLocalizations.of(context).modalBarrierDismissLabel, + backgroundColor: backgroundColor ?? Colors.white, + elevation: elevation, + shape: shape ?? BottomSheetComponent.shape(), + removeTop: ignoreSafeArea ?? true, + clipBehavior: clipBehavior, + isDismissible: isDismissible, + modalBarrierColor: barrierColor ?? Colors.black.withOpacity(0.4), + settings: settings, + enableDrag: enableDrag, + ), + ); + } + +} diff --git a/lib/widget/bottom_sheet_service/bottom_sheet_widget.dart b/lib/widget/bottom_sheet_service/bottom_sheet_widget.dart new file mode 100644 index 00000000..4c15df8b --- /dev/null +++ b/lib/widget/bottom_sheet_service/bottom_sheet_widget.dart @@ -0,0 +1,227 @@ +import 'package:flutter/material.dart'; + + +class BottomSheetWidgetRoute extends PopupRoute { + BottomSheetWidgetRoute({ + this.builder, + this.theme, + this.barrierLabel, + this.backgroundColor, + this.isPersistent, + this.elevation, + this.shape, + this.removeTop = true, + this.clipBehavior, + this.modalBarrierColor, + this.isDismissible = true, + this.enableDrag = true, + this.maxWidth = double.infinity, + @required this.isScrollControlled, + RouteSettings? settings, + this.enterBottomSheetDuration = const Duration(milliseconds: 250), + this.exitBottomSheetDuration = const Duration(milliseconds: 200), + }) : assert(isScrollControlled != null), + name = "BOTTOMSHEET: ${builder.hashCode}", + assert(isDismissible != null), + assert(enableDrag != null), + super(settings: settings); + final double? maxWidth; + final bool? isPersistent; + final WidgetBuilder? builder; + final ThemeData? theme; + final bool? isScrollControlled; + final Color? backgroundColor; + final double? elevation; + final ShapeBorder? shape; + final Clip? clipBehavior; + final Color? modalBarrierColor; + final bool isDismissible; + final bool enableDrag; + final String name; + final Duration enterBottomSheetDuration; + final Duration exitBottomSheetDuration; + // remove safearea from top + final bool removeTop; + + @override + Duration get transitionDuration => Duration(milliseconds: 700); + + @override + bool get barrierDismissible => isDismissible; + + @override + final String? barrierLabel; + + @override + Color get barrierColor => modalBarrierColor ?? Colors.black54; + + AnimationController? _animationController; + + @override + AnimationController createAnimationController() { + assert(_animationController == null); + _animationController = + BottomSheet.createAnimationController(navigator!.overlay!); + _animationController!.duration = enterBottomSheetDuration; + _animationController!.reverseDuration = exitBottomSheetDuration; + return _animationController!; + } + + @override + Widget buildPage( + BuildContext context, + Animation animation, + Animation secondaryAnimation, + ) { + Widget bottomSheet = MediaQuery.removePadding( + context: context, + removeTop: removeTop, + child: Center( + child: Container( + constraints: BoxConstraints.expand(width: maxWidth), + padding: EdgeInsets.only( + bottom: MediaQuery.of(context).viewInsets.bottom, + ), + child: _BottomSheetWidget( + route: this, + backgroundColor: backgroundColor!, + shape: shape!, + isScrollControlled: isScrollControlled!, + enableDrag: enableDrag, + ), + ), + ), + ); + if (theme != null) bottomSheet = Theme(data: theme!, child: bottomSheet); + + return bottomSheet; + } +} + +class _BottomSheetWidget extends StatefulWidget { + const _BottomSheetWidget({ + Key? key, + this.route, + this.backgroundColor, + this.elevation, + this.shape, + this.clipBehavior, + this.isScrollControlled = false, + this.enableDrag = true, + this.isPersistent = false, + }) : assert(isScrollControlled != null), + assert(enableDrag != null), + super(key: key); + final bool isPersistent; + final BottomSheetWidgetRoute? route; + final bool isScrollControlled; + final Color? backgroundColor; + final double? elevation; + final ShapeBorder? shape; + final Clip? clipBehavior; + final bool enableDrag; + + @override + _BottomSheetWidgetState createState() => _BottomSheetWidgetState(); +} + +class _BottomSheetWidgetState extends State<_BottomSheetWidget> { + String _getRouteLabel(MaterialLocalizations localizations) { + if ((Theme.of(context).platform == TargetPlatform.android) || + (Theme.of(context).platform == TargetPlatform.fuchsia)) { + return localizations.dialogLabel; + } else { + return ''; + } + } + + @override + Widget build(BuildContext context) { + assert(debugCheckHasMediaQuery(context)); + assert(debugCheckHasMaterialLocalizations(context)); + final mediaQuery = MediaQuery.of(context); + final localizations = MaterialLocalizations.of(context); + final routeLabel = _getRouteLabel(localizations); + + return AnimatedBuilder( + animation: widget.route!.animation!, + builder: (context, child) { + final animationValue = mediaQuery.accessibleNavigation + ? 1.0 + : widget.route!.animation!.value; + return Semantics( + scopesRoute: true, + namesRoute: true, + label: routeLabel, + explicitChildNodes: true, + child: ClipRect( + child: CustomSingleChildLayout( + delegate: _BottomSheetWidgetLayout( + animationValue, + widget.isScrollControlled, + ), + child: widget.isPersistent == false + ? BottomSheet( + animationController: widget.route!._animationController, + onClosing: () { + if (widget.route!.isCurrent) { + Navigator.pop(context); + } + }, + builder: widget.route!.builder!, + backgroundColor: widget.backgroundColor, + elevation: widget.elevation, + shape: widget.shape, + clipBehavior: widget.clipBehavior, + enableDrag: widget.enableDrag, + ) + : Scaffold( + bottomSheet: BottomSheet( + animationController: widget.route!._animationController, + onClosing: () { + // if (widget.route.isCurrent) { + // Navigator.pop(context); + // } + }, + builder: widget.route!.builder!, + backgroundColor: widget.backgroundColor, + elevation: widget.elevation, + shape: widget.shape, + clipBehavior: widget.clipBehavior, + enableDrag: widget.enableDrag, + ), + ), + ), + ), + ); + }, + ); + } +} + +class _BottomSheetWidgetLayout extends SingleChildLayoutDelegate { + _BottomSheetWidgetLayout(this.progress, this.isScrollControlled); + + final double progress; + final bool isScrollControlled; + + @override + BoxConstraints getConstraintsForChild(BoxConstraints constraints) { + return BoxConstraints( + minWidth: constraints.maxWidth, + maxWidth: constraints.maxWidth, + minHeight: 0.0, + maxHeight: constraints.maxHeight, + ); + } + + @override + Offset getPositionForChild(Size size, Size childSize) { + return Offset(0.0, size.height - childSize.height * progress); + } + + @override + bool shouldRelayout(_BottomSheetWidgetLayout oldDelegate) { + return progress != oldDelegate.progress; + } +} From 0e1b720418e7bfd1ceec9e06488442671cd8fd19 Mon Sep 17 00:00:00 2001 From: CocaPepsi Date: Sat, 22 May 2021 16:55:38 +0700 Subject: [PATCH 2/2] fix issue SafeArea --- lib/flag_phone_number_bottom_sheet.dart | 19 ++++++++++++++++--- .../bottom_sheet_component.dart | 14 ++++++++------ .../bottom_sheet_service.dart | 1 - .../bottom_sheet_widget.dart | 4 ---- 4 files changed, 24 insertions(+), 14 deletions(-) diff --git a/lib/flag_phone_number_bottom_sheet.dart b/lib/flag_phone_number_bottom_sheet.dart index 93f3a2e9..245092c8 100644 --- a/lib/flag_phone_number_bottom_sheet.dart +++ b/lib/flag_phone_number_bottom_sheet.dart @@ -71,8 +71,20 @@ class _FlagPhoneNumberBottomSheetState extends State crossAxisAlignment: CrossAxisAlignment.start, mainAxisSize: MainAxisSize.min, children: [ - BottomSheetComponent.draggableEdge(context), - const SizedBox(height: 24.0), + Align( + alignment: Alignment.centerLeft, + child: IconButton( + icon: Icon( + Icons.clear, + ), + splashColor: Colors.transparent, + hoverColor: Colors.transparent, + onPressed: () { + Navigator.pop(context); + }, + ), + ), + const SizedBox(height: 8.0), if (!widget.hideSearch) Padding( padding: const EdgeInsets.symmetric(horizontal: 8), @@ -89,12 +101,13 @@ class _FlagPhoneNumberBottomSheetState extends State hoverColor: Colors.transparent, splashColor: Colors.transparent, icon: Icon( - Icons.clear, + Icons.highlight_remove_outlined, size: 16.0, color: Colors.black.withOpacity(0.4), ), onPressed: () { setState(() { + showIconClear = false; filteredElements = widget.elements!; }); controllerFilterFormField!.text = ''; diff --git a/lib/widget/bottom_sheet_service/bottom_sheet_component.dart b/lib/widget/bottom_sheet_service/bottom_sheet_component.dart index 5a572789..44457050 100644 --- a/lib/widget/bottom_sheet_service/bottom_sheet_component.dart +++ b/lib/widget/bottom_sheet_service/bottom_sheet_component.dart @@ -12,13 +12,15 @@ class BottomSheetComponent { } static Widget container(BuildContext context, {@required Widget? child}) { - return Padding( - padding: EdgeInsets.only( - top: 8.0, - left: 16.0, - right: 16.0, + return SafeArea( + child: Padding( + padding: EdgeInsets.only( + top: 8.0, + left: 16.0, + right: 16.0, + ), + child: child, ), - child: child, ); } diff --git a/lib/widget/bottom_sheet_service/bottom_sheet_service.dart b/lib/widget/bottom_sheet_service/bottom_sheet_service.dart index 8de89b09..e50f3b02 100644 --- a/lib/widget/bottom_sheet_service/bottom_sheet_service.dart +++ b/lib/widget/bottom_sheet_service/bottom_sheet_service.dart @@ -47,7 +47,6 @@ class BottomSheetService { backgroundColor: backgroundColor ?? Colors.white, elevation: elevation, shape: shape ?? BottomSheetComponent.shape(), - removeTop: ignoreSafeArea ?? true, clipBehavior: clipBehavior, isDismissible: isDismissible, modalBarrierColor: barrierColor ?? Colors.black.withOpacity(0.4), diff --git a/lib/widget/bottom_sheet_service/bottom_sheet_widget.dart b/lib/widget/bottom_sheet_service/bottom_sheet_widget.dart index 4c15df8b..70cf6b01 100644 --- a/lib/widget/bottom_sheet_service/bottom_sheet_widget.dart +++ b/lib/widget/bottom_sheet_service/bottom_sheet_widget.dart @@ -10,7 +10,6 @@ class BottomSheetWidgetRoute extends PopupRoute { this.isPersistent, this.elevation, this.shape, - this.removeTop = true, this.clipBehavior, this.modalBarrierColor, this.isDismissible = true, @@ -40,8 +39,6 @@ class BottomSheetWidgetRoute extends PopupRoute { final String name; final Duration enterBottomSheetDuration; final Duration exitBottomSheetDuration; - // remove safearea from top - final bool removeTop; @override Duration get transitionDuration => Duration(milliseconds: 700); @@ -75,7 +72,6 @@ class BottomSheetWidgetRoute extends PopupRoute { ) { Widget bottomSheet = MediaQuery.removePadding( context: context, - removeTop: removeTop, child: Center( child: Container( constraints: BoxConstraints.expand(width: maxWidth),