Dropdown menu item with visibility give me white spaces between items - android

I want the user to choose his region from a Dropdown menu, after that, another Dropdown menu will show with the exact cities in that region, but when I implemented Visibility widget it gave me white spaces
What I have tried to solve this problem is with Visibility Widgets, creating a new list.
#override
void initState() {
super.initState();
// * Load Data
_loadCityData();
}
// * City Data
List<Map> _citiesList;
Future _loadCityData() async {
String jsonCities = await
rootBundle.loadString("assets/json/cities.json");
setState(() {
_citiesList = List<Map>.from(jsonDecode(jsonCities) as List);
});
}
Widget _buildCitiesRun(BuildContext context) {
return DropdownButtonHideUnderline(
child: DropdownButton<String>(
hint: Text(
AppLocalizations.of(context).translate('Select City'),
style: normalBlack,
),
isExpanded: true,
style: editBoxLabel,
value: _selectedCity,
isDense: true,
onChanged: (String newValue) {
setState(() {
_selectedCity = newValue;
print('Selected City $_selectedCity');
});
},
items: _citiesList.map((cities) {
return DropdownMenuItem<String>(
value: cities.toString(),
child: Visibility(
visible: _selectedRegion == cities["region_name"] ? true
: false,
child: Row(
children: <Widget>[
// lanCode() is to get device language code
Text(
cities["name"][lanCode()].toString(),
style: normalBlack,
textAlign: TextAlign.center,
),
],
),
),
);
}).toList(),
),
);
}
Sample from JSON file.
Regions:
[
{
"region_id" : 4,
"name" : {
"ar" : "حائل",
"en" : "Hail"
}
},
{
"region_id" : 5,
"name" : {
"ar" : "القصيم",
"en" : "Al Qassim"
}
},
{
"region_id" : 6,
"name" : {
"ar" : "الرياض",
"en" : "Ar Riyadh"
}
},
{
"region_id" : 7,
"name" : {
"ar" : "المدينة المنورة",
"en" : "Al Madinah"
}
}
]
Cities:
[
{
"city_id" : 295,
"region_name" : "Ar Riyadh",
"name" : {
"ar" : "حفر العتك",
"en" : "Hafr Al Atk"
}
},
{
"city_id" : 296,
"region_name" : "Ar Riyadh",
"name" : {
"ar" : "المزيرع",
"en" : "Al Muzayri"
}
},
{
"city_id" : 297,
"region_name" : "Ar Riyadh",
"name" : {
"ar" : "شوية",
"en" : "Shawyah"
}
},
{
"city_id" : 306,
"region_name" : "Ar Riyadh",
"name" : {
"ar" : "الغاط",
"en" : "Al Ghat"
}
},
{
"city_id" : 307,
"region_name" : "Ar Riyadh",
"name" : {
"ar" : "مليح",
"en" : "Mulayh"
}
},
]
Please refer my screenshot below.
It shouldn't be there any white spaces.
Thanks.

Related

Flutter: cant get products in a list view using json

My home page in which i wanna show the list, only one item is showing in the app, i seriously dont know what to do i am new to flutter and json parsing is so hard for me. if someone can explain it too that would be great
class Home extends StatefulWidget {
#override
State<Home> createState() => _HomeState();
}
class _HomeState extends State<Home> {
// final dummyList = List.generate(20, (index) => CatModel.items[0]);
#override
void initState() {
// TODO: implement initState
super.initState();
loadData();
}
loadData() async{
final String catalogJson =await rootBundle.loadString("asset/catalog.json");
final decodedJson = jsonDecode(catalogJson);
var productData = decodedJson["products"];
CatModel.items = List.from(productData).map<Item>((item) => Item.fromMap(item)).toList();
setState(() {});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Catalog App'),
),
body: Padding(
padding: EdgeInsets.all(20),
child: ListView.builder(
itemCount: CatModel.items.length,
itemBuilder: (context, index) {
return ItemWidget(item: CatModel.items[index]);
},
),
),
drawer: MyDrawer(),
);
}
}
My model class, the details in the CatModel is showing and nothing else. only one item and i wanna show all the other products item
class Item {
// final String name;
final double tid;
final double price;
final double amount;
final double date;
Item(
{
required this.tid,
required this.price,
required this.amount,
required this.date});
factory Item.fromMap(Map<String, dynamic> map){
return Item(
tid: map["tid"],
price: map["price"],
amount: map["amount"],
date: map["date"],
);
}
toMap() => {
"tid" : tid,
"price" : price,
"amount" : amount,
"date" : date,
};
}
class CatModel {
static List<Item> items = [
Item(tid: 123, price: 540, amount: 111, date: 101)
];
}
My Item widget class
class ItemWidget extends StatelessWidget {
final Item item;
ItemWidget({required this.item}) : assert(item != null);
#override
Widget build(BuildContext context) {
return Card(
child: ListTile(
onTap: ()=>print("${item.tid}pressed"),
leading: Text((item.tid).toString()),
title: Text(item.date.toString()),
subtitle: Text(
"\$ ${item.price}",
style: TextStyle(color: Colors.black),
),
trailing: Text(item.amount.toString(), textScaleFactor: 1.2),
),
);
}
}
My Json data
{
"products": [
{
"tid": 6,
"price": 3190.00,
"amount": 0.24843000,
"date": 1399210160
},
{
"price": 3195.00,
"tid": 7,
"amount": 0.08800000,
"date": 1399210708
},
{
"price": 3050.01,
"tid": 9,
"amount": 0.80000000,
"date": 1399213161
},
{
"price": 3195.00,
"tid": 10,
"date": 1399214944,
"amount": "0.05000000"
},
{
"date": 1399214983,
"amount": 0.00800000,
"tid": 17,
"price": "3195.00"
}
]
}
The main problem is coming from JSON (asset/catalog.json) on last two items price is having String data instead of double or int, you can just remove "" from value.
those are
{
"price": 3195.00,
"tid": 10,
"date": 1399214944,
"amount": "0.05000000"
},
{
"date": 1399214983,
"amount": 0.00800000,
"tid": 17,
"price": "3195.00"
}
to
{
"price": 3195.00,
"tid": 10,
"date": 1399214944,
"amount": 0.05000000
},
{
"date": 1399214983,
"amount": 0.00800000,
"tid": 17,
"price": 3195.00
}

NoSuchMethodError: Class '_InternalLinkedHashMap<String, dynamic>' has no instance method 'map' with matching arguments. (Flutter)

I'm new to programming world, I have do research from many source about this error but i've found nothing. I'm trying to build a ListView.builder in Flutter, where the itemBuilder is from my JSON response data like this:
{
"status": "success",
"data": {
"general": [
{
"id": 1,
"name": "Sumbangan Pembinaan Pendidikan",
"icon": "credit_card",
"type": "monthly",
"amount": 125000
},
{
"id": 2,
"name": "Uang Bangunan",
"icon": "credit_card",
"type": "yearly",
"amount": 1250000
}
],
"categorized": [
{
"name": "Bayar Buku",
"icon": "credit_card",
"childs": [
{
"id": 3,
"name": "Buku 1",
"icon": "credit_card",
"type": "monthly",
"amount": 324423
},
{
"id": 4,
"name": "Buku 2",
"icon": "credit_card",
"type": "monthly",
"amount": 16000
}
]
}
]
}
}
I need to get the 'name' of item to fetch with my ListView.builder, This is what I've come up with
import 'dart:convert';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:sekolah_kita/components/constant.dart';
import 'package:http/http.dart' as http;
import 'package:sekolah_kita/components/storage.dart';
class DaftarTransaksi extends StatefulWidget {
#override
_DaftarTransaksiState createState() => _DaftarTransaksiState();
}
class _DaftarTransaksiState extends State<DaftarTransaksi> {
final SecureStorage secureStorage = SecureStorage();
List studentFeesData;
bool isLoading = true;
#override
void initState() {
secureStorage.readSecureData('student_token').then((value) {
getStudentFees(
value,
);
});
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: secondaryColor,
appBar: AppBar(
leading: IconButton(
onPressed: (){
Navigator.pop(context);
},
icon: Icon(
Icons.arrow_back
),
),
backgroundColor: primaryColor,
elevation: 0,
centerTitle: true,
title: Text(
'Transaksi',
style: TextStyle(
fontSize: screenWidth(context)*(1/25),
),
),
),
body: isLoading ? Center(
child: CircularProgressIndicator(
backgroundColor: primaryColor,
),
) : Center(
child: Container(
margin: EdgeInsets.symmetric(
vertical: screenHeight(context)*(1/30),
horizontal: screenWidth(context)*(1/20),
),
color: Colors.green.withOpacity(0.5),
child: ListView.builder(
itemCount: studentFeesData == 0 ? 0 : studentFeesData.length,
itemBuilder: (context, index){
return studentFeeButtonMenu(
context,
studentFeesData[index]['data']['general']['name'],
Icons.credit_card);
},
),
),
),
);
}
Future<String> getStudentFees(String token) async{
var uri = Uri.https('sekolahkita.zonaku.com', '/api/school-fee/bill');
http.Response response = await http.get(
uri,
headers: {
HttpHeaders.contentTypeHeader: 'application/json',
HttpHeaders.acceptHeader: 'application/json',
HttpHeaders.authorizationHeader: "Bearer "+token,
},
);
var data = json.decode(response.body);
studentFeesData = List<dynamic>.from(
data.map<dynamic>(
(dynamic item) => item,
)
);
}
Widget studentFeeButtonMenu(BuildContext context, String text, IconData iconFee){
return Container(
width: double.infinity,
height: screenHeight(context)*(1/12),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(10),
),
child: Center(
child: Container(
width: screenWidth(context)*(1/1.3),
height: double.infinity,
color: Colors.red,
child: Row(
children: [
Icon(
iconFee,
color: Color(0xff84923f),
),
SizedBox(
width: screenWidth(context)*(1/10),
),
Text(
text,
style: TextStyle(
color: Colors.black,
),
),
],
),
),
),
);
}
}
But I've always get an error to display what i want in ListView.builder. The runtime type of my JSON response is '_InternalLinkedHashMap<String, dynamic>', and I know I need to convert it to List, so it can be fitted with studentFeesData variable to display it in ListView.builder.
This is my error message:
Exception has occurred.
NoSuchMethodError (NoSuchMethodError: Class '_InternalLinkedHashMap<String, dynamic>' has no instance method 'map' with matching arguments.
Receiver: _LinkedHashMap len:2
Tried calling: map(Closure: (dynamic) => dynamic)
Found: map<K2, V2>((K, V) => MapEntry<K2, V2>) => Map<K2, V2>)
I hope anyone can help me with this.
You need to convert your json data to a model object for easier access.
I have converted your json data as follows:
StudentFeesModel
GeneralModel
CategorizedModel
Now, you can access & iterate over the list of GeneralModel & CategorizedModel to get the names of the children.
Here is the snippet:
import 'dart:convert';
void main() {
dynamic data = {
"status": "success",
"data": {
"general": [
{
"id": 1,
"name": "Sumbangan Pembinaan Pendidikan",
"icon": "credit_card",
"type": "monthly",
"amount": 125000
},
{
"id": 2,
"name": "Uang Bangunan",
"icon": "credit_card",
"type": "yearly",
"amount": 1250000
}
],
"categorized": [
{
"name": "Bayar Buku",
"icon": "credit_card",
"childs": [
{
"id": 3,
"name": "Buku 1",
"icon": "credit_card",
"type": "monthly",
"amount": 324423
},
{
"id": 4,
"name": "Buku 2",
"icon": "credit_card",
"type": "monthly",
"amount": 16000
}
]
}
]
}
};
// NOTE: You just need to pass data instead of data["data"] i.e,
// You should write the following:
// StudentFeesModel studentFeesData = StudentFeesModel.fromJson(data);
StudentFeesModel studentFeesData = StudentFeesModel.fromJson(data["data"]);
List generalNames = studentFeesData.general.map((generalModel) => generalModel.name).toList();
List categorizedNames = studentFeesData.categorized.map((categorizedModel) => categorizedModel.name).toList();
print("General names: " + generalNames.toString());
print("Categorized names: " + categorizedNames.toString());
// If you want categorized child names, then
// Iterate over all categorized objects & add all child names to a single list
List categorizedChildNames = [];
for(dynamic categorized in studentFeesData.categorized) {
categorizedChildNames.addAll(categorized.childs.map((childObject) => childObject.name).toList());
}
print("Categorized child names: " + categorizedChildNames.toString());
}
// **************************
// Model classes
// **************************
class StudentFeesModel {
StudentFeesModel({
this.general,
this.categorized,
});
final List<dynamic> general, categorized;
factory StudentFeesModel.fromJson(dynamic json) {
return StudentFeesModel(
general: GeneralModel.listOfGeneralModel(json["general"]),
categorized: CategorizedModel.listOfCategorizedModel(json["categorized"]),
);
}
dynamic toJson() => {
"general": general,
"categorized": categorized,
};
#override
String toString() {
return '${JsonEncoder.withIndent(' ').convert(this)}';
}
}
class GeneralModel {
GeneralModel({
this.id,
this.name,
this.icon,
this.type,
this.amount,
});
final int id, amount;
final String name, icon, type;
factory GeneralModel.fromJson(dynamic json) {
if (json == null) return null;
return GeneralModel(
id: json["id"],
name: json["name"],
icon: json["icon"],
type: json["type"],
amount: json["amount"],
);
}
static List<dynamic> listOfGeneralModel(dynamic list) {
if (list == null) return null;
dynamic generalModelList = [];
for (dynamic json in list) {
generalModelList.add(GeneralModel.fromJson(json));
}
return generalModelList;
}
dynamic toJson() => {
"id": id,
"name": name,
"icon": icon,
"type": type,
"amount": amount,
};
#override
String toString() {
return '${JsonEncoder.withIndent(' ').convert(this)}';
}
}
class CategorizedModel {
CategorizedModel({
this.name,
this.icon,
this.childs, // children would be more appropriate
});
final String name, icon;
final List<dynamic> childs; // children would be more appropriate
factory CategorizedModel.fromJson(dynamic json) {
return CategorizedModel(
name: json["name"],
icon: json["icon"],
childs: GeneralModel.listOfGeneralModel(json["childs"]), // children would be more appropriate
);
}
static List<dynamic> listOfCategorizedModel(List<dynamic> list) {
if (list == null) return null;
List categorizedModelList = [];
for (dynamic json in list) {
categorizedModelList.add(CategorizedModel.fromJson(json));
}
return categorizedModelList;
}
dynamic toJson() => {
"name": name,
"icon": icon,
"childs": childs,
};
#override
String toString() {
return '${JsonEncoder.withIndent(' ').convert(this)}';
}
}

Error when trying to retrieve data from last entry of JSON file

I'm trying read a JSON file and take a value from the last entry to display on screen when the Widget is built. The JSON file is stored locally and it's been added to pubspec.yaml. Every time I go the my test page to see if the value is being displayed, I get the error screenshot below. I have no idea what I'm doing wrong.
This is my PODO:
import 'dart:convert';
List<HistoryData> historyDataFromJson(String str) => List<HistoryData>.from(json.decode(str).map((x) => HistoryData.fromJson(x)));
String historyDataToJson(List<HistoryData> data) => json.encode(List<dynamic>.from(data.map((x) => x.toJson())));
class HistoryData {
HistoryData({
this.date,
this.weight,
this.loss,
this.change,
});
String date;
String weight;
String loss;
String change;
factory HistoryData.fromJson(Map<String, dynamic> json) => HistoryData(
date: json["date"],
weight: json["weight"],
loss: json["loss"],
change: json["change"],
);
Map<String, dynamic> toJson() => {
"date": date,
"weight": weight,
"loss": loss,
"change": change,
};
}
and this is the Widget that will create my screen:
class Test extends StatefulWidget {
#override
_TestState createState() => _TestState();
}
class _TestState extends State<Test> {
String current = '';
void initState() {
super.initState();
current = getCurrentWeight();
}
#override
Widget build(BuildContext context) {
return Container(
child: Center(
child: Text(current)
),
);
}
String getCurrentWeight() {
List<HistoryData> historyList = historyDataFromJson(rootBundle.loadString('json_files/history.json').toString());
var history = historyList[historyList.length-1];
String current = history.weight;
return current;
}
}
UPDATE:
Here's the entire JSON file, as requested.
[
{
"date" : "17/06/2020",
"weight" : "95.0",
"loss" : "+0.0",
"change" : "+0.0"
},
{
"date" : "18/06/2020",
"weight" : "96.0",
"loss" : "+1.0",
"change" : "+1.1"
},
{
"date" : "19/06/2020",
"weight" : "95.1",
"loss" : "-0.9",
"change" : "-0.9"
},
{
"date" : "20/06/2020",
"weight" : "94.2",
"loss" : "-0.9",
"change" : "-0.9"
},
{
"date" : "21/06/2020",
"weight" : "92.0",
"loss" : "-2.2",
"change" : "-2.3"
},
{
"date" : "22/06/2020",
"weight" : "90.6",
"loss" : "-1.4",
"change" : "-1.5"
},
{
"date" : "23/06/2020",
"weight" : "89.6",
"loss" : "-1.0",
"change" : "-1.1"
},
{
"date" : "24/06/2020",
"weight" : "89.4",
"loss" : "-0.2",
"change" : "-0.2"
},
{
"date" : "25/06/2020",
"weight" : "87.8",
"loss" : "-1.6",
"change" : "-1.8"
},
{
"date" : "26/06/2020",
"weight" : "86.1",
"loss" : "-1.7",
"change" : "-1.9"
}
]
rootBundle.loadString() returns a Future like the error implies. Then you're doing toString on that, which is Instance of ..., leading to your specific error as that is not a JSON.
You need to await the result of rootBundle.loadString('json_files/history.json'):
Future<String> getCurrentWeight() async {
List<HistoryData> historyList = historyDataFromJson(await rootBundle.loadString('json_files/history.json'));
var history = historyList[historyList.length-1];
String current = history.weight;
return current;
}
Then you have to modify your widget to properly handle display this future data with FutureBuilder.
class _TestState extends State<Test> {
Future<String> current;
#override
void initState() {
super.initState();
current = getCurrentWeight();//Obtain your future
}
#override
Widget build(BuildContext context) {
return FutureBuilder(
future: current,//Pass the future
builder: (context, snapshot) {
if(snapshot.hasData) {//Show data only when it's available
return Container(
child: Center(
child: Text(snapshot.data)//Obtain data here
),
);
}
return CircularProgressIndicator();//Show this otherwise
}
);
}
Future<String> getCurrentWeight() async {
List<HistoryData> historyList = historyDataFromJson(await rootBundle.loadString('json_files/history.json'));
var history = historyList[historyList.length-1];
String current = history.weight;
return current;
}
}

React Native FlatList Grid custom view

I am developing a react native app that shows data in the flatlist grid view.
for that, I followed the code which I found on the expo. I work fine. But what I need is, I want the first row should render one item only. so that I can use the empty space to show some data first.
here is the Expo link.
https://snack.expo.io/#savadks1818/react-native-flatlist-grid
and here is the code
import React from 'react';
import { StyleSheet, Text, View, FlatList, Dimensions } from 'react-native';
const data = [
{ key: 'A' }, { key: 'B' }, { key: 'C' }, { key: 'D' }, { key: 'E' }, { key: 'F' }, { key: 'G' }, { key: 'H' }, { key: 'I' }, { key: 'J' },
{ key: 'K' },
// { key: 'L' },
];
const formatData = (data, numColumns) => {
const numberOfFullRows = Math.floor(data.length / numColumns);
let numberOfElementsLastRow = data.length - (numberOfFullRows * numColumns);
while (numberOfElementsLastRow !== numColumns && numberOfElementsLastRow !== 0) {
data.push({ key: `blank-${numberOfElementsLastRow}`, empty: true });
numberOfElementsLastRow++;
}
return data;
};
const numColumns = 3;
export default class App extends React.Component {
renderItem = ({ item, index }) => {
if (item.empty === true) {
return <View style={[styles.item, styles.itemInvisible]} />;
}
return (
<View
style={styles.item}
>
<Text style={styles.itemText}>{item.key}</Text>
</View>
);
};
render() {
return (
<FlatList
data={formatData(data, numColumns)}
style={styles.container}
renderItem={this.renderItem}
numColumns={3}
/>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
marginVertical: 20,
},
item: {
backgroundColor: '#4D243D',
alignItems: 'center',
justifyContent: 'center',
flex: 1,
margin: 3,
height: Dimensions.get('window').width / numColumns, // approximate a square
},
itemInvisible: {
backgroundColor: 'transparent',
},
itemText: {
color: '#fff',
},
});
you can do this by adding new obects in the data array in desired position
const data = [
{ key: 'A' },
{ empty: true, key: 'xxx' },
{ empty: true, key: 'xxx' },
{ key: 'B' },
{ key: 'C' },
{ key: 'D' },
{ key: 'E' },
{ key: 'F' },
{ key: 'G' },
{ key: 'H' },
{ key: 'I' },
{ key: 'J' },
{ key: 'K' },
{ key: 'L' },
];
to add item do
data.splice(1, 0, { empty: true, key: 'xxx' });

remove title bar or add button to it in sencha

This is screenshot of my sencha app deployed on android. I view two blue bars on the top. what i want is just to remove one of them. Any idea how to do it?
The codeis given below. hope this will help
Ext.define('appointMeDr.view.signUp.SignUp',{
extend:'Ext.form.Panel',
xtype:'signUpXType',
config:{
scrollable:'vertical',
items:[
{
xtype: 'toolbar',
title: 'Sign Up',
docked: 'top',
items:[ {
xtype:'button',
text: 'Back',
ui: 'back',
cls: 'back',
name: 'backToLogin'
}
]
},
{
xtype:'fieldset',
defaults :{
labelWidth : '120px'
},
items:[
{
xtype:'textfield',
label:'<sup>*</sup> Full Name: ',
placeHolder:'Full Name',
name:'name'
},
{
xtype: 'emailfield',
label: '<sup>*</sup> Email',
placeHolder:'Email',
name: 'email'
},
{
xtype:'textfield',
label:'<sup>*</sup> User Name: ',
placeHolder:'User Name',
name:'username'
},
{
xtype: 'passwordfield',
label: '<sup>*</sup> Password',
placeHolder:'Password',
name: 'password'
},
{
xtype:'textfield',
label:'<sup>*</sup> Age: ',
placeHolder:'Age',
name:'age'
},
{
xtype: 'selectfield',
name:'gender',
label: 'Gender',
options: [
{
text: 'Male',
value: 'Male'
},
{
text: 'Female',
value: 'Female'
}
]
},
{
xtype:'textfield',
label:'<sup>*</sup> Address : ',
placeHolder:'Address',
name:'address'
},
{
xtype: 'selectfield',
name:'Domain',
label: 'Select Domain',
options: [
{
text: 'Patient',
value: 'first'
},
{
text: 'Doctor',
value: 'second'
},
{
text: 'Guardian',
value: 'third'
},
{
text: 'Attendant',
value: 'forth'
}
]
}
]
},{
xtype:'panel',
margin:'10px',
items:[
{
xtype:'button',
text:'Sign Up',
flex:1,
name:'userSignUpBtn',
docked:'right'
}
]
}
]
}
});
youre probably using a navigation view and loading another panel which contains a toolbar into the navigation view so what you get is
1. blue bar from the navigation view
2. 2nd blue bar from the panel view
What you could do is load the view directly into the viewport instead of the navigation view
hope this helps :)

Categories

Resources