how to get and update Rangeslider values from database? - android

I want to update the RangeSlider values from the database. but I don't know how to do this please help to show and update the RangeSlider values from the database. I have two values from the database for RangeSlider to start and end which i set in getData() data but when I initialize the values in Rnageslider it gives me the error The argument type 'RangeValues?' can't be assigned to the parameter type 'RangeValues'. and also in RangeLabels(_currentRangeValues.start.round().toString(),_currentRangeValues.end.round().toString(),)
In RangeLabels it gives me an error:- The property 'start' can't be unconditionally accessed because the receiver can be 'null'. Try making the access conditional (using '?.') or adding a null check to the target ('!'). and same for end
values:- _currentRangeValues = RangeValues(data[0]['age1'], data[0]['age2']);
values which comes from databse:- 20 60 in getDData() function
here is my code:-
class Age extends StatefulWidget {
Age({Key? key}) : super(key: key);
#override
_Age createState() => _Age();
}
class _Age extends State<Age >{
var UsrID = Auth.prefs?.getString('usrid');
var data;
RangeValues? _currentRangeValues;
#override
void initState() {
super.initState();
getData();
}
getData() async{
var res = await http.get(Uri.https('www.*******.com',
'/index.php',{'act':'profile','UsrID': '${UsrID}'}));
data = jsonDecode(res.body);
print(data);
_currentRangeValues = RangeValues(data[0]['age1'], data[0]['age2']);
setState(() {});
print(res.body);
}
//RangeValues _currentRangeValues = RangeValues(30, 70);
#override
Widget build(BuildContext context){
return Scaffold(
Container(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Age',
style: TextStyle(
color: Color(0xff2c3531),
),
),
addVerticalSpace(10),
RangeSlider(
activeColor: Color(0xff8f9df2),
inactiveColor: Color(0xff9a9a9a),
values: _currentRangeValues!,
max: 100,
divisions: 5,
labels: RangeLabels(
_currentRangeValues!.start.round().toString(),
_currentRangeValues!.end.round().toString(),
),
onChanged: (RangeValues? values) {
setState(() {
_currentRangeValues = values;
});
},
),
],
),
)
}
Anyone, please help how to initialize dynamic data in `RangeValues
Here is error in RangeSlider() widget :-

You have to use Nullable types to avoid this issue.
change RangeValue to RangeValue?.
and you have to use ! at _currentRangeValue!.start.round().toString()
you can find more info on null safety Here

Related

how initialize variable in GetX controller?

I have GetxController with the late Map data and I won't fill this in onInit() after searching on the database, but when the page is open the emulator shows the red screen with the not initialize error.
I need the dataMap1 and 2 for showing the PieChart when the screen opens.
I think this occurred because I use the Future function, But I do not know how to fix this.
this is my entire controller code.
import 'package:get/get.dart';
import 'package:hive/hive.dart';
class ReportScreenController extends GetxController{
late Map<String, double> dataMap1;
final Map<String, double> dataMap2 = {
"ورزشی": 5,
"خصوصی": 3,
"اداری": 5,
"دسته بندی نشده": 3,
};
#override
Future<void> onInit() async {
super.onInit();
//categoryScrollController.position.ensureVisible()
await reportFunction();
}
Future<void> reportFunction() async {
//dataMap1
var taskBox = await Hive.openBox('task');
var taskFinish =
taskBox.values.where((task) => task.status == true).toList();
var taskUnFinish =
taskBox.values.where((task) => task.status == false).toList();
double test = double.parse(taskFinish.length.toString());
double test2 = double.parse(taskUnFinish.length.toString());
print(test.toString());
print(test2.toString());
dataMap1.addAll({
'رو زمین مانده': test2,
'تکمیل شده': test,
});
}
}
my view code is
class ReportScreen extends GetView<ReportScreenController> {
const ReportScreen({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Scaffold(
body: Stack(
fit: StackFit.expand,
children: [
background(),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 15.0),
child: Column(
children: [
const Text(':نمودار فعالیت', style: boldText),
MyPieChart(dataMap: controller.dataMap1),
const Text(':نمودار وظایف', style: boldText),
MyPieChart(dataMap: controller.dataMap2),
],
),
),
],
),
);
}
}
You forgot to initialize dataMap1, simply in onInit() add dataMap1 = {}.
I think you also dont need a late modifier, just use final final Map<String, double> dataMap1 = {};, but everybody is choosing thier weapons.
In addition i think there will be problem with that how you use controller.dataMap1 in your view. Most likely you dont rebuild your view after you finally initialize / populate dataMap1.
Update:
You can change in controller:
late Map<String, double> dataMap1; to final RxMap<String, double> dataMap1 = RxMap();, and in your view:
MyPieChart(dataMap: controller.dataMap1), to Obx(() => MyPieChart(dataMap: controller.dataMap1.value))

How to update flutter RangeSlider values which comes from database

I have static values of RangeSlider now I have to update the values and set them from static to dynamic. but I don't know how to do this please help to show and update the RangeSlider values from the database.
I have two vlaues from the database for RangeSlider to start and end in getData() data but I don't know how to initialize the values outside the build method.
values:- start = data[0]['age1'], end = data[0]['age2']
values which comes from databse:- 20 60
Here is my code:
class Age extends StatefulWidget {
Age({Key? key}) : super(key: key);
#override
_Age createState() => _Age();
}
class _Age extends State<Age >{
var UsrID = Auth.prefs?.getString('usrid');
var data;
#override
void initState() {
super.initState();
getData();
}
getData() async{
var res = await http.get(Uri.https('www.*******.com',
'/index.php',{'act':'profile','UsrID': '${UsrID}'}));
data = jsonDecode(res.body);
print(data);
setState(() {});
print(res.body);
}
//var start = data[0]['age1'];
//var end= data[0]['age2'];
//RangeValues _currentRangeValues = RangeValues(start,end);
RangeValues _currentRangeValues = RangeValues(30, 70);
#override
Widget build(BuildContext context){
return Scaffold(
Container(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Age',
style: TextStyle(
color: Color(0xff2c3531),
),
),
addVerticalSpace(10),
RangeSlider(
activeColor: Color(0xff8f9df2),
inactiveColor: Color(0xff9a9a9a),
values: _currentRangeValues,
max: 100,
divisions: 5,
labels: RangeLabels(
_currentRangeValues.start.round().toString(),
_currentRangeValues.end.round().toString(),
),
onChanged: (RangeValues values) {
setState(() {
_currentRangeValues = values;
});
},
),
],
),
)
}
Anyone please help how i add dynamic data in RangeValues _currentRangeValues = RangeValues(20, 70);
New error:-
Define _currentRangeValues in the class level
var data;
RangeValues? _currentRangeValues;
And initialize the range with getData call
getData() async{
var res = await http.get(Uri.https('www.*******.com',
'/index.php',{'act':'profile','UsrID': '${UsrID}'}));
data = jsonDecode(res.body);
_currentRangeValues = RangeValues(data[0][age1], data[0]['age2']);
}
And in order to make an async call in initstate use
#override
void initState() {
super.initState();
WidgetsBinding.instance.addPostFrameCallback((_) {
//makes the call when the UI is done.
getData();
});
}

Passing variable value from state to another widget

I am struggling with one simple case and it would be lovely if someone could help here.
Let's say that I have some stateful widget. In its state I define a variable (might be of any type) and this variable is later changed through setState() method, where I dynamically assign its value based on some certain criteria. Evertyhing until this point is conducted within one class.
What if I would like to access the value of this variable from another class (totally different page) and if its value changes, rebuild it? Could you please also give me some examples?
Thanks in advance!
That's exactly why State MANAGEMENT exists.
To manage your state through your app.
There are many different options to follow
See:
https://flutter.dev/docs/development/data-and-backend/state-mgmt/options
You can use provider package in that case.
In yaml file add,
provider: ^4.3.2+4
class HomeApp extends StatefulWidget {
#override
_HomeAppState createState() => _HomeAppState();
}
class _HomeAppState extends State<HomeApp> {
Counter _counterProvider;
#override
void initState() {
super.initState();
_counterProvider = Provider.of(context, listen: false);
}
void updateCounter() {
_counterProvider.setCount();
}
#override
Widget build(BuildContext context) {
Counter _counterProvider = Provider.of(context);
return Scaffold(
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Container(
child: Text(
_counterProvider.count.toString(),
style: TextStyle(
fontSize: 22,
),
),
),
RaisedButton(
onPressed: updateCounter,
child: Text('Click'),
),
],
),
),
);
}
}
// class for storing data(Counter.dart)
import 'package:flutter/material.dart';
class Counter extends ChangeNotifier { // create a common file for data
int _count = 0;
int get count => _count;
void setCount() {
_count++;
notifyListeners();
}
}

Im having trouble populating ListTile in ListView.builder from database

Im having trouble populating ListTile in ListView.builder from database.
I dont have "model class" since i dont need to update delete data i just need simple query.
I have ExpansionTile with three categories and in each one i need query from db. I dont know hoe to write or what to return from db class for this to work.
child: Column(
children: <Widget>[
Expanded(
child: ListView.builder(
itemBuilder: (context, i) => ExpansionTile(
title: new Text(
'${categoryName[i]}',
style: TextStyle(
fontSize: 18,
fontStyle: FontStyle.normal,
fontWeight: FontWeight.bold,
color: Color.fromRGBO(49, 85, 158, 1)),
),
children: list //final list = new List.generate(17, (i) => "Item ${i + 1}"); --just to populete with dummy items, instad of this i need db data
.map((val) => ListTile(
// leading: Icon(Icons.add),
title: new Row(
children: <Widget>[
new Checkbox(
value: _isCheck,
onChanged: (bool value) {
onChange(value);
}),
new Expanded(child: new Text(val)),
],
)))
.toList(),
),
itemCount: categoryName.length,
),
),
],
),
From my db class :
Future<List> getAllNotes() async {
var databasesPath = await getDatabasesPath();
String path = join(databasesPath, 'books.db');
Database database = await openDatabase(path, version: 1);
//var dbClient = await database();
var result = await database.rawQuery('SELECT * FROM $booksTable WHERE $colDescription = ${'Adventure'}');
return result.toList();
}
So how to write simple query to get result in ListView/ListTile?
You really need to provide much more details about your problem. Anyways, ill try to answer with what I have understood.
Let's say you have a table names 'booksTable' with 3 fields:
bookId | bookName | bookCategory
1 Book A Adventure
2 Book B History
3 Book C Adventure
4 Book D History
Make sure you create all these database functions in DatabaseHelper() class, so that you don't have to write logic to db again and again.
Now you query will look something like this:
Future<List<String>> getAllNotes(String category) async {
var dbClient = await database();
List<String> bookNames = List<String();
var result = await dbClient.rawQuery("SELECT bookname FROM booksTable WHERE bookCategory = $category");
result.forEach((item) {
bookNames.add(item["bookname"]);
});
return bookNames;
}
This will work only if you have to deserialise 1 column. If you have multiple columns selected, you have to create a model class.
Now in your front view, you have two options:
1) You can use initState to populate your List with bookNames of category in the parameter
2) You can use FutureBuilder to populate your list as well
(You have to use StatefulWidget for both these options)
I'll show you how to do it using initState here. If you want to know how to do it using FutureBuilder, let me know in comments.
List<String> booksList =List<String>();
var db = DatabaseHelper();
readList() async {
booksList = await db.getAllNotes("Adventure");
}
#override
void initState() {
super.initState();
readList();
}
ListView.builder(
itemBuilder: (context, i) {
Column( crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
ExpansionTile(
title: new Text(
"Adventure Category",
style: TextStyle(
fontSize: 18,
fontStyle: FontStyle.normal,
fontWeight: FontWeight.bold,
color: Color.fromRGBO(49, 85, 158, 1)),
),
ListTile(
title: new Row(
children: <Widget>[
new Checkbox(
value: _isCheck,
onChanged: (bool value) {
onChange(value);
}),
Expanded(child: new Text("${booksList[i]}")),
],
)))
),])}
itemCount: booksList.length,
),
),
],
)
Note: There might be typos in the code above, since i have typed it on phone, but you get the idea how to do it, right?
So, i have ListView (with 3 expanded groups) im geting them from array: ( List categoryName = ['Part 1: Adventure', 'Part 2: History','Part 3: Horror'];
And passing then here :
child: Column(
children: [
Expanded(
child: ListView.builder(
itemBuilder: (context, i) => ExpansionTile(
title: new Text(
'${categoryName[i]}',
),
That part working fine, i get 3 expandeble titles, now children of that ( ListTile ) need to be populate from db .
With your example :
readList() async {
sinsAgainstGod = await db.getSins("Adventure");
}
I get error: ...near "Adventure": syntax error..
And keep geting 0 lenght on booksList...
Future<List<String>> getNotes(String category) async {
var databasesPath = await getDatabasesPath();
String path = join(databasesPath, 'books.db');
Database database = await openDatabase(path, version: 1);
List<String> bookNames = List<String>();
var result = await database.rawQuery("SELECT $colDescription FROM $booksTable WHERE = $category ");
result.forEach((item) {
bookNames.add(item['Category']);
});
return bookNames;
}
What this result.forEach(item) suppose to do?
Thank you for your answer it was helpful.
Can you tell me why im getting 20 same description instead literate through all with this code:
Future<List<String>> getSins(String column) async {
var databasesPath = await getDatabasesPath();
String path = join(databasesPath, 'confession.db');
Database database = await openDatabase(path, version: 1);
List<String> bookNames = List<String>();
for (int i = 0; i < 20; i++) {
var result = await database.rawQuery(
'SELECT * FROM $plannerTable WHERE $colCategory= "Adventure');
bookNames.add((result[0][column].toString()));
}
return bookNames;
}
I want to get all decription from adventure category. Tnx

Flutter - How can I set the state of a Checkbox widget in a dynamic list of Checkbox

Sorry if this isn't perfectly clear. I welcome any suggestions for clarification as I'm new to Flutter and also to asking questions on StackOverflow.
I'll post what is and isn't working. Basically I want to have a Perk widget with a varying number of Checkbox widgets in it. When I create the widgets within the build method I can set the state of them (checked or unchecked) but dynamically creating Checkbox widgets using a for loop in a list and passing that list to a Row makes the Checkboxes unresponsive.
DOESN'T WORK (but I don't know why and it's what I'm going for)
import 'package:flutter/material.dart';
import 'package:gloomhaven_enhancement_calc/data/constants.dart';
class Perk extends StatefulWidget {
final int numOfChecks;
final String details;
final List<String> icons;
Perk(this.numOfChecks, this.details, this.icons);
#override
State<StatefulWidget> createState() => PerkState();
}
class PerkState extends State<Perk> {
int _numOfChecks;
String _details;
List<String> _icons;
bool _isChecked = false;
List<Checkbox> checkList = [];
#override
void initState() {
super.initState();
_numOfChecks = widget.numOfChecks;
_details = widget.details;
_icons = widget.icons;
setState(() {
void _itemChange(bool val) {
// setState(() {
_isChecked = val;
// });
print('clliccked' + val.toString());
}
for (int x = 0; x < _numOfChecks; x++) {
checkList.add(Checkbox(
value: _isChecked,
onChanged: (bool value) => _itemChange(value),
),);
}
});
}
Widget build(BuildContext context) {
return Container(
color: Colors.grey.withOpacity(0.75),
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
// here I pass the list of checkboxes created above, but they
// don't respond to user clicks
Row(children: checkList),
Expanded(
child: Text(
_details,
style: TextStyle(fontFamily: secondaryFontFamily),
),
),
],
));
}
}
WORKS (but I have to hard-code in the number of checkboxes - I need to be able to create them dynamically based on numOfChecks parameter)
import 'package:flutter/material.dart';
import 'package:gloomhaven_enhancement_calc/data/constants.dart';
class Perk extends StatefulWidget {
final int numOfChecks;
final String details;
final List<String> icons;
Perk(this.numOfChecks, this.details, this.icons);
#override
State<StatefulWidget> createState() => PerkState();
}
class PerkState extends State<Perk> {
int _numOfChecks;
String _details;
List<String> _icons;
bool _isChecked = false;
List<Checkbox> checkList = [];
#override
void initState() {
super.initState();
_numOfChecks = widget.numOfChecks;
_details = widget.details;
_icons = widget.icons;
}
void checkboxChecked(bool val) {
// setState(() {
_isChecked = val;
// });
print('clliccked' + val.toString());
}
Widget build(BuildContext context) {
return Container(
color: Colors.grey.withOpacity(0.75),
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Row(children:
<Widget>[
// here I create checkboxes based on the number but it's
// obviously a hack just to make it work
Checkbox(
value: _isChecked,
onChanged: (bool value) => checkboxChecked(value),
),
_numOfChecks > 1 ? Checkbox(
value: _isChecked,
onChanged: (bool value) => checkboxChecked(value),
) : Container(),
_numOfChecks > 2 ? Checkbox(
value: _isChecked,
onChanged: (bool value) => checkboxChecked(value),
) : Container(),
_numOfChecks > 3 ? Checkbox(
value: _isChecked,
onChanged: (bool value) => checkboxChecked(value),
) : Container(),
_numOfChecks > 4 ? Checkbox(
value: _isChecked,
onChanged: (bool value) => checkboxChecked(value),
) : Container(),
]
),
Expanded(
child: Text(
_details,
style: TextStyle(fontFamily: secondaryFontFamily),
),
),
],
));
}
}
BONUS
I need to also save each checkbox state in sharepreferences. I was going to just create a separate entry for each one but I'm sure there's a more efficient way. They don't need to do anything, just need to remember if they're checked or unchecked and persist that through restarts.
DOESN'T WORK section has a lot of mistakes.
You have to store details of checkboxes (titles, icons, count) inside of Perk class. You need only titles and icons. Then you can retrieve checkboxes count by calling titles.length.
State of checked items has to be inside of State class (List checkList).
Change type of _checkList to List and initialize it in initState.
#override
void initState() {
super.initState();
...
_checkList = List(widget.titles.length);// or List.generate(widget.numOfChecks, (i) => false);
}
To build a number of widgets (or other items) you can use this approach:
Row(
children: List.generate(
_numOfChecks,
(i) => Checkbox(
value: _checkList[i],
onChanged: (bool value) => setState(() { _checkList[i] = value; }),
)
).toList();
)
I hope my answer will help you to find right solution.

Categories

Resources