List.Builder giving range error in Flutter - flutter

I have added my entire code over here. The getRecords method takes more time to add to the lists and hence my list returns empty at first and so listbuilder fails giving range error and that only range accepted is 0. BTW, Its a Todo app.
InitState :
void initState() {
super.initState();
setState(() {
getRecords();
});
}
Getting from the database
void getRecordsAndDisplay() async {
final records = await Firestore.instance.collection('tasks').getDocuments();
for (var record in records.documents) {
if (record.data['phone'] == '1') {
int len = record.data['task'].length;
if (len != null || len != 0) {
for (int i = 0; i < len; i++) {
String temp = record.data['task'][i];
tasks.add(temp);
}
}
else
continue;
}
else
continue;
}
setState(() {
listView = ListView.builder(
scrollDirection: Axis.vertical,
itemCount: tasks.length,
itemBuilder: (BuildContext context,int index) {
return Container(
margin: EdgeInsets.only(bottom: 10.0),
decoration: BoxDecoration(
color: Colors.deepPurple[700],
borderRadius: BorderRadius.all(Radius.circular(20.0)),
),
child: ListTile(
onTap: (){},
leading: IconButton(
icon: Icon(Icons.delete),
iconSize: 25.0,
color: Colors.white,
onPressed: () {
setState(() {
tasks.removeAt(index);
checkValue.removeAt(index);
updateValue();
});
},
),
title: Text(
'${tasks[index]}',
style: TextStyle(
fontSize: 18.0,
color: Colors.white,
fontWeight: FontWeight.bold,
decoration: checkValue[index]
? TextDecoration.lineThrough
: null,
),
),
trailing: Checkbox(
value: checkValue[index],
activeColor: Colors.white,
checkColor: Colors.deepPurple[700],
onChanged: (bool value) {
setState(() {
checkValue[index] = !checkValue[index];
});
},
),
),
);
},
);
});
}
Scaffold:
return Scaffold(
backgroundColor: Color(0xff8780FF),
body: SafeArea(
child: Container(
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topRight,
colors: [Colors.deepPurple[400], Color(0xff6B63FF)])),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Container(
padding: EdgeInsets.fromLTRB(30.0, 30.0, 30.0, 15.0),
decoration: BoxDecoration(boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.2),
spreadRadius: 1.0,
blurRadius: 50.0,
),
]),
child: Icon(
Icons.list,
color: Colors.white,
size: 30.0,
),
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Container(
padding: EdgeInsets.only(
bottom: 20.0,
left: 30.0,
),
child: Text(
'Todo List',
style: TextStyle(
color: Colors.white,
fontSize: 35.0,
fontWeight: FontWeight.w900,
),
),
),
Expanded(
child: SizedBox(
width: 20.0,
),
),
IconButton(
padding: EdgeInsets.only(
right: 10.0,
bottom: 20.0,
),
icon: Icon(Icons.add),
iconSize: 30.0,
color: Colors.white,
onPressed: () async {
final resultText = await showModalBottomSheet(
context: context,
builder: (context) => AddTaskScreen(),
isScrollControlled: true);
setState(() {
tasks.add(resultText);
checkValue.add(false);
Firestore.instance
.collection('tasks')
.document('1')
.updateData({
'task': FieldValue.arrayUnion([resultText]),
});
});
},
),
IconButton(
padding: EdgeInsets.only(
right: 10.0,
bottom: 20.0,
),
icon: Icon(Icons.delete_outline),
iconSize: 30.0,
color: Colors.white,
onPressed: () {
setState(() {
tasks.clear();
checkValue.clear();
Firestore.instance
.collection('tasks')
.document('1')
.updateData({
'task': null,
});
});
},
),
],
),
],
),
Flexible(
child: Container(
padding: EdgeInsets.only(left: 10.0, right: 10.0),
height: MediaQuery.of(context).size.height,
child: listView,
),
),
],
),
),
),
);
Please help me out. I am stuck with this for a long time :(

the problem is that in initstate you cannot await for async methods so you should implement a StreamBuilder that wraps your listview..
A streambuilder is a widget that takes a stream and waits for the call completition then when the data is ok shows a widget -> your listview
A little example
StreamBuilder(
stream: YOUR_ASYNC_CALL_THAT_RETURN_A_STREAM,
builder: (context, snapshot) {
if (!snapshot.hasData) {
return Container(
alignment: Alignment.center,
child: Text(
"NO ITEMS"
),
);
}
else {
var yourList = snapshot.data.documents;//there you have to do your implementation
return ListView.builder(
itemBuilder: (context, index) => buildItem(index,yourList[index]),
itemCount: yourList.length,
);
}
},
),

Related

How do i return a container based on a list of item selected in flutter?

I have a list of items
List<String> items = [
"All",
"Jobs",
"Messages",
"Customers",
];
int current = 0;
And this list is directly responsible for my tab bar:
When i tap an item in the Tab bar i want to return a different container on each of them?
How do i go about this in flutter?
I tried returning an if statement just before the container but it seems i don't get the statement correctly.
this is the container i want to return if the item user select is All, and then put conditions in place for the rest items.
this is how i put the condition but it gives me this error
My return statement and code -
current = 0 ??
Container(
margin: const EdgeInsets.only(top: 30),
height: MediaQuery.of(context).size.height * 1,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const SizedBox(
height: 10,
),
Text(
items[current],
style: GoogleFonts.laila(
fontWeight: FontWeight.w500,
fontSize: 30,
color: Colors.deepPurple),
),
],
),
),
current = 1 ?? Text('hello')
FULL WIDGET ADDED
class NotificationsView extends StatefulWidget {
#override
State<NotificationsView> createState() => _NotificationsViewState();
}
class _NotificationsViewState extends State<NotificationsView> {
final controller = Get.put(NotificationsController());
List<String> items = [
"All",
"Jobs",
"Messages",
"Customers",
];
int current = 0;
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(
"Notifications".tr,
style: GoogleFonts.poppins(
color: Color(0xff000000),
fontSize: 16,
fontWeight: FontWeight.w600),
),
centerTitle: false,
backgroundColor: Colors.transparent,
elevation: 0,
automaticallyImplyLeading: false,
leadingWidth: 15,
leading: new IconButton(
icon: new Icon(Icons.arrow_back_ios, color: Color(0xff3498DB)),
onPressed: () => {Get.back()},
),
),
body: RefreshIndicator(
onRefresh: () async {
},
child: ListView(
primary: true,
children: <Widget>[
filter(),
],
),
),
);
}
Widget notificationsList() {
return Obx(() {
if (!controller.notifications.isNotEmpty) {
return CircularLoadingWidget(
height: 300,
onCompleteText: "Notification List is Empty".tr,
);
} else {
var _notifications = controller.notifications;
return ListView.separated(
itemCount: _notifications.length,
separatorBuilder: (context, index) {
return SizedBox(height: 7);
},
shrinkWrap: true,
primary: false,
itemBuilder: (context, index) {
var _notification = controller.notifications.elementAt(index);
if (_notification.data['message_id'] != null) {
return MessageNotificationItemWidget(
notification: _notification);
} else if (_notification.data['booking_id'] != null) {
return BookingNotificationItemWidget(
notification: _notification);
} else {
return NotificationItemWidget(
notification: _notification,
onDismissed: (notification) {
controller.removeNotification(notification);
},
onTap: (notification) async {
await controller.markAsReadNotification(notification);
},
);
}
});
}
});
}
Widget filter() {
return Container(
width: double.infinity,
margin: const EdgeInsets.all(5),
child: Column(
children: [
/// CUSTOM TABBAR
SizedBox(
width: double.infinity,
height: 60,
child: ListView.builder(
physics: const BouncingScrollPhysics(),
itemCount: items.length,
scrollDirection: Axis.horizontal,
itemBuilder: (ctx, index) {
return Column(
children: [
GestureDetector(
onTap: () {
setState(() {
current = index;
});
},
child: AnimatedContainer(
duration: const Duration(milliseconds: 300),
margin: const EdgeInsets.all(5),
decoration: BoxDecoration(
color: current == index
? Color(0xff34495E)
: Color(0xffF5F5F5),
borderRadius: BorderRadius.circular(11),
),
child: Center(
child: Padding(
padding: const EdgeInsets.only(
left: 10.0, right: 10.0, top: 5, bottom: 5),
child: Text(
items[index],
style: GoogleFonts.poppins(
fontSize: 12,
fontWeight: FontWeight.w500,
color: current == index
? Colors.white
: Colors.grey),
),
),
),
),
),
],
);
}),
),
/// MAIN BODY
current = 0 ??
Container(
margin: const EdgeInsets.only(top: 30),
height: MediaQuery.of(context).size.height * 1,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const SizedBox(
height: 10,
),
Text(
items[current],
style: GoogleFonts.laila(
fontWeight: FontWeight.w500,
fontSize: 30,
color: Colors.deepPurple),
),
Padding(
padding: const EdgeInsets.only(
left: 20.0, right: 20.0, top: 20.0, bottom: 20),
child: Column(
children: [
Stack(
children: [
Row(
children: [
Container(
decoration: BoxDecoration(
color: Color(0xffEFFAFF),
borderRadius:
BorderRadius.circular(20)),
child: Padding(
padding: const EdgeInsets.all(10.0),
child: Image.asset(
'assets/icon/suitcase.png'),
),
),
SizedBox(
width: 15,
),
Column(
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
Text(
'New Job started ',
style: GoogleFonts.poppins(
fontSize: 14,
fontWeight: FontWeight.w500,
color: Color(0xff151515)),
),
Text(
'Tailoring for John Cletus ',
style: GoogleFonts.poppins(
fontSize: 10,
fontWeight: FontWeight.w400,
color: Color(0xff151515)),
),
],
),
Spacer(),
Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(2),
color: Color(0xffFFE8E8),
),
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
'Urgent',
style: GoogleFonts.poppins(
color: Color(0xffC95E5E)),
),
),
),
],
),
],
),
Divider(
height: 5,
color: Color(0xffEFFAFF),
),
],
),
),
],
),
),
current = 1 ?? Text('hello')
],
),
);
}
}
You can use Builder if want to display different type of widget based on the current index.
Builder(
builder: (context) {
switch (current) {
case 0:
return Container(
margin: const EdgeInsets.only(top: 30),
height: MediaQuery.of(context).size.height * 1,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const SizedBox(
height: 10,
),
Text(
items[current],
style: GoogleFonts.laila(
fontWeight: FontWeight.w500,
fontSize: 30,
color: Colors.deepPurple),
),
],
),
);
case 1:
return Text('Hello');
default:
return SizedBox.shrink();
}
},
);
Below approach will solve your problem. If you need further assistance, please feel free to comment.
int _currentIndex = 0;
var _containers = <Widget>[
AllContainer(),
JobsContainer(),
MessagesContainer(),
CustomerContainer(),
];
Widget _bottomTab() {
return BottomNavigationBar(
currentIndex: _currentIndex,
onTap: _onItemTapped, //
type: BottomNavigationBarType.fixed,
selectedLabelStyle: const TextStyle(color: Colors.blue),
selectedItemColor: WAPrimaryColor,
unselectedLabelStyle: const TextStyle(color: Colors.blue),
unselectedItemColor: Colors.grey,
items: const <BottomNavigationBarItem>[
BottomNavigationBarItem(label: 'All'),
BottomNavigationBarItem(
label: 'Jobs'),
BottomNavigationBarItem(
label: 'Messages'),
BottomNavigationBarItem( label: 'Customer'),
],
);
}
void _onItemTapped(int index) async {
print('bottom index::: $index');
setState(() {
_currentIndex = index;
});
}
#override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
bottomNavigationBar: _bottomTab(),
body: Center(child: _containers.elementAt(_currentIndex)),
),
);
}
You can use conditional if on widget level,
like
/// MAIN BODY
if (current == 0)
Container(
margin: const EdgeInsets.only(top: 30),
height: MediaQuery.of(context).size.height * 1,
...
),
if (current == 1) Text('hello')
Also can be use else if
if (current == 0)
Container(
margin: const EdgeInsets.only(top: 30),
height: MediaQuery.of(context).size.height * 1,
) //you shouldnt put coma
else if (current == 1) Text('hello')
],
),
);
But creating a separate method will be better instead of putting it here
Widget getWidget(int index) {
/// MAIN BODY
if (current == 0) // or switch case
return Container(
margin: const EdgeInsets.only(top: 30),
height: MediaQuery.of(context).size.height * 1,
); //you shouldnt put coma
else if (current == 1) return Text('hello');
return Text("default");
}
And call the method getWidget(current).
Also there are some widget like PageView, IndexedStack will help to organize the code structure

assigning icon value based on data from flutter sqflite

I'm trying to load the favorite button on my card based on the data from database inside the future builder. while using the following code inside ListView.Builder, is sets the value to true and button click does not change it. I think it is because of FutureBuilder.
txtData.zFavourite == null
? isFavourite[index] = false
: isFavourite[index] = true;
it also requires to initialize the value for isFavourite and if it is assigned outside the widget, I do not get the data from database as it directly loads into the future builder.
how do we assign the value for isFavourite based on the data from the database and change the favourite icon based on the button click?
I also checked this link to handle button clicks for the individual list.
late List<bool> isFavourite = [false, false];
Widget _displayZhesa() {
return FutureBuilder<List<Zhebsa>>(
future: _getZhebsa(),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return const Center(
child: CircularProgressIndicator(),
);
}
if (snapshot.hasData) {
return ListView.builder(
itemCount: snapshot.data!.length,
itemBuilder: (context, index) {
final txtData = snapshot.data![index];
txtData.zFavourite == null
? isFavourite[index] = false
: isFavourite[index] = true;
return Card(
elevation: 10,
color: Colors.white70,
shadowColor: Colors.amber[500],
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
padding: const EdgeInsets.all(5.0),
width: double.infinity,
decoration: BoxDecoration(
color: Colors.orange[400],
border: Border.all(
color: Colors.amber.shade100,
width: 2,
),
),
child: Center(
child: Text(
sQuery,
style: const TextStyle(
color: Colors.black,
fontSize: 20,
fontWeight: FontWeight.w500),
),
),
),
Row(
children: <Widget>[
Center(
child: IconButton(
onPressed: () {
setState(() {
isFavourite[index] = !isFavourite[index];
});
},
/* () =>
_setFaviurite(txtData.zFavourite, index), */
icon: Icon(
isFavourite[index]
? Icons.favorite_sharp
: Icons.favorite_border_sharp,
size: 30.0,
color: Colors.redAccent,
),
),
),
Expanded(
child: ListTile(
title: const Text('ཞེ་ས།'),
subtitle: Text(txtData.zWord), //ཞེ་སའི་ཚིག
),
),
Container(
padding: const EdgeInsets.only(right: 20),
child: IconButton(
onPressed: () {
isPlayingPronunciation
? stopPronunciation()
: _playPronunciation(
'${txtData.zPronunciation}');
setState(() {
isPlayingPronunciation =
!isPlayingPronunciation;
});
},
icon: Icon(
isPlayingPronunciation
? Icons.stop_circle_outlined
: Icons.volume_up,
size: 50.0,
color: Colors.blue,
),
),
),
],
),
Container(
padding: const EdgeInsets.only(left: 30.0),
child: ListTile(
title: const Text('དཔེར་བརྗོད།'),
subtitle: SelectableText('${txtData.zPhrase}'),
),
),
],
),
);
},
);
} else {
return const Text('No Data');
}
});
}

How to remove build side effects in this context, using Staggered Grid View Builder Flutter?

I am trying to create the build method without side effects (without blinking). I solved this problem using StatefulBuilder, but I read that I should rebuild 1000x times without any change or effect.
The Staggered Grid View Builder Widget are rebuilt when the keyboard is opening, or whenever I open again the page, or add/remove an item from it. That's good, normally, but with side effects like you see below. Maybe there is any solution to animate the remove/add functionality, or the infinite reloading and keep the rest of the items in cache. So I need to limit the builder recreate inside Grid View Builder?
On other applications I don't see this ugly "blinking". Where is the problem and how can I solve it? I used Animation Limiter but it's not working for me, neither PrecacheImage, somehow I need to rebuild without blink (first items).
My code:
class VisionBoard extends StatefulWidget {
const VisionBoard({Key? key}) : super(key: key);
#override
_VisionBoardState createState() => _VisionBoardState();
}
class _VisionBoardState extends State<VisionBoard> with SingleTickerProviderStateMixin {
ScreenshotController screenshotController = ScreenshotController();
String saveGoalsButtonText = "SAVE GOALS";
String wallpaperButtonText = "CREATE WALLPAPER";
String saveWallpaperButtonText = "SAVE";
bool createWallpaper = false;
bool isWallpaperCreated = false;
late File imageFile;
late String newImage;
late Uint8List imageRaw;
int noOfImages = 0;
late Uint8List wallpaperBytes;
String title = "My Vision Board";
String goals = "";
late List<String> visions = <String>[];
final TextEditingController _textFieldController = TextEditingController();
final TextEditingController _goalsController = TextEditingController();
static final _formKey = GlobalKey<FormState>();
#override
void initState() {
super.initState();
loadVisionBoardTitleAndImages();
}
void loadVisionBoardTitleAndImages() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
//await prefs.clear();
setState(() {
_textFieldController.text = prefs.getString('titlu') ?? title;
visions = prefs.getStringList('visions') ?? <String>[];
_goalsController.text = prefs.getString('goals') ?? goals;
});
}
void _removeVisions(int index) async {
SharedPreferences prefs = await SharedPreferences.getInstance();
setState(() {
isButtonDisabled=true;
visions.removeAt(index);
prefs.setStringList('visions', visions);
createWallpaper = false;
wallpaperButtonText = "CREATE WALLPAPER";
isWallpaperCreated = false;
});
await CreateWallpaperLayouts().createWallpaper(visions).then((value) {
setState(() {
wallpaperBytes = value;
wallpaper = Image.memory(wallpaperBytes);
precacheImage(wallpaper.image, context);
isButtonDisabled=false;
});
});
}
#override
Widget build(BuildContext context) {
return Sizer(
builder: (context, orientation, deviceType) {
return GestureDetector(
onTap: () {
FocusScopeNode currentFocus = FocusScope.of(context);
if (!currentFocus.hasPrimaryFocus) {
currentFocus.unfocus();
}
},
child: Scaffold(
body: AnimationLimiter(
child: Container(
decoration: const BoxDecoration(
image: DecorationImage(
image: AssetImage("assets/background-marmura.jpeg"), fit: BoxFit.cover)),
child: SafeArea(
child: SingleChildScrollView(
child: Container(
margin: const EdgeInsets.fromLTRB(20, 0, 20, 0),
child: Column(
children: [
StatefulBuilder(
builder: (BuildContext context, StateSetter setState) {
return Row(
children: [
Flexible(
child: Text(_textFieldController.text,
style: const TextStyle(
fontWeight: FontWeight.w700,
fontSize: 21,
color: Color(0xff393432),
),
),
),
IconButton(
icon: const Icon(
Icons.edit,
size: 21,
color: Color(0xff393432),
),
onPressed: () {
showAlertDialog(context, setState);
},
)
]);
}
),
const SizedBox(height: 5),
GridView.builder(
clipBehavior: Clip.none,
physics: const ScrollPhysics(),
shrinkWrap: true,
gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent(
maxCrossAxisExtent: SizeConfig.screenWidth!/3,),
itemCount: (visions.length == 12) ? visions.length : visions.length + 1,
itemBuilder: (BuildContext ctx, index) {
if (index < visions.length) {
return AnimationConfiguration.staggeredGrid(
position: index,
duration: const Duration(milliseconds: 1000),
columnCount: 3,
child: ScaleAnimation(
child: FadeInAnimation(
child: OpacityAnimatedWidget.tween(
opacityEnabled: 1, //define start value
opacityDisabled: 0, //and end value
enabled: index < visions.length, //bind with the boolean
child: Stack(
alignment: Alignment.center,
children: [
Container(
width: 25.w,
height: 25.w,
decoration: BoxDecoration(
image: DecorationImage(
image: CleverCloset.imageFromBase64String(visions[index]).image,
fit: BoxFit.fill),
borderRadius: const BorderRadius.all(
Radius.circular(
5.0) // <--- border radius here
),
),
),
Positioned(
top:0,
right:0,
child: ClipOval(
child: InkWell(
onTap: () {
_removeVisions(index);
},
child: Container(
padding: const EdgeInsets.all(5),
color: Colors.white,
child:
const Icon(
Icons.delete,
size: 16,
color: Color(0xff393432)),
),
),
),
),
],
clipBehavior: Clip.none,
),
),
),
),
);
}
else if(index<12){
return InkWell(
onTap: () {
_openGallery(context);
},
child:
Stack(
alignment: Alignment.center,
children:[
Container(
width: 25.w,
height: 25.w,
decoration:
BoxDecoration(
border: Border.all(color: const Color(0xff393432)),
borderRadius: const BorderRadius.all(Radius.circular(5.0)),
),
child:
const Icon(
Icons.add,
size: 25,
color: Color(0xff393432),
)
),
],
),
);
}
else {
return Container(color: Colors.red);
}
}
),
const SizedBox(height: 10),
Row(
mainAxisAlignment: MainAxisAlignment.start,
children: const [
Text("You can add up to 12 pictures.",
style: TextStyle(
fontSize: 15,
fontWeight: FontWeight.w400,
fontStyle: FontStyle.italic,
),),
],
),
const SizedBox(height: 10),
StatefulBuilder(
builder: (BuildContext context, StateSetter setState) {
return Column (
children: [
if(visions.isNotEmpty && visions.length>1 && !isWallpaperCreated) Row(
children: [
SizedBox(
width: 50.w,
child: OpacityAnimatedWidget.tween(
opacityEnabled: 1, //define start value
opacityDisabled: 0, //and end value)
enabled: !isWallpaperCreated &&
visions.isNotEmpty && visions.length > 1,
child: OutlinedButton(
onPressed: visions.isNotEmpty &&
visions.length > 1 ? () async{
setState(() {
wallpaperButtonText = "CREATING...";
//_createWallpaper();
});
wallpaperBytes = await CreateWallpaperLayouts().createWallpaper(visions);
setState(() {
noOfImages = visions.length;
isWallpaperCreated = true;
createWallpaper = true;
});
//Navigator.pushReplacementNamed(context, '/masterclasses');
} : null,
style: OutlinedButton.styleFrom(
primary: const Color(0xffE4BCB4),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(
18.0),
),
side: const BorderSide(
width: 3, color: Color(0xffE4BCB4)),
),
child: Text(
wallpaperButtonText,
style: const TextStyle(
color: Color(0xff393432),
fontSize: 14,
fontWeight: FontWeight.w700,
)
),
),
),
),
],
),
const SizedBox(height:40),
if(createWallpaper==true) OpacityAnimatedWidget.tween(
opacityEnabled: 1, //define start value
opacityDisabled: 0, //and end value
enabled: createWallpaper, //bind with the boolean
child: Row(
children: const [
Flexible(
child: Text("Wallpaper",
style: TextStyle(
fontWeight: FontWeight.w700,
fontSize: 21,
color: Color(0xff393432),
),
),
),
],
),
),
if(createWallpaper==true) const SizedBox(height:15),
if(createWallpaper==true)
OpacityAnimatedWidget.tween(
opacityEnabled: 1, //define start value
opacityDisabled: 0, //and end value
enabled: createWallpaper,
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
children:[ Container(
width: 50.w,//double.infinity,
height: 50.h,//SizeConfig.screenHeight,
decoration: BoxDecoration(
image: DecorationImage(
image: Image.memory(wallpaperBytes).image,
fit: BoxFit.fill,
)
),
//child: CreateWallpaperLayouts().createWallpaper(visions),
),],
),
),
if(createWallpaper==true) const SizedBox(height:10),
if(createWallpaper==true) StatefulBuilder(
builder: (BuildContext context, StateSetter setState) {
return OpacityAnimatedWidget.tween(
opacityEnabled: 1, //define start value
opacityDisabled: 0, //and end value
enabled: createWallpaper,
child: Row(
children: [
SizedBox(
width: 50.w,
child: OutlinedButton(
onPressed: () {
_saveWallpaper(wallpaperBytes);
setState(() {
saveWallpaperButtonText = "SAVED!";
});
Future.delayed(const Duration(milliseconds: 1300), () {
setState(() {
saveWallpaperButtonText = "SAVE";
});
});
//Navigator.pushReplacementNamed(context, '/masterclasses');
},
style: OutlinedButton.styleFrom(
primary: const Color(0xffE4BCB4),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(18.0),
),
side: const BorderSide(width: 3, color: Color(0xffE4BCB4)),
),
child: Text(
saveWallpaperButtonText,
style: const TextStyle(
color: Color(0xff393432),
fontSize: 14,
fontWeight: FontWeight.w700,
)
),
),
),
const SizedBox(width: 10),
],
),
);
}
),
if(createWallpaper==true) const SizedBox(height:50),
Row(
children: const [
Flexible(
child: Text("Goals & Affirmations",
style: TextStyle(
fontWeight: FontWeight.w700,
fontSize: 21,
color: Color(0xff393432),
),
),
),
],
),
],
);
}
),
const SizedBox(height: 10),
Row(
mainAxisAlignment: MainAxisAlignment.start,
children: const [
Text("Add goals and affirmations.",
style: TextStyle(
fontSize: 15,
),),
],
),
const SizedBox(height: 10),
StatefulBuilder(
builder: (BuildContext context, StateSetter setState) {
return Column(
children: [
Card(
elevation: 0,
color: const Color(0xffEFEFEF),
child: Padding(
padding: const EdgeInsets.all(10.0),
child: TextFormField(
key: _formKey,
controller: _goalsController,
maxLines: 8,
decoration: const InputDecoration(border: InputBorder.none),
),
)
),
const SizedBox(height: 10),
Row(
children: [
Container(
width: 50.w,
margin: const EdgeInsets.fromLTRB(0, 0, 0, 40),
child: OutlinedButton(
onPressed: () async{
setState(() {
saveGoalsButtonText = "SAVED!";
});
Future.delayed(const Duration(seconds: 1), () {
setState(() {
saveGoalsButtonText = "SAVE GOALS";
});
});
SharedPreferences prefs = await SharedPreferences.getInstance();
setState(() {
goals = _goalsController.text;
prefs.setString('goals', goals);
});
//Navigator.pushReplacementNamed(context, '/masterclasses');
},
style: OutlinedButton.styleFrom(
primary: const Color(0xffE4BCB4),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(18.0),
),
side: const BorderSide(width: 3, color: Color(0xffE4BCB4)),
),
child: Text(
saveGoalsButtonText,
style: const TextStyle(
color: Color(0xff393432),
fontSize: 14,
fontWeight: FontWeight.w700,
)
),
),
),
],
),
],
);
}
),
],
),
),
),
),
),
),
),
);
}
);
}
}

How to usage Obx() with getx in flutter?

On my UI screen, I have 2 textfields in a column. If textFormFieldEntr is empty, hide textFormFiel. If there is a value in the textFormFieldEntr, let the other textfield be visible. After I set the bool active variable to false in the Controller class, I checked the value in the textFormFieldEntr in the showText class. I'm wrong using obx on the UI screen. The textfields are listed in the _formTextField method. Can you answer by explaining the correct obx usage on the code I shared?
class WordController extends GetxController {
TextEditingController controllerInput1 = TextEditingController();
TextEditingController controllerInput2 = TextEditingController();
bool active = false.obs();
final translator = GoogleTranslator();
RxList data = [].obs;
#override
void onInit() {
getir();
super.onInit();
}
void showText() {
if (!controllerInput1.text.isEmpty) {
active = true;
}
}
ekle(Word word) async {
var val = await WordRepo().add(word);
showDilog("Kayıt Başarılı");
update();
return val;
}
updateWord(Word word) async {
var val = await WordRepo().update(word);
showDilog("Kayıt Başarılı");
return val;
}
deleteWord(int? id) async {
var val = await WordRepo().deleteById(id!);
return val;
}
getir() async {
//here read all data from database
data.value = await WordRepo().getAll();
print(data);
return data;
}
translateLanguage(String newValue) async {
if (newValue == null || newValue.length == 0) {
return;
}
List list = ["I", "i"];
if (newValue.length == 1 && !list.contains(newValue)) {
return;
}
var translate = await translator.translate(newValue, from: 'en', to: 'tr');
controllerInput2.text = translate.toString();
//addNote();
return translate;
}
showDilog(String message) {
Get.defaultDialog(title: "Bilgi", middleText: message);
}
addNote() async {
var word =
Word(wordEn: controllerInput1.text, wordTr: controllerInput2.text);
await ekle(word);
getir();
clear();
}
clear() {
controllerInput2.clear();
controllerInput1.clear();
}
updateNote() async {
var word =
Word(wordEn: controllerInput1.text, wordTr: controllerInput2.text);
await updateWord(word);
await getir();
update();
}
}
UI:
class MainPage extends StatelessWidget {
bool _active=false.obs();
String _firstLanguage = "English";
String _secondLanguage = "Turkish";
WordController controller = Get.put(WordController());
final _formKey = GlobalKey<FormState>();
#override
Widget build(BuildContext context) {
controller.getir();
return Scaffold(
drawer: _drawer,
backgroundColor: Colors.blueAccent,
appBar: _appbar,
body: _bodyScaffold,
floatingActionButton: _floattingActionButton,
);
}
SingleChildScrollView get _bodyScaffold {
return SingleChildScrollView(
child: Column(
children: [
chooseLanguage,
translateTextView,
],
),
);
}
AppBar get _appbar {
return AppBar(
backgroundColor: Colors.blueAccent,
centerTitle: true,
title: Text("TRANSLATE"),
elevation: 0.0,
);
}
get chooseLanguage => Container(
height: 55.0,
decoration: buildBoxDecoration,
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
firstChooseLanguage,
changeLanguageButton,
secondChooseLanguage,
],
),
);
get buildBoxDecoration {
return BoxDecoration(
color: Colors.white,
border: Border(
bottom: BorderSide(
width: 3.5,
color: Colors.grey,
),
),
);
}
refreshList() {
controller.getir();
}
get changeLanguageButton {
return Material(
color: Colors.white,
child: IconButton(
icon: Icon(
Icons.wifi_protected_setup_rounded,
color: Colors.indigo,
size: 30.0,
),
onPressed: () {},
),
);
}
get secondChooseLanguage {
return Expanded(
child: Material(
color: Colors.white,
child: InkWell(
onTap: () {},
child: Center(
child: Text(
this._secondLanguage,
style: TextStyle(
color: Colors.blue[600],
fontSize: 22.0,
),
),
),
),
),
);
}
get firstChooseLanguage {
return Expanded(
child: Material(
color: Colors.white,
child: InkWell(
onTap: () {},
child: Center(
child: Text(
this._firstLanguage,
style: TextStyle(
color: Colors.blue[600],
fontSize: 22.0,
),
),
),
),
),
);
}
get translateTextView => Column(
children: [
Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(8.0)),
),
margin: EdgeInsets.only(left: 2.0, right: 2.0, top: 2.0),
child: _formTextField,
),
Container(
height: Get.height/1.6,
child: Obx(() {
return ListView.builder(
itemCount: controller.data.length,
itemBuilder: (context, index) {
return Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(5.0)),
),
margin: EdgeInsets.only(left: 2.0, right: 2.0, top: 0.8),
child: Container(
color: Colors.white30,
height: 70.0,
padding:
EdgeInsets.only(left: 8.0, top: 8.0, bottom: 8.0),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
firstText(controller.data, index),
secondText(controller.data, index),
],
),
historyIconbutton,
],
),
),
);
},
);
}),
)
],
);
get _formTextField {
return Form(
key: _formKey,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Container(
color: Colors.white30,
height: 120.0,
padding: EdgeInsets.only(left: 16.0, top: 8.0, bottom: 8.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
textFormFieldEntr,
favoriIconButton,
],
),
),
textFormField //burası kapandı
],
),
);
}
get textFormFieldEntr {
return Flexible(
child: Container(
child: TextFormField(
onTap: () {
showMaterialBanner();
},
// onChanged: (text) {
// controller.translateLanguage(text);
// },
controller: controller.controllerInput1,
maxLines: 6,
validator: (controllerInput1) {
if (controllerInput1!.isEmpty) {
return "lütfen bir değer giriniz";
} else if (controllerInput1.length > 22) {
return "en fazla 22 karakter girebilirsiniz";
}
return null;
},
decoration: InputDecoration(
hintText: "Enter",
contentPadding: const EdgeInsets.symmetric(vertical: 5.0),
),
),
),
);
}
void showMaterialBanner() {
ScaffoldMessenger.of(Get.context!).showMaterialBanner(MaterialBanner(
backgroundColor: Colors.red,
content: Padding(
padding: const EdgeInsets.only(top: 30.0),
child: Column(
children: [
TextFormField(
controller: controller.controllerInput1,
maxLines: 6,
onChanged: (text) {
controller.translateLanguage(text);
controller.showText();
},
validator: (controllerInput2) {
if (controllerInput2!.length > 22) {
return "en fazla 22 karakter girebilirsiniz";
}
return null;
},
decoration: InputDecoration(
suffixIcon: IconButton(onPressed: () {
FocusScope.of(Get.context!).unfocus();
closeBanner();
}, icon: Icon(Icons.clear),),
contentPadding: const EdgeInsets.symmetric(vertical: 5.0),
),
),
SizedBox(height: 80.0),
TextFormField(
controller: controller.controllerInput2,
maxLines: 6,
validator: (controllerInput2) {
if (controllerInput2!.length > 22) {
return "en fazla 22 karakter girebilirsiniz";
}
return null;
},
decoration: InputDecoration(
contentPadding: const EdgeInsets.symmetric(vertical: 5.0),
),
),
],
),
),
actions: [
IconButton(
onPressed: () {
closeBanner();
},
icon: Icon(
Icons.arrow_forward_outlined,
color: Colors.indigo,
size: 36,
),
),
]));
}
void closeBanner() {
ScaffoldMessenger.of(Get.context!).hideCurrentMaterialBanner();
}
// } controller.controllerInput1.text==""?_active=false: _active=true;
get textFormField {
return Visibility(
visible: controller.active,
child: Container(
color: Colors.white30,
height: 120.0,
padding: EdgeInsets.only(left: 16.0, right: 42.0, top: 8.0, bottom: 8.0),
child: Container(
child: TextFormField(
controller: controller.controllerInput2,
maxLines: 6,
validator: (controllerInput2) {
if (controllerInput2!.length > 22) {
return "en fazla 22 karakter girebilirsiniz";
}
return null;
},
decoration: InputDecoration(
contentPadding: const EdgeInsets.symmetric(vertical: 5.0),
),
),
),
),
);
}
FutureBuilder<dynamic> get historyWordList {
return FutureBuilder(
future: controller.getir(),
builder: (context, AsyncSnapshot snapShot) {
if (snapShot.hasData) {
var wordList = snapShot.data;
return ListView.builder(
itemCount: wordList.length,
itemBuilder: (context, index) {
return Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(5.0)),
),
margin: EdgeInsets.only(left: 8.0, right: 8.0, top: 0.8),
child: Container(
color: Colors.white30,
height: 70.0,
padding: EdgeInsets.only(left: 8.0, top: 8.0, bottom: 8.0),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
firstText(wordList, index),
secondText(wordList, index),
],
),
historyIconbutton,
],
),
),
);
},
);
} else {
return Center();
}
},
);
}
IconButton get historyIconbutton {
return IconButton(
onPressed: () {},
icon: Icon(Icons.history),
iconSize: 30.0,
);
}
Text firstText(wordList, int index) {
return Text(
"İngilizce: ${wordList[index].wordEn ?? ""}",
style: TextStyle(
fontWeight: FontWeight.w600,
),
maxLines: 1,
overflow: TextOverflow.ellipsis,
);
}
Text secondText(wordList, int index) {
return Text(
"Türkçe: ${wordList[index].wordTr ?? ""}",
style: TextStyle(
fontWeight: FontWeight.w400,
),
maxLines: 1,
overflow: TextOverflow.ellipsis,
);
}
get favoriIconButton {
return IconButton(
alignment: Alignment.topRight,
onPressed: () async {
bool validatorKontrol = _formKey.currentState!.validate();
if (validatorKontrol) {
String val1 = controller.controllerInput1.text;
String val2 = controller.controllerInput2.text;
print("$val1 $val2");
await controller.addNote();
await refreshList();
}
await Obx(() => textFormField(
controller: controller.controllerInput2,
));
await Obx(() => textFormField(
controller: controller.controllerInput1,
));
},
icon: Icon(
Icons.forward,
color: Colors.blueGrey,
size: 36.0,
),
);
}
FloatingActionButton get _floattingActionButton {
return FloatingActionButton(
onPressed: () {
Get.to(WordListPage());
},
child: Icon(
Icons.app_registration,
size: 30,
),
);
}
Drawer get _drawer {
return Drawer(
child: ListView(
// Important: Remove any padding from the ListView.
padding: EdgeInsets.zero,
children: <Widget>[
userAccountsDrawerHeader,
drawerFavorilerim,
drawersettings,
drawerContacts,
],
),
);
}
ListTile get drawerContacts {
return ListTile(
leading: Icon(Icons.contacts),
title: Text("Contact Us"),
onTap: () {
Get.back();
},
);
}
ListTile get drawersettings {
return ListTile(
leading: Icon(Icons.settings),
title: Text("Settings"),
onTap: () {
Get.back();
},
);
}
ListTile get drawerFavorilerim {
return ListTile(
leading: Icon(
Icons.star,
color: Colors.yellow,
),
title: Text("Favorilerim"),
onTap: () {
Get.to(FavoriListPage());
},
);
}
UserAccountsDrawerHeader get userAccountsDrawerHeader {
return UserAccountsDrawerHeader(
accountName: Text("UserName"),
accountEmail: Text("E-mail"),
currentAccountPicture: CircleAvatar(
backgroundColor: Colors.grey,
child: Text(
"",
style: TextStyle(fontSize: 40.0),
),
),
);
}
}
You can simple do it like this
class ControllerSample extends GetxController{
final active = false.obs
functionPass(){
active(!active.value);
}
}
on page
final sampleController = Get.put(ControllerSample());
Obx(
()=> Form(
key: yourkeyState,
child: Column(
children: [
TextFormField(
//some other needed
//put the function on onChanged
onChanged:(value){
if(value.isEmpty){
sampleController.functionPass();
}else{
sampleController.functionPass();
}
}
),
Visibility(
visible: sampleController.active.value,
child: TextFormField(
//some other info
)
),
]
)
)
)

How to Increment and Decrements single item in a List View in Flutter?

In my products Screen I have two buttons + and - for quantity,
these two buttons in my ListView it Increment/Decrement the whole list , I want to increment or decrement quantity upon button click for single list item. If I increase or decrease the counter it increment in every list item.
StreamController _event =StreamController<int>.broadcast();
int _counter = 0;
void initState() {
super.initState();
_event.add(0);
}
#override
Widget build(BuildContext context) {
.
.
return Scaffold(
body: allItemsFlowlist(),
);
}
Widget allItemsFlowlist(){
return Container(
child: ListView.builder(
itemCount: items.documents.length,
physics: AlwaysScrollableScrollPhysics(parent: BouncingScrollPhysics()),
itemBuilder: (context, i) {
return Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Flexible(
flex: 3,
child: Row(
children: <Widget>[
Flexible(
flex: 4,
child: Container(
child: Row(
children: <Widget>[
Container(
width: 35,
height: 35,
decoration: BoxDecoration(
color: colorPallet('vprice_sectionIncrementerBackground'),
borderRadius: BorderRadius.circular(5),
),
child: IconButton(
icon: Icon(Icons.remove),
onPressed: _decrementCounter,
iconSize: 18,
color: colorPallet('vprice_sectionDecrementerBackground')
),
),
Padding(
padding: EdgeInsets.symmetric(horizontal: 16.0),
child: Container(
width: 35,
height: 35,
decoration: BoxDecoration(
border: Border.all(
color: colorPallet('vprice_sectionIncrementerBackground'), //Color(0xFFFFD500),
width: 2,
),
borderRadius: BorderRadius.circular(5),
),
child: Center(
child: StreamBuilder<int>(
stream: _event.stream,
builder: (context, snapshot) {
return Text(
_counter.toString(),
style: TextStyle(
color: colorPallet('vprice_sectionTextTextStyle4'),
fontSize: 16,
fontWeight: FontWeight.w500,
),
);
}),
),
),
),
Container(
width: 35,
height: 35,
decoration: BoxDecoration(
color: colorPallet('vprice_sectionIncrementerBackground'),
borderRadius: BorderRadius.circular(5),
),
child: IconButton(
icon: Icon(Icons.add),
onPressed: _incrementCounter,
iconSize: 18,
color: colorPallet('vprice_sectionDecrementerBackground'),
),
),
],
)),
),
Incrementer:
_incrementCounter() {
_counter++;
_event.add(_counter);
}
Decrementer:
_decrementCounter() {
if (_counter <= 0) {
_counter = 0;
} else {
_counter--;
}
_event.add(_counter);
}
Turn _counter into a list and add an item for each item in your listView.builder to it.
And when changing, change _counter [i];
And so will change that specific item!
List<int> _counter = List();
ListView.builder(
itemCount: items.documents.length,
physics: AlwaysScrollableScrollPhysics(parent: BouncingScrollPhysics()),
itemBuilder: (context, i) {
if(_counter.length < items.documents.length){
_counter.add(0);
}
return Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Flexible(
[...]
child: IconButton(
icon: Icon(Icons.remove),
onPressed: (){_decrementCounter(i);},
iconSize: 18,
color: colorPallet('vprice_sectionDecrementerBackground')
),
),
[...]
child: IconButton(
icon: Icon(Icons.add),
onPressed: (){_incrementCounter(i);},
iconSize: 18,
color: colorPallet('vprice_sectionDecrementerBackground'),
),
),
],
)),
),
[...]
_incrementCounter(int i) {
_counter[i]++;
_event.add(_counter[i]);
}
_decrementCounter(int i) {
if (_counter[i] <= 0) {
_counter[i] = 0;
} else {
_counter[i]--;
}
_event.add(_counter[i]);
}
Hope this helps!