I am iterating over the map and creating a radio button inside the bottom sheet, in my dashboard I have "..." button once clicked it opens the bottom sheet.(inside my dashboard I am calling the DashboardFilter class present in filter.dart file that brings the bottomsheet,
below is the filter.dart file
class DashboardFilter extends StatefulWidget {
#override
_DashboardFilterState createState() => _DashboardFilterState();
final ValueChanged<Map<String, bool>> parentAction;
final ValueChanged<Map<String, bool>> childAction;
int radioValue1 = -1;
DashboardFilter(
{Key key,
this.parentAction,
this.childAction,
})
: super(key: key);
}
class _DashboardFilterState extends State<DashboardFilter> {
void showModalSheet() {
List<Map<String, Object>> timeData;
timeData = [
{"id": 1, "displayId": "Daily"},
{"id": 2, "displayId": "Weekly"},
{"id": 3, "displayId": "Monthly"}
];
showModalBottomSheet<void>(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10.0),
),
context: context,
builder: (BuildContext context) {
return StatefulBuilder(
builder: (BuildContext context, StateSetter state) {
return createBox(context, timeData, state);
});
});
}
createBox(BuildContext context,
List<Map<String, Object>> tickbox, StateSetter state) {
DateTime toDate;
DateTime fromDate;
var tickboxdata = tickbox.map<Widget>((data) {
int id = data["id"];
var dispId = data["displayId"];
return radiogen(context, id, dispId);
}).toList();
return SingleChildScrollView(
child: LimitedBox(
child: Column(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Container(
child: Column(
children: tickboxdata,
),),], ), ), );
}
void _handleRadioValueChange1(int value) {
setState(() {
widget.radioValue1 = value;
switch (widget.radioValue1) {
case 1:
print("1 selected");
break;
case 2:
break;
case 3:
break;
}
});
}
Widget radiogen(BuildContext context, int id, var disp) {
return Container(
padding: EdgeInsets.all(8.0),
child: new Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
new Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
new Radio(
value: id,
groupValue: widget.radioValue1,
onChanged: _handleRadioValueChange1,
),
new Text(
disp,
style: new TextStyle(fontSize: 16.0),
), ], ), ], ), );
}
#override
Widget build(BuildContext context) {
return Container(
child: IconButton(
icon: new Icon(Icons.more_horiz), onPressed: showModalSheet),
);
}
}
The issue what I am facing is once I select the radio button, its not showing which Item is selected on that time ,I again need to go to back and press again (...) button then it shows that option is selected.
can anyone help me to solve this,
Ithink problem is with the setState, let me know if there any changes to do?
after sometime studying your code here is my solution
you need put a Statesetter on radiogen widget
Widget radiogen(BuildContext context, int id, var disp, StateSetter
stateSetter) {
return Container(
padding: EdgeInsets.all(8.0),
child: new Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
new Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
new Radio(
value: id,
groupValue: widget.radioValue1,
onChanged: (value) {
stateSetter(() {
_handleRadioValueChange1(value);
});
}),
new Text(
disp,
style: new TextStyle(fontSize: 16.0),
),
],
),
],
),
);
}
then pass the state when you call the widget
createBox(BuildContext context, List<Map<String, Object>> tickbox,
StateSetter state) {
DateTime toDate;
DateTime fromDate;
var tickboxdata = tickbox.map<Widget>((data) {
int id = data["id"];
var dispId = data["displayId"];
return radiogen(context, id, dispId, state);
}).toList();
return SingleChildScrollView(
child: LimitedBox(
child: Column(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Container(
child: Column(
children: tickboxdata,
),
),
],
),
),
);
}
this way you can change the state on the radio
Radio(
value: id,
groupValue: widget.radioValue1,
onChanged: (value) {
stateSetter(() {
_handleRadioValueChange1(value);
});
}),
Related
I'm trying to select nested listview item, used listbuilder inside a listbuilder. Let’s say, I have 10 customers with 5 orders each, want to display customer1 and 5 orders, customer2 all orders…. .
I read the records from PostgreSQL and group them based on cust_id, resulted dataType is Map<String, List> and able to display on the screen. However while selecting the orders for processing (order2 of customer1, order4 of customer2, etc) it is throwing "Unsupported operation: Cannot modify an unmodifiable list".
Looks like I’m trying to modify immutable object. I tried to change Map<String, List> to Map<String, List< DetailedPositions>> but facing another error. Can you help to select orders. Any help would be appreciated.
import 'package:flutter/material.dart';
import 'package:e2/Models/model_positions.dart';
import 'package:e2/pages/modify_order.dart';
class ModifyPosition extends StatefulWidget {
const ModifyPosition({super.key});
#override
State<ModifyPosition> createState() => _ModifyPositionState();
}
class _ModifyPositionState extends State<ModifyPosition> {
Map data = {};
List<DetailedPositions> selectedContacts = [];
List<GroupedPositions> detailedPositions = [];
#override
Widget build(BuildContext context) {
data = ModalRoute.of(context)?.settings.arguments as Map;
var custIDs = data.values.toList()[0];
var custNames = data.values.toList()[1];
return Scaffold(
appBar: AppBar(
title: Text('Modify Positions '),
centerTitle: true,
),
body: SafeArea(
child: Container(
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Expanded(
child: FutureBuilder<Map<String, List<dynamic>>>(
future: ModelsPositions().detailedPositionsData(custIDs),
builder: (context, snapshot) {
Map<String, List<dynamic>> positions_raw =
snapshot.data ?? {};
List<GroupedPositions> detailedPositions = [];
positions_raw.forEach((k, v) {
detailedPositions
.add(GroupedPositions(custID: k, custInfo: v));
});
switch (snapshot.connectionState) {
case ConnectionState.waiting:
return Center(child: CircularProgressIndicator());
default:
if (snapshot.hasError) {
return Center(
child: Text(
'Error while loading Master Positions screen'));
} else {
return DetailedPosition(detailedPositions);
}}},)),],),),),);}
Widget DetailedPosition(List<GroupedPositions> detailedPositions) {
return Container(
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Expanded(
child: ListView.builder(
shrinkWrap: true,
physics: BouncingScrollPhysics(),
itemCount: detailedPositions.length,
itemBuilder: (BuildContext context, int index) {
final pos = detailedPositions[index];
final ID = pos.custID;
final custInfo = pos.custInfo;
final custID = ID.split(',')[0];
final custName = ID.split(',')[1];
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
//Text('Parent'),
Row(children: [
Expanded(
child: Padding(
padding: EdgeInsets.all(20),
child: Text("Cust_id : $custID",
style: TextStyle(
height: 3.0,
fontSize: 15.0,
fontWeight: FontWeight.bold,
)))),
Expanded(
child: Text("Cust_Name : $custName",
style: TextStyle(
height: 3.0,
fontSize: 15.0,
fontWeight: FontWeight.bold,
))),
]),
ListView.builder(
itemCount: custInfo.length,
physics: ClampingScrollPhysics(),
shrinkWrap: true,
itemBuilder: (BuildContext context, int childIndex) {
final pos = custInfo[childIndex];
final quantity = pos.elementAt(2);
final instrument = pos.elementAt(3);
final avgPrice = pos.elementAt(4);
final prodType = pos.elementAt(5);
final price1 = pos.elementAt(6);
final price2 = pos.elementAt(7);
final isSelected = pos.elementAt(8);
return ListTile(
horizontalTitleGap: -5,
title: Card(
child: Row(
crossAxisAlignment:
CrossAxisAlignment.center,
children: [
Expanded(
child: Column(
crossAxisAlignment:
CrossAxisAlignment.stretch,
children: [
Text('Qty : $quantity'),
const SizedBox(height: 10),
Text(instrument),
const SizedBox(height: 10),
Text('Avg : $avgPrice'),
],
),
),
Flexible(
fit: FlexFit.tight,
child: Column(
mainAxisAlignment:
MainAxisAlignment.end,
crossAxisAlignment:
CrossAxisAlignment.end,
mainAxisSize: MainAxisSize.min,
children: [
Text('$prodType'),
Text('$price1'),
const SizedBox(height: 10,),
Text('$price2'), ], ), ), ])),
leading: isSelected
? Icon(
Icons.check_circle,
color: Colors.green[700],
)
: Icon(
Icons.check_circle_outline,
color: Colors.grey,
),
onTap: () {
setState(() {
detailedPositions[index].custInfo[childIndex][8] =
!detailedPositions[index].custInfo[childIndex][8]; **--> Here facing the issue**
// if (detailedPositions[index]
// .custInfo[childIndex][8] ==
// true) {
.....
});
},); }), ], ); }), ) ], ), ); } }
class DetailedPositions {
String custID;
String custName;
int quantity;
String instrument;
double avgPrice;
String prodType;
double price1;
double price2;
bool isSelected = false;
DetailedPositions(
{required this.custID,
required this.custName,
required this.quantity,
required this.instrument,
required this.avgPrice,
required this.prodType,
required this.price1,
required this.price2});
}
class GroupedPositions {
String custID;
List<dynamic> custInfo;
GroupedPositions({required this.custID, required this.custInfo});
}
I have a search page that displays names with an add icon. When I press the add icon I want to pass the name to my previous screen that displays a list with names. I tried to do it as you can see down in my code but I have an error that my Athlete model doesn't have the constructor add. Can you help me figure out how to display the names in my list in previous screen? Thanks in advance!
My first screen that I display a list with names:
class AthleteScreen extends StatefulWidget {
const AthleteScreen({Key? key}) : super(key: key);
#override
State<AthleteScreen> createState() => _AthleteScreenState();
}
class _AthleteScreenState extends State<AthleteScreen> {
final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
Future<List<Athlete>>? futureAthletebyTeamKey;
final List<Athlete> _athlete = [];
#override
Widget build(BuildContext context) {
return Scaffold(
key: _scaffoldKey,
appBar: AppBar(
title: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
const Text(
'Athletes'),
actions: <Widget>[
Row(
children: [
IconButton(
onPressed: () {
Navigator.of(context)
.push<Athlete>(
MaterialPageRoute(builder: (_) => const AddAthlete()))
.then((value) => setState(() {
if (value != null && value is Athlete) {
Athlete.add(_athlete[index].lastName, _athlete[index].firstName,_athlete[index].fatherName); //here is when I push to the page where the names that I want to add are displayed
}
}));
},
icon: const Icon(Icons.add),
color: Colors.black,
iconSize: 30.0,
),
],
),
],
),
body: Stack(
children: [
SingleChildScrollView(
child: Column(children: [
FutureBuilder<List<Athlete>>(
future: futureAthletebyTeamKey,
builder: (context, AsyncSnapshot snapshot) {
if (snapshot.hasData) {
List<Athlete> _athlete = snapshot.data;
return ListView.builder(
itemCount: _athlete.length,
itemBuilder: (BuildContext context, int i) {
return CheckboxListTile(
title: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
Flexible(
child: Text(
'${_athlete[i].lastName} ${_athlete[i].firstName}',
),
),
],
),
} else if (snapshot.hasError) {
logger.e('${snapshot.error}');
}
return const Center(
heightFactor: 20,
child: CircularProgressIndicator.adaptive(),
);
},
),
]),
),
);
}
}
My second screen where the names that I want to add in the list of my first page are displayed
class AddAthlete extends StatefulWidget {
const AddAthlete({Key? key}) : super(key: key);
#override
State<AddAthlete> createState() => _AddAthleteState();
}
class _AddAthleteState extends State<AddAthlete> {
final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
Future<List<Athlete>>? futureSearchAthleteByName;
#override
void initState() {
futureSearchAthleteByName =
ApiService.searchAthletesByName(context) as Future<List<Athlete>>?;
text = myController.text;
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: const <Widget>[
Text(
'Add Athletes',
),
],
),
),
body: SingleChildScrollView(
child: Column(
children: [
Stack(
children: [
SingleChildScrollView(
child: Column(children: [
FutureBuilder<List<Athlete>>(
future: futureSearchAthleteByName,
builder: (context, AsyncSnapshot snapshot) {
if (snapshot.hasData) {
List<Athlete> _athlete = snapshot.data;
return ListView.builder(
itemCount: _athlete.length,
itemBuilder: (BuildContext context, int index) {
if (myController.text == '') {
return Container();
} else if (myController.text != '' &&
_athlete[index]
.lastName!
.toLowerCase()
.contains(myController.text
.toLowerCase()) ||
_athlete[index]
.firstName!
.toLowerCase()
.contains(
myController.text.toLowerCase())) {
return Column(
children: [
ListTile(
title: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment:
CrossAxisAlignment.start,
),
Row(
children: [
Flexible(
child: Text(
'${_athlete[index].lastName} ${_athlete[index].firstName}',
),
),
],
),
Row(
children: [
Flexible(
child: Text(
'(${_athlete[index].fatherName})',
),
),
],
),
],
),
trailing: IconButton(
icon: const Icon(
Icons.add,
color: Colors.black,
),
onPressed: () {
Navigator.pop(
context,
Athlete(
lastName: _athlete[index]
.lastName,
firstName: _athlete[index]
.firstName,
fatherName: _athlete[index]
.fatherName));
print(_athlete[index].lastName);
print(_athlete[index].firstName);
print(_athlete[index].fatherName); \\here is when I pop the names in my previous screen
},
),
),
],
);
}
});
} else if (snapshot.hasError) {
logger.e('${snapshot.error}');
}
return Container();
},
),
]),
),
],
),
],
),
),
);
}
}
If I was you I might do it in a different way
I add all the user id to the list on the second screen and pass the list to the second screen
in the first screen I call the API and get all the data by id and show it
(when a user doesn't select any element don't call the API)
How it possible to create a listView with Search function in a popup flutter?
I call the listView using API laravel. I want data in the popup will be able to be select or user can search it in popup and then select it. As user select the data and click submit data will be able to post in database.
below is the function that I used to call the data
List _listViewData = List();
#override
initState() {
super.initState();
// when loading your widget for the first time, loads country from db
_countryA();
}
void _countryA() async {
// gets data from db
final countryA = await CallApi().getData('countries');
var resBody = json.decode(countryA.body);
setState(() {
// converts db row data to List<String>, updating state
_listViewData = resBody;
});
}
I just know how to call the data of country using dropdown in an alert button.
I dont want it to be display in dropdown but instead in a list in flutter.
below is function that I called in the dropdown
void _showDialog() {
// flutter defined function
showDialog(
context: context,
builder: (BuildContext context) {
// return object of type Dialog
return AlertDialog(
title: new Text("Select Country", textAlign:TextAlign.center,),
actions: <Widget>[
// usually buttons at the bottom of the dialog
new FlatButton(
child: new Text("Close"),
onPressed: () {
Navigator.of(context).pop();
},
),
],
content: new Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Expanded(
child: DropdownButton(
items: _listViewData.map((item) {
return new DropdownMenuItem(
child: new Text(item['country']),
value: item['id'].toString(),
);
}).toList(),
onChanged: (newVal) {
setState(() {
_mySelectionAr = newVal;
});
},
value: _mySelectionAr,
),
),
],
),
);
},
);
}
So, the conclusion is that I want it to be display in listview in the flutter popup not a dropdown in a popup. I just cannot figure out how to call all the list data of country in a list in popup include with the search function.
Edit
The most simple way is after folk this github.
You can update file https://github.com/figengungor/country_pickers/blob/master/lib/countries.dart directly
or in
https://github.com/figengungor/country_pickers/blob/master/lib/country_picker_dialog.dart at line 113 change _allCountries to what you need, you can hard code or use your own ready made api but need to follow owner's Country Class.
You can use https://pub.dev/packages/country_pickers directly or reference source code and build your own
for Counties you need does not exist. you can fork this github project and modify directly https://github.com/figengungor/country_pickers/blob/master/lib/countries.dart
It support features you need can use in showDialog and inside is a ListView
also provide search by phone and name
full example code
import 'package:country_pickers/country.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:country_pickers/country_pickers.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Country Pickers Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
routes: {
'/': (context) => DemoPage(),
},
);
}
}
class DemoPage extends StatefulWidget {
#override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<DemoPage> {
Country _selectedDialogCountry =
CountryPickerUtils.getCountryByPhoneCode('90');
Country _selectedFilteredDialogCountry =
CountryPickerUtils.getCountryByPhoneCode('90');
Country _selectedCupertinoCountry =
CountryPickerUtils.getCountryByIsoCode('tr');
Country _selectedFilteredCupertinoCountry =
CountryPickerUtils.getCountryByIsoCode('DE');
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Country Pickers Demo'),
),
body: ListView(
padding: EdgeInsets.all(8.0),
children: <Widget>[
Card(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text('CountryPickerDropdown'),
ListTile(title: _buildCountryPickerDropdown(false)),
],
),
),
Card(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text('CountryPickerDropdown (filtered)'),
ListTile(title: _buildCountryPickerDropdown(true)),
],
),
),
Card(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text('CountryPickerDialog'),
ListTile(
onTap: _openCountryPickerDialog,
title: _buildDialogItem(_selectedDialogCountry),
),
],
),
),
Card(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text('CountryPickerDialog (filtered)'),
ListTile(
onTap: _openFilteredCountryPickerDialog,
title: _buildDialogItem(_selectedFilteredDialogCountry),
),
],
),
),
Card(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text('CountryPickerCupertino'),
ListTile(
title: _buildCupertinoSelectedItem(_selectedCupertinoCountry),
onTap: _openCupertinoCountryPicker,
),
],
),
),
Card(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text('CountryPickerCupertino (filtered)'),
ListTile(
title: _buildCupertinoSelectedItem(
_selectedFilteredCupertinoCountry),
onTap: _openFilteredCupertinoCountryPicker,
),
],
),
),
],
),
);
}
_buildCountryPickerDropdown(bool filtered) => Row(
children: <Widget>[
CountryPickerDropdown(
initialValue: 'AR',
itemBuilder: _buildDropdownItem,
itemFilter: filtered
? (c) => ['AR', 'DE', 'GB', 'CN'].contains(c.isoCode)
: null,
onValuePicked: (Country country) {
print("${country.name}");
},
),
SizedBox(
width: 8.0,
),
Expanded(
child: TextField(
decoration: InputDecoration(labelText: "Phone"),
),
)
],
);
Widget _buildDropdownItem(Country country) => Container(
child: Row(
children: <Widget>[
CountryPickerUtils.getDefaultFlagImage(country),
SizedBox(
width: 8.0,
),
Text("+${country.phoneCode}(${country.isoCode})"),
],
),
);
Widget _buildDialogItem(Country country) => Row(
children: <Widget>[
CountryPickerUtils.getDefaultFlagImage(country),
SizedBox(width: 8.0),
Text("+${country.phoneCode}"),
SizedBox(width: 8.0),
Flexible(child: Text(country.name))
],
);
void _openCountryPickerDialog() => showDialog(
context: context,
builder: (context) => Theme(
data: Theme.of(context).copyWith(primaryColor: Colors.pink),
child: CountryPickerDialog(
titlePadding: EdgeInsets.all(8.0),
searchCursorColor: Colors.pinkAccent,
searchInputDecoration: InputDecoration(hintText: 'Search...'),
isSearchable: true,
title: Text('Select your phone code'),
onValuePicked: (Country country) =>
setState(() => _selectedDialogCountry = country),
itemBuilder: _buildDialogItem)),
);
void _openFilteredCountryPickerDialog() => showDialog(
context: context,
builder: (context) => Theme(
data: Theme.of(context).copyWith(primaryColor: Colors.pink),
child: CountryPickerDialog(
titlePadding: EdgeInsets.all(8.0),
searchCursorColor: Colors.pinkAccent,
searchInputDecoration: InputDecoration(hintText: 'Search...'),
isSearchable: true,
title: Text('Select your phone code'),
onValuePicked: (Country country) =>
setState(() => _selectedFilteredDialogCountry = country),
itemFilter: (c) => ['AR', 'DE', 'GB', 'CN'].contains(c.isoCode),
itemBuilder: _buildDialogItem)),
);
void _openCupertinoCountryPicker() => showCupertinoModalPopup<void>(
context: context,
builder: (BuildContext context) {
return CountryPickerCupertino(
backgroundColor: Colors.black,
itemBuilder: _buildCupertinoItem,
pickerSheetHeight: 300.0,
pickerItemHeight: 75,
initialCountry: _selectedCupertinoCountry,
onValuePicked: (Country country) =>
setState(() => _selectedCupertinoCountry = country),
);
});
void _openFilteredCupertinoCountryPicker() => showCupertinoModalPopup<void>(
context: context,
builder: (BuildContext context) {
return CountryPickerCupertino(
backgroundColor: Colors.white,
pickerSheetHeight: 200.0,
initialCountry: _selectedFilteredCupertinoCountry,
onValuePicked: (Country country) =>
setState(() => _selectedFilteredCupertinoCountry = country),
itemFilter: (c) => ['AR', 'DE', 'GB', 'CN'].contains(c.isoCode),
);
});
Widget _buildCupertinoSelectedItem(Country country) {
return Row(
children: <Widget>[
CountryPickerUtils.getDefaultFlagImage(country),
SizedBox(width: 8.0),
Text("+${country.phoneCode}"),
SizedBox(width: 8.0),
Flexible(child: Text(country.name))
],
);
}
Widget _buildCupertinoItem(Country country) {
return DefaultTextStyle(
style:
const TextStyle(
color: CupertinoColors.white,
fontSize: 16.0,
),
child: Row(
children: <Widget>[
SizedBox(width: 8.0),
CountryPickerUtils.getDefaultFlagImage(country),
SizedBox(width: 8.0),
Text("+${country.phoneCode}"),
SizedBox(width: 8.0),
Flexible(child: Text(country.name))
],
),
);
}
}
I have 2 class, the first one is Main Widget Screen and 2nd is List Card. In View Perspective, Main Widget Screen Class contain List Widget from List Card Widget Class , as seen as below picture :
On List Card Widget, every list has 2 Text: Text1 and Text2.
also, there're 2 button: this month and last month. data on List Card Widget will refresh according to Bloc Stream ZikirHistoryBloc.onChangeTab(). the default is this month.
What i want to achieve is :
How to Show/Hide (On/Off) Text1 and Text2 by button on Main Screen ?
My Effort so far:
Main Screen Class :
class MainScreen extends StatefulWidget {
#override
_MainScreenState createState() {
return new _MainScreenState();
}
}
class _MainScreenState extends State<MainScreen> {
ZikirHistoryBloc zikirHistoryBloc;
int selectedValue = 1;
...
#override
Widget build(BuildContext context) {
return Scaffold(
...
Expanded(
child: ButtonMenuWidget(
image: "assets/images/zikir/button-text1.png",
title: translations.text("button_show_hide_text1"),
subtitle: point,
onTap: () {
//This is action for Button for Show/Hide Text1**
}
)
),
Expanded(
child: ButtonMenuWidget(
image: "assets/images/home/button-text2.png",
title: translations.text("button_show_hide_text2"),
subtitle: dzikir,
onTap: () {
//This is action for Button for Show/Hide Text1**
}
)
),
...
SizedBox(
width: 1000,
child: Padding(
padding: EdgeInsets.all(8),
child: StreamBuilder(
stream: zikirHistoryBloc.tabSelectedValueStream,
builder: (context, snapshot) {
return CupertinoSegmentedControl<int>(
selectedColor: Pigment.fromString(UIData.primaryColor),
borderColor: Pigment.fromString(UIData.primaryColor),
children: <int, Widget>{
0: Text(translations.text("last_month").toString()),
1: Text(translations.text("this_month").toString()),
},
onValueChanged: (int newValue) {
zikirHistoryBloc.onChangeTab(newValue);
},
groupValue: snapshot.data,
);
}
),
)
),
...
this.HistoriesWidget(),
...
}//::end of Widget build
...
Widget HistoriesWidget() {
return StreamBuilder(
stream: zikirHistoryBloc.dzikirHistoriesStream,
builder: (BuildContext ctx, AsyncSnapshot<List<DzikirHistory>> snapshot) {
if (snapshot.hasError) return new Text('Error: ${snapshot.error}');
if (!snapshot.hasData) return Center(child: ActivityIndicatorWidget());
if (snapshot.data.length <= 0) return Center(child: Text(translations.text("empty_data")));
return ListView.builder(
shrinkWrap: true,
itemCount: snapshot.data.length,
primary: false,
physics: const NeverScrollableScrollPhysics(),
itemBuilder: (ctx, i) {
//**Below will call class ListCardWidget**
return ListCardWidget(dzikirHistory: snapshot.data[i]);
}
);
}
);
}
...
} //::end of Class `Main Screen`
List Card Widget Class :
class ListCardWidget extends StatefulWidget {
DzikirHistory dzikirHistory;
ListCardWidget({this.dzikirHistory});
#override
_ListCardWidget createState() {
return new _ListCardWidget(dzikirHistory: dzikirHistory);
}
}
class _ListCardWidget extends State<ListCardWidget> {
bool isHiddenText1;
bool isHiddenText2;
DzikirHistory dzikirHistory;
#override
Widget build(BuildContext context) {
return Column(
children: <Widget>[
Container(
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
isHiddenText1 ? Container() : this.Text1Row(context),
isHiddenText2 ? Container() : this.Text2Row(context),
SizedBox(height: 10,),
],
)
],
),
),
Divider(height: 2, color: Pigment.fromString(UIData.primaryColor),),
],
);
}
Widget Text1Row(context) {
return Column(
children: <Widget>[
SizedBox(height: 10,),
Row(
children: <Widget>[
SizedBox(child: Image.asset("assets/images/home/my-zikir-total.png"),height: 20, width: 20,),
SizedBox(width: 10,),
Text('Text 1 ='+getNumberFormat(dzikirHistory.dzikirTotal.toString()),
style: TextStyle(
fontSize: 16,
color: Pigment.fromString(UIData.primaryColor)
),
),
],
),
],
);
}
Widget Text2Row(context) {
return Column(
children: <Widget>[
SizedBox(height: 10,),
Row(
children: <Widget>[
SizedBox(child: Image.asset("assets/images/home/my-point.png"),height: 20, width: 20,),
SizedBox(width: 10,),
Text('Text 2 ='+getNumberFormat(dzikirHistory.counter.toString()),
style: TextStyle(
fontSize: 16,
color: Pigment.fromString(UIData.primaryColor)
),
),
],
),
],
);
}
getNumberFormat(String str) {
final f = new NumberFormat("#.###");
return str.replaceAll(f.symbols.GROUP_SEP, '');
}
...
}//end of class List Card Widget
Other Class (Model) :
class DzikirHistory {
static const CATEGORY_POINT = "point";
static const CATEGORY_DZIKIR = "dzikir";
int id;
int counter;
int dzikirTotal;
String dzikirDate;
dynamic status;
dynamic createdAt;
dynamic updatedAt;
List<DzikirDetail> dzikirDetails;
DzikirHistory({
this.id,
this.counter,
this.dzikirTotal,
this.dzikirDate,
this.status,
this.createdAt,
this.updatedAt,
this.dzikirDetails
});
factory DzikirHistory.fromJson(Map<String, dynamic> json) => new DzikirHistory(
id: json["id"],
counter: json["counter"],
dzikirTotal: json["dzikir_total"],
dzikirDate: json["dzikir_date"],
status: json["status"],
createdAt: DateTime.parse(json["created_at"]),
updatedAt: DateTime.parse(json["updated_at"]),
// dzikirDetails: new List<DzikirDetail>.from(json["dzikir_details"].map((x) => DzikirDetail.fromJson(x))),
);
Map<String, dynamic> toJson() => {
"id": id,
"counter": counter,
"dzikir_total": dzikirTotal,
"dzikir_date": dzikirDate,
"status": status,
"created_at": createdAt.toIso8601String(),
"updated_at": updatedAt.toIso8601String(),
// "dzikir_details": new List<dynamic>.from(dzikirDetails.map((x) => x.toJson())),
};
}
Bloc Code:
class ZikirHistoryBloc extends Object implements BlocBase {
...
init() async {
_tabSelectedValueController.sink.add(1);
_userController.sink.add(User.fromJson(await Storage.getUser()));
}
onChangeTab(int segment) {
_tabSelectedValueController.sink.add(segment);
if (segment == 1) {
_dzikirHistoriesController.sink.add(dzikirHistories);
} else {
_dzikirHistoriesController.sink.add(dzikirLastHistories);
}
}
...
}
Any Idea ?
Thanks In Advance
UPDATE
Using #FadhliS solution not working because when i click last month the data wont refresh (previously it's normal). also, the show/hide only works if i click last month or this month button.
The best solution would be using inherited widget/provider/scopedModel plugins as you want to manage the state globally across many classes from parent to children.You should read about those and incorporate them into your project.
But you can also try this, it's a small fix but not the ideal solution
Create two booleans in your parent state class and pass it to your child list widget class. You can set state to those too
class MainScreen extends StatefulWidget {
#override
_MainScreenState createState() {
return new _MainScreenState();
}
}
class _MainScreenState extends State<MainScreen> {
ZikirHistoryBloc zikirHistoryBloc;
int selectedValue = 1;
//you don't have to declare false as bool is initialised false by default
bool showText1 = false;
bool showText2 = false;
#override
Widget build(BuildContext context) {
return Scaffold(
...
Expanded(
child: ButtonMenuWidget(
image: "assets/images/zikir/button-text1.png",
title: translations.text("button_show_hide_text1"),
subtitle: point,
onTap: () {
setState(){
showText1 = !showText1;
}
}
)
),
Expanded(
child: ButtonMenuWidget(
image: "assets/images/home/button-text2.png",
title: translations.text("button_show_hide_text2"),
subtitle: dzikir,
onTap: () {
setState(){
showText2 = !showText2;
}
}
)
),
...
this.HistoriesWidget(),
...
}//::end of Widget build
...
Widget HistoriesWidget() {
return StreamBuilder(
stream: zikirHistoryBloc.dzikirHistoriesStream,
builder: (BuildContext ctx, AsyncSnapshot<List<DzikirHistory>> snapshot) {
if (snapshot.hasError) return new Text('Error: ${snapshot.error}');
if (!snapshot.hasData) return Center(child: ActivityIndicatorWidget());
if (snapshot.data.length <= 0) return Center(child: Text(translations.text("empty_data")));
return ListView.builder(
shrinkWrap: true,
itemCount: snapshot.data.length,
primary: false,
physics: const NeverScrollableScrollPhysics(),
itemBuilder: (ctx, i) {
//**Below will call class ListCardWidget**
return ListCardWidget(
dzikirHistory: snapshot.data[i],
showText1: showText1,
showText2: showText2
);
}
);
}
);
}
...
} //
And then in your list card widget class, pass it as parameter and use it
class ListCardWidget extends StatefulWidget {
DzikirHistory dzikirHistory;
bool showText1;
bool showText2;
ListCardWidget({this.dzikirHistory, this.showText1, this.showText2});
#override
_ListCardWidget createState() {
//you dont have to pass the elements to your state class
return new _ListCardWidget();
}
}
class _ListCardWidget extends State<ListCardWidget> {
//remove all these variables
//you can access all the variables directly from the stateful class
//widget.yourvariable
bool isHiddenText1;
bool isHiddenText2;
DzikirHistory dzikirHistory;
#override
Widget build(BuildContext context) {
return Column(
children: <Widget>[
Container(
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
widget.showText1 ? Container() : this.Text1Row(context),
widget.showText2 ? Container() : this.Text2Row(context),
SizedBox(height: 10,),
],
)
],
),
),
Divider(height: 2, color: Pigment.fromString(UIData.primaryColor),),
],
);
}
Widget Text1Row(context) {
return Column(
children: <Widget>[
SizedBox(height: 10,),
Row(
children: <Widget>[
SizedBox(child: Image.asset("assets/images/home/my-zikir-total.png"),height: 20, width: 20,),
SizedBox(width: 10,),
Text('Text 1 ='+getNumberFormat(widget.dzikirHistory.dzikirTotal.toString()),
style: TextStyle(
fontSize: 16,
color: Pigment.fromString(UIData.primaryColor)
),
),
],
),
],
);
}
Widget Text2Row(context) {
return Column(
children: <Widget>[
SizedBox(height: 10,),
Row(
children: <Widget>[
SizedBox(child: Image.asset("assets/images/home/my-point.png"),height: 20, width: 20,),
SizedBox(width: 10,),
Text('Text 2 ='+getNumberFormat(widget.dzikirHistory.counter.toString()),
style: TextStyle(
fontSize: 16,
color: Pigment.fromString(UIData.primaryColor)
),
),
],
),
],
);
}
getNumberFormat(String str) {
final f = new NumberFormat("#.###");
return str.replaceAll(f.symbols.GROUP_SEP, '');
}
...
}//end of class List Card Widget
List<ServicesMensCollection> menServicesList = []
..add(ServicesMensCollection('ihdgfstfyergjergdshf', 'janik', 10))
..add(ServicesMensCollection('ihdgfstfyergjerg', 'janik', 10))
..add(ServicesMensCollection('ihdgfstfyergjerg', 'janik', 10))
..add(ServicesMensCollection('ihdgfstfyergjergdf', 'janik', 10))
bool _value2 = false;
void _value2Changed(bool value) => setState(() => _value2 = value);
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: new Scaffold(
body: new Container(
decoration: new BoxDecoration(color: const Color(0xFFEAEAEA)),
child: Padding(
padding: EdgeInsets.fromLTRB(10.0, 10.0, 10.0, 10.0),
child: Column(
children: <Widget>[
servicesCategory(),
],),),)); }
Widget servicesButton() {
return Container(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
RaisedButton(
onPressed: () {listView();},
child: Text('Mens'),),
RaisedButton(
onPressed: () {listView();},
child: Text('Womens')),
RaisedButton(
onPressed: () {listView();},
child: Text('Childrens'),
)]); }
Widget listView(){
return ListView.builder(
itemCount: menServicesList.length,
itemBuilder: (BuildContext context, int index) {
return list(index); },);
}
Widget list(int index){
return Container(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
Text(menServicesList[index].name),
Text(menServicesList[index].name),
Checkbox(onChanged:_value2Changed,
value: _value2,
)],),);
}}
I am implementing listview with checkbox in my project.I have 3 buttons which is created in a row.I want to display the list when the button is clicked.Here the issue is listview is not at all visible for me.I had implemented the same example in android but i don't know how to do this in flutter.
Try this. This is a sample screen which you can refer for your implementation.
In this there are 3 sample list which are being replaced to main list on selection, you can add a function which will sort the list based on selection (so no need to have multiple lists)
import 'package:flutter/material.dart';
/*
These are the sample list for demo
*/
List<ItemVO> mainList = List();
List<ItemVO> sampleMenList = [
ItemVO("1", "Mens 1"),
ItemVO("2", "Mens 2"),
ItemVO("3", "Mens 3")
];
List<ItemVO> sampleWomenList = [
ItemVO("1", "Women 1"),
ItemVO("2", "Women 2"),
ItemVO("3", "Women 3")
];
List<ItemVO> sampleKidsList = [
ItemVO("1", "kids 1"),
ItemVO("2", "kids 2"),
ItemVO("3", "kids 3")
];
class TestScreen extends StatefulWidget {
#override
State<StatefulWidget> createState() {
return _TestScreen();
}
}
class _TestScreen extends State<TestScreen> {
#override
void initState() {
super.initState();
mainList.addAll(sampleMenList);
}
#override
Widget build(BuildContext context) {
return Material(
child: Stack(
children: <Widget>[
ListView.builder(
itemBuilder: (BuildContext context, index) {
return getCard(index);
},
itemCount: mainList.length,
),
Container(
margin: EdgeInsets.only(bottom: 20),
alignment: Alignment.bottomCenter,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
FloatingActionButton(
onPressed: () {
mainList.clear();
setState(() {
mainList.addAll(sampleMenList);
});
},
heroTag: "btn1",
child: Text("Mens"),
),
FloatingActionButton(
onPressed: () {
mainList.clear();
setState(() {
mainList.addAll(sampleWomenList);
});
},
heroTag: "btn2",
child: Text("Women"),
),
FloatingActionButton(
onPressed: () {
mainList.clear();
setState(() {
mainList.addAll(sampleKidsList);
});
},
heroTag: "btn3",
child: Text("Kids"),
)
],
),
),
],
),
);
}
/*
Get the card item for a list
*/
getCard(int position) {
ItemVO model = mainList[position];
return Card(
child: Container(
height: 50,
alignment: Alignment.center,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
"ID:: "+model._id,
style: TextStyle(fontSize: 18, color: Colors.black),
),
Padding(padding: EdgeInsets.only(left: 5,right: 5)),
Text(
"Name:: "+model._name,
style: TextStyle(fontSize: 18, color: Colors.black),
)
],
),
),
margin: EdgeInsets.all(10),
);
}
}
/*
Custom model
i.e. for itemList
*/
class ItemVO {
String _id, _name;
String get id => _id;
set id(String value) {
_id = value;
}
get name => _name;
set name(value) {
_name = value;
}
ItemVO(this._id, this._name);
}
In your code you didn't added ListView in widget, so it will not show any list, so try adding ListView in widget and then change the list data and try it.
I think You have 2 choices on how to tackle your problem.
Preload the listViews and set their visibility to gone / invisible
Try to play around with the code from this blog