How can I get user email while paying through Google pay in flutter - flutter

How can I make request so it can return user email so I can use it afterwards
{
"provider": "google_pay",
"data": {
"environment": "TEST",
"apiVersion": 2,
"apiVersionMinor": 0,
"allowedPaymentMethods": [
{
"type": "CARD",
"tokenizationSpecification": {
"type": "PAYMENT_GATEWAY",
"parameters": {
"gateway": "example",
"gatewayMerchantId": "gatewayMerchantId"
}
},
"parameters": {
"allowedCardNetworks": ["VISA", "MASTERCARD"],
"allowedAuthMethods": ["PAN_ONLY", "CRYPTOGRAM_3DS"],
"billingAddressRequired": true,
"billingAddressParameters": {
"format": "FULL",
"phoneNumberRequired": true
}
}
}
],
"merchantInfo": {
"merchantId": "BCR2DN4TZSYNRF3D",
"merchantName": "Software Hub"
},
"transactionInfo": {
"countryCode": "US",
"currencyCode": "USD"
}
}
}
That's the google pay Json File so let me know how can i make request so it can return user email which he is using for paying
GooglePayButton(
paymentConfigurationAsset:
'gpay.json',
paymentItems: _paymentItems,
style: GooglePayButtonStyle.white,
type: GooglePayButtonType.pay,
height: 200,
width: 200,
margin: const EdgeInsets.only(top: 15.0),
onPaymentResult: (data){
print(data);
},
loadingIndicator: const Center(
child: CircularProgressIndicator(),
),
),
That button is created using flutter pay package

Related

flutter, fetching dummy local json

i have local dummy json and i want to put it on title but the variables forms does not defined, i don't understand how to call the forms
the Json and title both are in different stateless widget in same page
Json
List<dynamic> forms = [
{
"id": 65,
"label": "Is this a test drive period or demonstration period?",
"code": "survey_general",
"type": "select_box",
"service_id": 48,
"client_type": "SURVEY_MITSU",
"column_order": 1,
"required": true,
"options": {
"step_number": "1",
"step_label": "General Information",
"options": []
},
"validation": null,
"requisite": false,
"multiple": false
},
]
Title
Container(
margin: EdgeInsets.fromLTRB(16, 20, 16, 8),
child: Text(
'Part 1: ${jsonEncode(forms['options']['step_label'])}',
style: Constants.textTitle.copyWith(
fontSize: 16,
fontFamily: 'Nunito',
),
),
),
It is not an appropriate approach to access the variables from other Widgets. The forms variable is not a local variable in Title.
There are two approaches:
Put the dummy variable forms into the Title Widget
Create a new class to store your dummy variable
class Dummy{
static const List<dynamic> forms = [
{
"id": 65,
"label": "Is this a test drive period or demonstration period?",
"code": "survey_general",
"type": "select_box",
"service_id": 48,
"client_type": "SURVEY_MITSU",
"column_order": 1,
"required": true,
"options": {
"step_number": "1",
"step_label": "General Information",
"options": []
},
"validation": null,
"requisite": false,
"multiple": false
},
];
}
Container(
margin: EdgeInsets.fromLTRB(16, 20, 16, 8),
child: Text(
'Part 1: ${jsonEncode(Dummy.forms['options']['step_label'])}',
style: Constants.textTitle.copyWith(
fontSize: 16,
fontFamily: 'Nunito',
),
),
),

How can I get Api data in Streambuilder - Flutter

I have an API, I want to show this API live. When the user removes any data delete live and also add any data from the backend I want to show it live.
Now how can I achieve it in flutter?
I am using Getx(Obx not working) , ListView.builder, and Dio package.
My Page.dart
import 'package:clipboard/clipboard.dart';
import 'package:dio/dio.dart';
import 'package:eva_icons_flutter/eva_icons_flutter.dart';
import 'package:flutter/material.dart';
import 'package:flutter_phone_direct_caller/flutter_phone_direct_caller.dart';
import 'package:get/get.dart';
import 'package:intl/intl.dart';
import 'package:isp_app/src/configs/appColors.dart';
import 'package:isp_app/src/configs/appConfigs.dart';
import 'package:isp_app/src/controllers/baseController.dart';
import 'package:isp_app/src/widgets/customButton.dart';
import 'package:isp_app/src/widgets/customRawText.dart';
import 'package:isp_app/src/widgets/kText.dart';
import 'package:shared_preferences/shared_preferences.dart';
class NewCollectionTab extends StatefulWidget with BaseController {
#override
State<NewCollectionTab> createState() => _NewCollectionTabState();
}
class _NewCollectionTabState extends State<NewCollectionTab>
with BaseController {
final keyRefresh = GlobalKey<RefreshIndicatorState>();
#override
Widget build(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(height: 20),
Padding(
padding: EdgeInsets.symmetric(horizontal: 20),
child: KText(
text: 'Main',
fontSize: 18,
fontWeight: FontWeight.w600,
color: Colors.black,
),
),
SizedBox(height: 10),
Obx( ()=>
ListView.builder(
shrinkWrap: true,
primary: false,
physics: BouncingScrollPhysics(),
itemCount: connectionDataC.connection.length,
itemBuilder: (context, index) {
final item = connectionDataC.connection[index];
return item.connectionStatus == true
? Container()
: InkWell( child: Padding(
padding: EdgeInsets.only(bottom: 10),
child: ListTile(
leading: CircleAvatar(
radius: 30,
backgroundColor: black12,
backgroundImage: NetworkImage(
item.catImg.toString(),
),
),
title: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [
KText(
text: item.userName.toString(),
fontSize: 16,
maxLines: 2,
fontWeight: FontWeight.w600,
),
],
),
SizedBox(height: 5),
Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [
Icon(
Icons.date_range,
size: 12,
color: black12,
),
SizedBox(width: 5),
KText(
text: DateFormat('dd-MM-yyyy').format(
DateTime.parse(
item.confrmDate.toString(),
),
),
fontSize: 12,
fontWeight: FontWeight.w600,
),
],
),
SizedBox(height: 5),
],
),
subtitle: KText(
text: item.description.toString(),
fontSize: 13,
color: black54,
maxLines: 3,
textAlign: TextAlign.justify,
fontWeight: FontWeight.normal,
),
),
),
);
},
),
),
],
);
}
}
My Controller.dart
import 'package:dio/dio.dart';
import 'package:get/get.dart';
import 'package:isp_app/src/configs/appConfigs.dart';
import 'package:isp_app/src/models/connections.dart';
import 'package:shared_preferences/shared_preferences.dart';
class ConnectionController extends GetxController {
// ignore: unused_field
final _dio = Dio();
// final RxList<dynamic> connectionList = RxList();
final connection = RxList<Connection>();
getconnectionList() async {
print('++++++++++++++++++++++++++++++++++');
try {
final sharedPreferences = await SharedPreferences.getInstance();
final token = sharedPreferences.get('accessToken');
final userName = sharedPreferences.get('loginUserName');
final res = await _dio.get(
'$baseUrl/new_connection/?search=$userName',
options: Options(
headers: {
"Content-Type": "application/json",
"Accept": "application/json",
"Authorization": 'Token $token'
},
),
);
print(res.statusCode);
print(res.headers);
// print(res.body);
// print(res.unauthorized);
print(res.realUri);
print(res.statusMessage);
print(res.data);
print(res.realUri);
print(res.requestOptions);
print('++++++++++++++++++++++++++++++++++');
if (res.statusCode == 200) {
if (res.statusCode! >= 200 && res.statusCode! < 300) {
connection.addAll(
(res.data as List).map((e) => Connection.fromJson(e)).toList());
}
}
} catch (e) {
print(e);
}
}
}
My Api Data demo :
[
{
"id": 1,
"confrm_date": "2022-01-17T07:14:06",
"User_name": "গণপরিবহনে অঘোষিত নিয়ম",
"Phone_Number": "0185455545",
"Description": "পরিবহন খাতের সঙ্গে মো. রুবেল হোসেন যুক্ত সেই ১৯৯৭ সাল থেকে। শুরু থেকেই তিনি ‘পুলিশ পাস’-এর কথা শুনে আসছেন। আদৌ এ নিয়ে কোনো আইন বা নিয়ম আছে কি না, তা জানেন না তিনি। তাঁর মতো অনেক পরিবহনমালিক ও শ্রমিকের একই অবস্থা।\r\n\r\nএত দিন শিক্ষার্থীদের জন্য বাসে অর্ধেক ভাড়ার (হাফ পাস) কথা শোনা গেলেও গণপরিবহনে ভাড়াসংক্রান্ত আরেকটি বিষয় প্রচলিত আছে। সেটিই হলো ওই ‘পুলিশ পাস’। এ ক্ষেত্রে অর্ধেক ভাড়া নয়, কোনো ভাড়াই দিচ্ছেন না অনেক পুলিশ সদস্য।",
"Connection_status": false,
"cat_img": "http://103.137.75.74:82/media/cat_img/LOGO-01.png",
"Connection_by": 1
},
{
"id": 2,
"confrm_date": "2022-01-17T07:14:06",
"User_name": "অবৈধ রসিদে টোল",
"Phone_Number": "0185455545",
"Description": "অবৈধ রসিদ তৈরি করে রাজধানীর যাত্রাবাড়ীর মেয়র হানিফ উড়ালসড়ক থেকে টোল আদায় করার অভিযোগ উঠেছে সংঘবদ্ধ একটি চক্রের বিরুদ্ধে। বিভিন্ন যানবাহনের চালকদের ভয় দেখিয়ে টোলের নামে চাঁদা আদায় করছিল চক্রটি। না দিলে প্রাণনাশের হুমকি দিচ্ছিল তারা।",
"Connection_status": false,
"cat_img": "http://103.137.75.74:82/media/cat_img/LOGO-01.png",
"Connection_by": 1
},
{
"id": 3,
"confrm_date": "2022-01-17T07:14:06",
"User_name": "User",
"Phone_Number": "0185455545",
"Description": "নরমাল ডেলিভারি হসপিটাল",
"Connection_status": false,
"cat_img": "http://103.137.75.74:82/media/cat_img/LOGO-01.png",
"Connection_by": 1
},
{
"id": 4,
"confrm_date": "2022-01-17T07:14:06",
"User_name": "User",
"Phone_Number": "0185455545",
"Description": "কাশেম মঞ্জিল, তানযীমুল উম্মাহ হিফয মাদ্রাসা।",
"Connection_status": false,
"cat_img": "http://103.137.75.74:82/media/cat_img/LOGO-01.png",
"Connection_by": 1
},
{
"id": 5,
"confrm_date": "2022-01-17T10:42:57",
"User_name": "User",
"Phone_Number": "0185455545",
"Description": "হাউজিং মারকাজ মসজিদের পিছনে - nstu teacher 2300 tk router +\r\nline charge 1000+ 360",
"Connection_status": true,
"cat_img": "http://103.137.75.74:82/media/cat_img/LOGO-01.png",
"Connection_by": 1
},
{
"id": 6,
"confrm_date": "2022-01-17T10:43:04",
"User_name": "User",
"Phone_Number": "0185455545",
"Description": "মাষ্টার পাড়া - হালিমা ভিলা ৩ তলায়",
"Connection_status": true,
"cat_img": "http://103.137.75.74:82/media/cat_img/LOGO-01.png",
"Connection_by": 1
},
{
"id": 7,
"confrm_date": "2022-01-17T10:44:25",
"User_name": "User",
"Phone_Number": "0185455545",
"Description": "মিঠুর কানেকশন আছে এখন , ১ তারিখ নিবে।",
"Connection_status": true,
"cat_img": "http://103.137.75.74:82/media/cat_img/LOGO-01.png",
"Connection_by": 1
},
{
"id": 8,
"confrm_date": "2022-01-17T10:44:49",
"User_name": "User",
"Phone_Number": "0185455545",
"Description": "এতিম খানার পিছনে।",
"Connection_status": true,
"cat_img": "http://103.137.75.74:82/media/cat_img/LOGO-01.png",
"Connection_by": 1
},
{
"id": 10,
"confrm_date": "2022-01-20T07:09:03",
"User_name": "User123",
"Phone_Number": "0185455545",
"Description": "54155",
"Connection_status": true,
"cat_img": "http://103.137.75.74:82/media/cat_img/LOGO-01.png",
"Connection_by": 1
},
{
"id": 11,
"confrm_date": "2022-01-20T07:09:48",
"User_name": "12345",
"Phone_Number": "0185455545",
"Description": "546",
"Connection_status": true,
"cat_img": "http://103.137.75.74:82/media/cat_img/LOGO-01.png",
"Connection_by": 1
}
]
Thing is that APIs do not send you "updates" so the client in this case your application does not receive updates when the server, this would require another mechanism like a socket, in which you connect to a server, and listen for active updates, In terms of a normal web api it works as request vs response, the server only responds to a request, so if you want to have a behavior that simulates a "real time" you will need to code a timer, which makes the request every 5 seconds for example, in that case, you will try to fetch new information every certain amount of time. Make sense?

How to handle selected item for dynamically generated ListView in Flutter

final variationMap = HashMap<String, List>();
In this map, I have
key -> ["color"] = value -> ["White", "Black"];
key -> ["ram"] = value -> ["128GB", "256GB"];
Based on this information I have designed the below UI.
**I want -> If I select white, white will be selected and black will remain unselected. And If I select black white will become unselected.
The same goes for Ram. Selecting one will make the other unselected. Two list view selections will work independently. **
For a single list view, we can achieve this using a selectedIndex variable.
Here is the API response. Here attribute value can be multiple. But I need to show one value in UI. So after some logic, I store the label and value into a map.
"productVariation": [
{
"price": 406089.25,
"qty": 449,
"variationAttribute": [
{
"attribute_value": "White",
"attributeDetails": {
"attributeLabel": [
{
"label": "Color"
}
]
}
},
{
"attribute_value": "128GB",
"attributeDetails": {
"attributeLabel": [
{
"label": "Ram"
}
]
}
}
]
},
{
"price": 292561.69,
"qty": 246,
"variationAttribute": [
{
"attribute_value": "White",
"attributeDetails": {
"attributeLabel": [
{
"label": "Color"
}
]
}
},
{
"attribute_value": "256GB",
"attributeDetails": {
"attributeLabel": [
{
"label": "Ram"
}
]
}
}
]
},
{
"price": 951456.88,
"qty": 828,
"variationAttribute": [
{
"attribute_value": "Black",
"attributeDetails": {
"attributeLabel": [
{
"label": "Color"
}
]
}
},
{
"attribute_value": "128GB",
"attributeDetails": {
"attributeLabel": [
{
"label": "Ram"
}
]
}
}
]
},
{
"price": 930735.09,
"qty": 321,
"variationAttribute": [
{
"attribute_value": "Black",
"attributeDetails": {
"attributeLabel": [
{
"label": "Color"
}
]
}
},
{
"attribute_value": "256GB",
"attributeDetails": {
"attributeLabel": [
{
"label": "Ram"
}
]
}
}
]
}
]
Here is the UI code. This code is for the bottom sheet dialog.
variationView() {
final widgets = <Widget>[];
var i = 1; // maintain vertical dot line between variation
for (var key in widget.controller.variationMap.keys) {
final list = widget.controller.variationMap[key];
widgets.add(
GlobalText(
str: "Select $key",
fontSize: 18,
fontWeight: FontWeight.w300,
),
);
widgets.add(
const SizedBox(
height: 20,
),
);
widgets.add(
SizedBox(
height: 60,
child: ListView.builder(
itemCount: list!.length,
shrinkWrap: true,
scrollDirection: Axis.horizontal,
itemBuilder: (ctx, index) {
return GestureDetector(
onTap: () {
setState(() {
isSelectedIndex = index;
isSelectedIndexForListView = i;
});
},
child:Container(
margin: EdgeInsets.only(right: 11),
padding: EdgeInsets.all(4),
width: 60,
height: 55,
decoration: BoxDecoration(
color: Color(0xfff8f8f8),
borderRadius: BorderRadius.circular(10),
border: Border.all(
color: isSelectedIndex == index && isSelectedIndexForListView == i
? Colors.black
: Color(0xffe2e2e2),
width: 1,
),
),
child: Center(
child: GlobalText(
str: list[index],
color: Color(0xff535960),
fontSize: 13,
fontWeight: FontWeight.w400,
maxLines: 2,
),
),
),
);
},
),
),
);
if (i < widget.controller.variationMap.keys.length) {
widgets.add(
const SizedBox(
height: 30,
),
);
}
i++;
}
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: widgets,
);
}
I have tried multiple ways but failed to hold or manage the state of the selected item.
In this code, I have tried to hold the index of the list view and another for item selected index. but When I select a ram, So same index color also goes selected and vice versa.
I have also tried using Unique key. But failed to solve the problem.
First you can create a model class for Value which will have to fields one for the value name another for checking if it's selected or not.
class Value{
String valueName;
bool isSelected;
}
Then create another class which will have one field of String type that is the label and another field of type List of Value object.
class Model {
String label;
List<Value> valueList;
}
From your controller or viewmodel class or the class you are using to update the states you will just have to update the value of isSelected field.

Getting Error on implementing Dismissible on flutter list

I am trying to implement Dismissible to swipe and remove the item from the list in flutter, but I am getting the below error on implementation of the same
type '_InternalLinkedHashMap<String, dynamic>' is not a subtype of
type 'String'
at this line of the code key: Key(item)
How should I resolve it ?
ListView.separated(
separatorBuilder: (context, index){
return Divider();
},
controller: _scrollController,
itemCount: noteItems,
shrinkWrap: true,
itemBuilder: (context, index) {
final item = firstdata[index];
return
Dismissible(
direction: DismissDirection.endToStart,
key: Key(item),
onDismissed: (direction) {
setState(() {
firstdata.removeAt(index);
});
Scaffold.of(context)
.showSnackBar(SnackBar(content: Text("$item dismissed")));
},
background: Container(color: Colors.red)
,
child: Padding(
padding: const EdgeInsets.fromLTRB(8.0, 7.0, 8.0, 0.0),
child: Column(
children: <Widget>[
ListTile(
leading:ClipRRect(
borderRadius: BorderRadius.circular(10),
child: Image.asset('images/appstore.png', width: 50, height: 50)
) ,
title:
Row(children: [
Flexible(
child: firstdata[index]['id']!= null?AutoSizeText(
firstdata[index]['id'],
maxLines: 2,
style: TextStyle(fontWeight: FontWeight.bold),) :Text(''),
),
],),
),
],
),
),
);
},
),
The JSON data structure for the list view is here below
{
"error": "false",
"notification": [
{
"rn": "1",
"id": "224",
"company_details": {
"code": "2",
}
},
{
"rn": "2",
"id": "219",
"company_details": {
"code": "3",
}
},
{
"rn": "3",
"id": "213",
"company_details": {
"code": "3",
}
},
{
"rn": "4",
"id": "209",
"company_details": {
"code": "4",
}
},
{
"rn": "5",
"id": "204",
"company_details": {
"code": "3",
}
},
{
"rn": "6",
"id": "199",
"company_details": {
"code": "3",
}
},
{
"rn": "7",
"id": "193",
"company_details": {
"code": "3",
}
}
],
}
How should I implement the same and get it resolved?
As stated in the other answer, the Key function expects a string to create a key based on that. If you can identify an item based on one of its parameters (for example id), then you could use item.id and it would be fine.
However, to make sure it will be truly unique key for any combination of parameters (in your case id, rn and company_details) you can use ObjectKey:
Replace the following line:
key: Key(item)
With the following:
key:ObjectKey(item)
This way Flutter can identify your item's parameters and create a key based on the combination of them.
Other options include ValueKey and UniqueKey.
type '_InternalLinkedHashMap<String, dynamic>' is not a subtype of type 'String'
means that it crashed because it was expecting a String and flutter did not find one.
This means that:
key: Key(item)
Key(item)-> Is not a String. I don´t know how are you creating Key/where is it.
My best guess is to try to find some method like...:
`key: Key(item).aMethodthatgivesaString()`
`key: Key(item).toString()`
Let me know if this was useful.

Flutter: How to custom Header from JSON

I have a JSON file like this (link API):
[
{
"continentName": "North America",
"countryFlag": "https://www.countryflags.io/us/shiny/64.png",
"countryCode": "US",
"countryName": "United States"
},
{
"continentName": "North America",
"countryFlag": "https://www.countryflags.io/ca/shiny/64.png",
"countryCode": "CA",
"countryName": "Canada"
},
{
"continentName": "South America",
"countryFlag": "https://www.countryflags.io/br/shiny/64.png",
"countryCode": "BR",
"countryName": "Brazil"
},
{
"continentName": "South America",
"countryFlag": "https://www.countryflags.io/in/shiny/64.png",
"countryCode": "IN",
"countryName": "India"
},
{
"continentName": "Europe",
"countryFlag": "https://www.countryflags.io/gb/shiny/64.png",
"countryCode": "GB",
"countryName": "United Kingdom"
},
{
"continentName": "Europe",
"countryFlag": "https://www.countryflags.io/de/shiny/64.png",
"countryCode": "DE",
"countryName": "Germany"
}
I want to show header of same "continentName" (Ex: North America; South America; Europe) like this
So pls help me, if possible to use StickyHeader or SliverAppBar then great, this is main file:
import 'package:ask/model/page3_model.dart';
import 'package:ask/services/page3_services.dart';
import 'package:flutter/material.dart';
class Page3 extends StatefulWidget {
#override
_Page3State createState() => _Page3State();
}
class _Page3State extends State<Page3> {
List<Header> _header = [];
#override
void initState() {
super.initState();
HeaderServices.getHeader().then((header) {
setState(() {
_header = header;
});
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Header')),
body: Container(),
);
}
}
"It looks like your post is mostly code; please add some more details". =.= ...........................................
Since, we can see that there are more than one info related to a continentName, for example, for North America has countryFlag, countryCode, 'countryName' respectively, and that is unique. So we will keep our newData in this format
{
North America: [
[countryFlag, countryCode, countryName],
[countryFlag, countryCode, countryName]
]
}
...
So, this is how we will do that using our new Map which will store the value like the above representation
Map _newMap = {};
// new Map which will store the data
// _data is the variable name which stores your JSON Array
_data.forEach((elem){
if(_newMap.containsKey(elem["continentName"])){
_newMap[elem["continentName"]].add([elem["countryFlag"], elem["countryName"], elem["countryCode"]]);
}else{
// Array of arrays will be stored like this
_newMap[elem["continentName"]] = [[elem["countryFlag"], elem["countryName"], elem["countryCode"]]];
}
});
print(_newMap);
/*
OUTPUT
{North America: [[https://www.countryflags.io/us/shiny/64.png, United States, US], [https://www.countryflags.io/ca/shiny/64.png, Canada, CA]], South America: [[https://www.countryflags.io/br/shiny/64.png, Brazil, BR], [https://www.countryflags.io/in/shiny/64.png, India, IN]], Europe: [[https://www.countryflags.io/gb/shiny/64.png, United Kingdom, GB], [https://www.countryflags.io/de/shiny/64.png, Germany, DE]]}
*/
See that! So, the idea is for every continentName, we can have array of arrays which will contain different item to be shown under a specific continentName
With that, here is final solution for you:
class _MyHomePageState extends State<MyHomePage> {
List<Map> _data = [
{
"continentName": "North America",
"countryFlag": "https://www.countryflags.io/us/shiny/64.png",
"countryCode": "US",
"countryName": "United States"
},
{
"continentName": "North America",
"countryFlag": "https://www.countryflags.io/ca/shiny/64.png",
"countryCode": "CA",
"countryName": "Canada"
},
{
"continentName": "South America",
"countryFlag": "https://www.countryflags.io/br/shiny/64.png",
"countryCode": "BR",
"countryName": "Brazil"
},
{
"continentName": "South America",
"countryFlag": "https://www.countryflags.io/in/shiny/64.png",
"countryCode": "IN",
"countryName": "India"
},
{
"continentName": "Europe",
"countryFlag": "https://www.countryflags.io/gb/shiny/64.png",
"countryCode": "GB",
"countryName": "United Kingdom"
},
{
"continentName": "Europe",
"countryFlag": "https://www.countryflags.io/de/shiny/64.png",
"countryCode": "DE",
"countryName": "Germany"
}
];
// This will give out our final widget with header and data
Widget get myWidget{
// Consists of all the Widgets
List<Widget> _widget = [];
Map _newMap = {};
// new Map which will store the data
_data.forEach((elem){
if(_newMap.containsKey(elem["continentName"])){
_newMap[elem["continentName"]].add([elem["countryFlag"], elem["countryName"], elem["countryCode"]]);
}else{
// Array of arrays will be stored like this
_newMap[elem["continentName"]] = [[elem["countryFlag"], elem["countryName"], elem["countryCode"]]];
}
});
_newMap.forEach((k,v){
List<Widget> _subHeaderItems = [];
_widget.add(
Container(
color: Colors.grey,
width: double.infinity,
child: Text(k, textAlign: TextAlign.center)
)
);
// We get the item like this item => [countryName, countryCode, countryFlag]
v.forEach((item){
_subHeaderItems.add(
Row(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
SizedBox(width: 10.0),
Image.network(
item[0],
width: 30.0,
height: 20.0
),
SizedBox(width: 20.0),
Text(item[2]),
SizedBox(width: 35.0),
Text(item[1]),
]
)
);
_subHeaderItems.add(
Divider(height: 1.0, color: Colors.grey[300])
);
});
_widget.add(
Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: _subHeaderItems
)
);
});
return Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: _widget
);
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Container(
height: double.infinity,
width: double.infinity,
child: this.myWidget
)
);
}
}
RESULT YOU WILL GET
Hope that helps :)