ListView give so many junks on page change in Flutter - flutter

I'm a guy from android development and I'm in love with flutter. But I have experienced some issues with ListView, with this kind of problem is like the Main Thread is doing a lot of jobs and I resolve this using AsyncTask on android but in Flutter, this is giving to me in official documents.
Since Flutter is single threaded and runs an event loop (like
Node.js), you don’t have to worry about thread management or spawning
background threads. If you’re doing I/O-bound work, such as disk
access or a network call, then you can safely use async/await and
you’re all set. If, on the other hand, you need to do computationally
intensive work that keeps the CPU busy, you want to move it to an
Isolate to avoid blocking the event loop, like you would keep any sort
of work out of the main thread in Android.
In my home it is a stateful widget and here is the code :
return new WillPopScope(
onWillPop: () async => false,
child: Scaffold(
backgroundColor: Colors.white,
appBar: AppBar(
automaticallyImplyLeading: false,
centerTitle: true,
backgroundColor: ThemeColor.AppPrimaryColor, // status bar color
brightness: Brightness.dark, // status bar brightness
elevation: 5,
title: AppBarContent(),
),
drawer: MenuBar(),
body: Container(
child: SingleChildScrollView(
controller: _scrollController,
child: Column(
children: <Widget>[
Column(
children: <Widget>[
Container(
child: CategorySlider(),
),
SizedBox(
height: screenHeight * 0.02,
),
Container(
child: BannerSlider(),
),
SizedBox(
height: screenHeight * 0.03,
),
Container(
child: Container(
margin: EdgeInsets.only(left: 20.0),
child: Row(
mainAxisSize: MainAxisSize.max,
children: <Widget>[
Text(
'Vitrines em destaque',
style: CustomFontStyle.titleList(),
),
],
),
),
),
Padding(
padding: const EdgeInsets.all(9.0),
child: CompanyList(true),
),
],
),
],
),
),
),
),
);
In bottom I have this line that calls a widget CompanyList:
Padding(
padding: const EdgeInsets.all(9.0),
child: CompanyList(true),
),
And this is my CompanyList class
class CompanyList extends StatefulWidget {
final filtered;
final isShrink;
final MasterCategoryModel masterCategoryModel;
CompanyList(
[this.isShrink = false, this.masterCategoryModel, this.filtered = false]);
// const CompanyList({Key key}) : super(key: key);
#override
State<StatefulWidget> createState() => new CompanyListState();
}
class CompanyListState extends State<CompanyList> {
CompanyController companyController = new CompanyController();
CompanyService companyService;
Map<String, dynamic> companyList = {};
bool loadingData = true;
bool loadData = true;
bool loadMoreData = false;
int pageCounter = 1;
#override
void initState() {
super.initState();
companyService = Provider.of<CompanyService>(context, listen: false);
companyService.loadMoreData$.listen((value) {
if (value) {
if (loadData) {
loadData = false;
getMoreData();
}
}
});
widget.filtered
? getCompanyByMsCateg(widget.masterCategoryModel)
: getRandomActiveCompanys();
}
#override
void dispose() {
super.dispose();
}
getRandomActiveCompanys() {
setState(() {
loadingData = true;
});
companyController.getRandomActiveCompanys(pageCounter).then((value) {
setState(() {
pageCounter++;
companyList = value;
loadingData = false;
});
}).catchError((error) {
print(error);
setState(() {
loadingData = false;
});
});
}
getMoreData() {
setState(() {
loadMoreData = true;
});
companyController.getRandomActiveCompanys(pageCounter).then((value) {
setState(() {
pageCounter++;
companyList['data'] = companyList['data']..addAll(value['data']);
loadMoreData = false;
});
}).catchError((error) {
print(error);
setState(() {
loadMoreData = false;
});
});
}
getCompanyByMsCateg(MasterCategoryModel masterCategoryModel) {
setState(() {
loadingData = true;
});
companyController
.getCompanysByMsgCateg(masterCategoryModel.master_category_id)
.then((value) {
setState(() {
companyList.addAll(value);
loadingData = false;
});
}).catchError((error) {
print(error);
setState(() {
loadingData = false;
});
});
}
getMoreCompanyData() {
setState(() {
// companyList.add(totalCompanyList[i]);
});
Future.delayed(const Duration(milliseconds: 3000), () {
loadData = true;
});
}
getCompanyData(company) {
Navigator.push(
context,
PageTransition(
type: PageTransitionType.rightToLeft,
child: CompanyScreen(
company: company,
),
),
);
}
#override
Widget build(BuildContext context) {
final double screenHeight = MediaQuery.of(context).size.height;
final double screenWidth = MediaQuery.of(context).size.width;
return !loadingData
? ListView.builder(
addAutomaticKeepAlives: true,
shrinkWrap: widget.isShrink ? true : false,
physics: ClampingScrollPhysics(),
padding: const EdgeInsets.all(8),
itemCount: companyList['data'].length,
itemBuilder: (BuildContext context, int index) {
return GestureDetector(
onTap: () => getCompanyData(companyList['data'][index]),
child: Container(
child: Column(
children: <Widget>[
Row(
mainAxisSize: MainAxisSize.max,
children: <Widget>[
Flexible(
flex: 2,
child: Container(
height: screenHeight * 0.12,
decoration: new BoxDecoration(
border: Border.all(
color: ThemeColor.AppBorderGrey,
),
borderRadius: new BorderRadius.only(
topLeft: const Radius.circular(5.0),
bottomLeft: const Radius.circular(5.0),
),
),
child: Center(
child:
companyList['data'][index]['image'] != null
? Container(
height: 45,
width: 45,
child: ClipRRect(
borderRadius: BorderRadius.all(
Radius.circular(20.0)),
child: Image.network(
'${MainConfig.storageDoc + companyList['data'][index]['image']}',
width: 42,
height: 42,
cacheWidth: 42,
cacheHeight: 42,
fit: BoxFit.cover,
),
),
)
: new Container(
width: screenWidth * 0.13,
height: screenWidth * 0.13,
decoration: new BoxDecoration(
shape: BoxShape.circle,
image: new DecorationImage(
fit: BoxFit.fill,
image: AssetImage(
'assets/icons/error/no_image_v2.png'),
),
),
),
),
),
),
Flexible(
flex: 3,
child: Container(
height: screenHeight * 0.12,
decoration: new BoxDecoration(
border: Border.all(
color: ThemeColor.AppBorderGrey,
),
borderRadius: new BorderRadius.only(
topRight: const Radius.circular(5.0),
bottomRight: const Radius.circular(5.0),
),
),
child: Center(
child: Text(
'${companyList['data'][index]['storename']}',
),
),
),
),
],
),
SizedBox(
height: 10.0,
),
],
),
),
);
})
: Center(
child: Column(
children: <Widget>[
SizedBox(
height: 10.0,
),
Center(
child: SpinKitThreeBounce(
color: ThemeColor.AppPrimaryColor,
size: 30.0,
),
),
],
),
);
}
}
If I change page and go back, my application always junk and close so I make some research and find that problem was a problem with CacheImages so in GitHub I find a solution for put a fixed cacheWidth and cacheHeight and this make my app don't crash but have junk. So I'm thinking of isolating the function that load this widget. What I must do?
child: Image.network(
'${MainConfig.storageDoc + companyList['data'][index]['image']}',
width: 42,
height: 42,
cacheWidth: 42,
cacheHeight: 42,
fit: BoxFit.cover,
),

Related

Flutter ListView builder not updating with fresh data

I'm running a search filter function which retrieves players from a Floor DB. The functionality works fine and I can see through logs that the new player are returned, however my UI won't update which seems to be from the new list i assign not triggering a re-render.
Can anyone see what's wrong with my code?
import 'package:flutter/material.dart';
import '../database/LocalDatabase.dart';
import '../model/Player.dart';
class Pitch extends StatefulWidget {
const Pitch({super.key});
#override
_Pitch createState() => _Pitch();
}
class _Pitch extends State<Pitch> {
List<Player> playersList = <Player>[];
Offset positionOne = const Offset(100, 100);
Offset positionTwo = const Offset(200, 100);
#override
Widget build(BuildContext context) {
return Container(
constraints: BoxConstraints.expand(),
color: Colors.white,
child: Stack(
alignment: Alignment.center,
children: [
Image.asset("assets/images/pitch.png"),
Positioned(
left: positionOne.dx,
top: positionOne.dy,
child: Draggable(
feedback: playerImage(
"https://cdn.sofifa.net/players/158/023/22_120.png"),
childWhenDragging: Opacity(
opacity: 0,
child: playerImage(
"https://cdn.sofifa.net/players/158/023/22_120.png"),
),
child: playerImage(
"https://cdn.sofifa.net/players/158/023/22_120.png"),
onDragEnd: (details) {
setState(() {
positionOne = details.offset;
});
},
),
),
Positioned(
left: positionTwo.dx,
top: positionTwo.dy,
child: Draggable(
feedback: playerImage(
"https://cdn.sofifa.com/players/notfound_0_120.png"),
childWhenDragging: Opacity(
opacity: 0,
child: playerImage(
"https://cdn.sofifa.com/players/notfound_0_120.png"),
),
child: playerImage(
"https://cdn.sofifa.com/players/notfound_0_120.png"),
onDragEnd: (details) {
setState(() {
positionTwo = details.offset;
});
},
),
)
],
),
);
}
#override
void initState() {
super.initState();
// getPlayers().then((value) {
// debugPrint("playerfromdb: ${value[0].name}");
// });
}
Future<List<Player>> getPlayers() async {
final database =
await $FloorLocalDatabase.databaseBuilder('local_database.db').build();
final playerDao = database.playerDao;
final players = playerDao.getAllPlayers();
return players;
}
Widget playerImage(String imageUrl) {
return GestureDetector(
onTap: () => showDialog<void>(
context: context,
builder: (BuildContext context) => Dialog(
backgroundColor: Colors.white,
child: SizedBox(
height: 300,
width: 300,
child: Column(
children: [
const SizedBox(height: 24),
Container(
margin: const EdgeInsets.only(left: 16),
height: 48,
child: TextField(
decoration: const InputDecoration.collapsed(
hintText: 'Enter player name',
focusColor: Colors.transparent),
onChanged: (value) {
searchPlayers(value);
},
)),
const SizedBox(height: 24),
SizedBox(
height: 200,
child: ListView.builder(
itemCount: playersList.length,
itemBuilder: (context, index) {
return playerItem(playersList.elementAt(index));
}),
),
],
)))),
child: SizedBox(
width: 48,
height: 48,
child: Image.network(imageUrl),
));
}
Widget playerItem(Player? player) {
return Container(
height: 48,
margin: const EdgeInsets.all(8),
padding: const EdgeInsets.only(left: 8, right: 8),
decoration: BoxDecoration(
shape: BoxShape.rectangle,
color: Colors.white,
borderRadius: BorderRadius.circular(16),
boxShadow: const [BoxShadow(blurRadius: 8)]),
child: Row(
children: [
SizedBox(
height: 36,
width: 36,
child: Image.network(player?.playerImageUrl ?? "")),
const SizedBox(width: 8),
Text(player?.name ?? "")
],
),
);
}
Future<void> searchPlayers(String query) async {
final database = await $FloorLocalDatabase
.databaseBuilder('local_database.db')
.build();
final playerDao = database.playerDao;
// await List<Player> filteredPlayers =
playerDao.searchPlayers(query).then((value) {
setState(() => playersList = value);
debugPrint(value[0].name);
});
}
}
Because your put ListView.builder in Dialog it will create a new stack and a new stack can't rerender from another stack
You can change your code with create a new stateful widget for dialogs
import 'package:flutter/material.dart';
import '../database/LocalDatabase.dart';
import '../model/Player.dart';
class Pitch extends StatefulWidget {
const Pitch({super.key});
#override
_Pitch createState() => _Pitch();
}
class _Pitch extends State<Pitch> {
Offset positionOne = const Offset(100, 100);
Offset positionTwo = const Offset(200, 100);
#override
Widget build(BuildContext context) {
return Container(
constraints: BoxConstraints.expand(),
color: Colors.white,
child: Stack(
alignment: Alignment.center,
children: [
Image.asset("assets/images/pitch.png"),
Positioned(
left: positionOne.dx,
top: positionOne.dy,
child: Draggable(
feedback: playerImage(
"https://cdn.sofifa.net/players/158/023/22_120.png"),
childWhenDragging: Opacity(
opacity: 0,
child: playerImage(
"https://cdn.sofifa.net/players/158/023/22_120.png"),
),
child: playerImage(
"https://cdn.sofifa.net/players/158/023/22_120.png"),
onDragEnd: (details) {
setState(() {
positionOne = details.offset;
});
},
),
),
Positioned(
left: positionTwo.dx,
top: positionTwo.dy,
child: Draggable(
feedback: playerImage(
"https://cdn.sofifa.com/players/notfound_0_120.png"),
childWhenDragging: Opacity(
opacity: 0,
child: playerImage(
"https://cdn.sofifa.com/players/notfound_0_120.png"),
),
child: playerImage(
"https://cdn.sofifa.com/players/notfound_0_120.png"),
onDragEnd: (details) {
setState(() {
positionTwo = details.offset;
});
},
),
)
],
),
);
}
Widget playerImage(String imageUrl) {
return GestureDetector(
onTap: () => showDialog<void>(
context: context,
builder: (BuildContext context) => Dialog(
backgroundColor: Colors.white,
child: const PlayersDialog(),
),
),
child: SizedBox(
width: 48,
height: 48,
child: Image.network(imageUrl),
),
);
}
}
class PlayersDialog extends StatefulWidget {
const PlayersDialog({super.key});
#override
_PlayersDialog createState() => _PlayersDialog();
}
class _PlayersDialog extends State<PlayersDialog> {
List<Player> playersList = <Player>[];
Future<void> searchPlayers(String query) async {
final database =
await $FloorLocalDatabase.databaseBuilder('local_database.db').build();
final playerDao = database.playerDao;
// await List<Player> filteredPlayers =
playerDao.searchPlayers(query).then((value) {
setState(() => playersList = value);
debugPrint(value[0].name);
});
}
#override
Widget build(BuildContext context) {
return SizedBox(
height: 300,
width: 300,
child: Column(
children: [
const SizedBox(height: 24),
Container(
margin: const EdgeInsets.only(left: 16),
height: 48,
child: TextField(
decoration: const InputDecoration.collapsed(
hintText: 'Enter player name',
focusColor: Colors.transparent),
onChanged: (value) {
searchPlayers(value);
},
)),
const SizedBox(height: 24),
SizedBox(
height: 200,
child: ListView.builder(
itemCount: playersList.length,
itemBuilder: (context, index) {
return playerItem(playersList.elementAt(index));
},
),
),
],
),
);
}
Widget playerItem(Player? player) {
return Container(
height: 48,
margin: const EdgeInsets.all(8),
padding: const EdgeInsets.only(left: 8, right: 8),
decoration: BoxDecoration(
shape: BoxShape.rectangle,
color: Colors.white,
borderRadius: BorderRadius.circular(16),
boxShadow: const [BoxShadow(blurRadius: 8)]),
child: Row(
children: [
SizedBox(
height: 36,
width: 36,
child: Image.network(player?.playerImageUrl ?? "")),
const SizedBox(width: 8),
Text(player?.name ?? "")
],
),
);
}
#override
void initState() {
super.initState();
// getPlayers().then((value) {
// debugPrint("playerfromdb: ${value[0].name}");
// });
}
Future<List<Player>> getPlayers() async {
final database =
await $FloorLocalDatabase.databaseBuilder('local_database.db').build();
final playerDao = database.playerDao;
final players = playerDao.getAllPlayers();
return players;
}
}

Screen does not update even though build function is running flutter

So I have created a chat app which draws from a pusher client. Whenever there is a new message, the build function does rebuild, and I believe the widget list does change, but there is no update on the screen. How do I fix this ?
Widget build(BuildContext context) {
// print(messageWidgetList.length);
return Scaffold(
backgroundColor: AppColors.lightGrey,
appBar: AppBar(
backgroundColor: Colors.transparent,
title: Text(
messageTo,
style: TextStyle(
color: AppColors.white,
fontSize: 22,
),
),
),
body: Stack(
children: [
Padding(
padding:
const EdgeInsets.only(top: 12, left: 12, right: 12, bottom: 70),
child: ValueListenableBuilder<List<Widget>>(
valueListenable: messageWidgetList,
builder: (context, value, widget) {
print("Updated");
print(value.length);
// print(widget);
return ListView.builder(
// controller: scrollController,
physics: AlwaysScrollableScrollPhysics(),
reverse: true,
addAutomaticKeepAlives: true,
itemCount: value.length,
itemBuilder: (ctx, index) {
// print(index);
return value[index];
},
);
},
),
),
Align(
alignment: Alignment.bottomCenter,
child: Column(
mainAxisAlignment: MainAxisAlignment.end,
children: [
if (xFilesImages.isNotEmpty)
SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
children: xFilesImages.map<Widget>((element) {
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 10.0),
child: SizedBox(
height: 100,
width: 80,
child: Image.file(
File(element.path),
frameBuilder:
(ctx, child, frame, wasSynchronouslyLoaded) {
return SizedBox(
width: MediaQuery.of(ctx).size.width,
height: MediaQuery.of(ctx).size.height,
child: Stack(
children: [
Align(
alignment: Alignment.topRight,
child: Container(
height: 25,
width: 25,
decoration: BoxDecoration(
shape: BoxShape.circle,
color: AppColors.lightestGrey,
),
child: FittedBox(
child: GestureDetector(
onTap: () {
xFilesImages.remove(element);
setState(() {});
},
child:
const Icon(Icons.cancel)),
),
),
),
child
],
),
);
},
),
),
);
}).toList(),
),
),
const SizedBox(height: 5),
Container(
height: 60,
width: MediaQuery.of(context).size.width,
child: Padding(
padding:
const EdgeInsets.only(left: 10, bottom: 10, right: 10),
child: Container(
// height: 30,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10),
color: AppColors.darkGrey,
),
child: TextFormField(
// expands: true,
style: TextStyle(color: AppColors.white),
focusNode: messageFocusNode,
controller: messageController,
decoration: InputDecoration(
contentPadding: const EdgeInsets.only(
right: 8, left: 8, top: 14),
prefixIcon: InkWell(
onTap: () async {
if (!(await Permission.camera.isGranted)) {
await Permission.camera.request();
await Permission.photos.request();
}
ImagePicker _picker = ImagePicker();
xFilesImages =
await _picker.pickMultiImage() ?? [];
print("Got xFiles");
print(xFilesImages.length);
for (XFile xFile in xFilesImages) {
print(xFile.name);
print(xFile.path);
}
setState(() {});
},
child: Icon(
Icons.attachment,
size: 34,
color: AppColors.lightestGrey,
),
),
suffixIcon: GestureDetector(
onTap: () async {
//TODO: When you wake up, you have implemented picking images. Work on displaying picked images and then sending them
// loading = true;
// messageController.text = '';
if (messageController.text.isNotEmpty ||
xFilesImages.isNotEmpty) {
messageFocusNode.unfocus();
// messageWidgetList.add(sentMessage(
// {"message": messageController.text}));
setState(() {});
print("Sent button clicked");
ApiProvider.sendMessage(
widget.userModel.bearerToken,
widget.senderPhone.phoneNumbers.first,
messageTo,
messageController.text,
xFilesImages);
// loading = false;
messageController.text = '';
xFilesImages = [];
setState(() {});
}
},
child: const Icon(
Icons.send,
size: 30,
color: const Color(0xFF004b77),
),
),
fillColor: AppColors.lightGrey,
hintText: "Enter message...",
hintStyle:
TextStyle(color: AppColors.lightestGrey)),
),
),
),
),
],
),
),
if (loading)
Container(
height: double.infinity,
width: double.infinity,
color: AppColors.lightGrey.withOpacity(0.3),
child: Center(
child: SpinKitChasingDots(
color: AppColors.blue,
)),
)
],
),
);
}
Bad, does not work
static final List<Widget> items= [];
Widget build(BuildContext context) {
return ListView(children: items); // <-- look here
}
Good, does update properly
static final List<Widget> items= [];
Widget build(BuildContext context) {
return ListView(children: [...items]); // <-- look here
}
Grandious with the little extra mile
static final List<Widget> items= [];
Widget build(BuildContext context) {
return ListView(children: <Widget>[...items]); // <-- look here
}
setState needs a brand new object to update properly. It does not look into a List like here if something changed in there.

How to hide FloatingActionButton under keyboard and not textformfield in flutter?

So I am trying to hide FloatingActionButton using resizeToAvoidBottomInsert: false, but it also hiding textformfield. Is there any way to just hide FloatingActionButton alone and not textformfield and textformfield should appear when the keyboard appears. If you have time please share some kt how to focus textformfield because every time it only focusing first textfield. Below I attaching the Screenshots and full code.
import 'package:flutter/material.dart';
void main() {
runApp(App());
}
class App extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: CardWithTextformfield(),
);
}
}
class CardWithTextformfield extends StatefulWidget {
const CardWithTextformfield({Key? key}) : super(key: key);
#override
_CardWithTextformfieldState createState() => _CardWithTextformfieldState();
}
class _CardWithTextformfieldState extends State<CardWithTextformfield> {
var name =<TextEditingController>[];
var id =<TextEditingController>[];
var addCard =1;
bool cardOneVisibility=true;
bool cardTwoVisibility=false;
bool cardThreeVisibility=false;
bool cardFourVisibility=false;
bool cardFiveVisibility=false;
bool cardSixVisibility=false;
void incrementcard(){
setState(() {
if(addCard==0){
cardOneVisibility=true;
}
else if(addCard==1){
cardOneVisibility=true;
cardTwoVisibility=true;
}
else if(addCard==2){
cardOneVisibility=true;
cardTwoVisibility=true;
cardThreeVisibility=true;
}
else if(addCard==3){
cardOneVisibility=true;
cardTwoVisibility=true;
cardThreeVisibility=true;
cardFourVisibility=true;
}
else if(addCard==4){
cardOneVisibility=true;
cardTwoVisibility=true;
cardThreeVisibility=true;
cardFourVisibility=true;
cardFiveVisibility=true;
}
else if(addCard==5){
cardOneVisibility=true;
cardTwoVisibility=true;
cardThreeVisibility=true;
cardFourVisibility=true;
cardFiveVisibility=true;
cardSixVisibility=true;
}
addCard++;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
resizeToAvoidBottomInset: false,
appBar: AppBar(
title: Text('Card with TextformField'),
),
floatingActionButton: FloatingActionButton(
onPressed: addCard>=6 ? null : incrementcard,
child: Icon(Icons.add),
),
body: Container(
child:SingleChildScrollView(
child: Column(
children: [
Visibility(visible: cardOneVisibility,child: cardslist(0)),
Visibility(visible: cardTwoVisibility,child: cardslist(1)),
Visibility(visible: cardThreeVisibility,child: cardslist(2)),
Visibility(visible: cardFourVisibility,child: cardslist(3)),
Visibility(visible: cardFiveVisibility,child: cardslist(4)),
Visibility(visible: cardSixVisibility,child: cardslist(5)),
],
),
),
),
);
}
Widget cardslist(int index){
if(name.length <= index){
name.add(TextEditingController());
id.add(TextEditingController());
}
return Card(
margin: EdgeInsets.all(10),
child: Container(
child: Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Container(
margin: EdgeInsets.all(10),
child: Text('Team Name: ')),
Expanded(child: TextFormField(
controller: name[index],
decoration: InputDecoration(hintText: 'Team Name'),
),),
Container(
margin: EdgeInsets.all(10),
child: Text('Team Id: '),),
Expanded(child: TextFormField(
controller: id[index],
decoration: InputDecoration(hintText: 'Team Id'),
),),
],
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
GestureDetector(
child: Container(
width: 50,height: 50,
margin: EdgeInsets.all(10),
decoration: BoxDecoration(
shape: BoxShape.rectangle,
color:Colors.grey,
),
child: Center(child: Text('IT'),),
),
),
GestureDetector(
child: Container(
width: 50,height: 50,
margin: EdgeInsets.all(10),
decoration: BoxDecoration(
shape: BoxShape.rectangle,
color: Colors.grey,
),
child: Center(child: Text('DEV'),),
),
),
GestureDetector(
child: Container(
width: 50,height: 50,
margin: EdgeInsets.all(10),
decoration: BoxDecoration(
shape: BoxShape.rectangle,
color: Colors.grey,
),
child: Center(child: Text('TEST'),),
),
),
GestureDetector(
child: Container(
width: 50,height: 50,
margin: EdgeInsets.all(10),
decoration: BoxDecoration(
shape: BoxShape.rectangle,
color: Colors.grey,
),
child: Center(child: Text('HR'),),
),
),
],
)
],
),
),
);
}
}
please check. remove resizeToAvoidBottomInsert: false, and controll floating button based on addCard size.
import 'package:flutter/material.dart';
void main() {
runApp(App());
}
class App extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: CardWithTextformfield(),
);
}
}
class CardWithTextformfield extends StatefulWidget {
const CardWithTextformfield({Key key}) : super(key: key);
#override
_CardWithTextformfieldState createState() => _CardWithTextformfieldState();
}
class _CardWithTextformfieldState extends State<CardWithTextformfield> {
List<TextEditingController> name = <TextEditingController>[];
List<TextEditingController> id = <TextEditingController>[];
var addCard = 1;
bool cardOneVisibility = true;
bool cardTwoVisibility = false;
bool cardThreeVisibility = false;
bool cardFourVisibility = false;
bool cardFiveVisibility = false;
bool cardSixVisibility = false;
bool showFab = false;
void incrementcard() {
setState(() {
if (addCard == 0) {
cardOneVisibility = true;
} else if (addCard == 1) {
cardOneVisibility = true;
cardTwoVisibility = true;
} else if (addCard == 2) {
cardOneVisibility = true;
cardTwoVisibility = true;
cardThreeVisibility = true;
} else if (addCard == 3) {
cardOneVisibility = true;
cardTwoVisibility = true;
cardThreeVisibility = true;
cardFourVisibility = true;
} else if (addCard == 4) {
cardOneVisibility = true;
cardTwoVisibility = true;
cardThreeVisibility = true;
cardFourVisibility = true;
cardFiveVisibility = true;
} else if (addCard == 5) {
cardOneVisibility = true;
cardTwoVisibility = true;
cardThreeVisibility = true;
cardFourVisibility = true;
cardFiveVisibility = true;
cardSixVisibility = true;
}
addCard++;
});
}
#override
Widget build(BuildContext context) {
final bool keyboardIsOpen = MediaQuery.of(context).viewInsets.bottom != 0;
return Scaffold(
resizeToAvoidBottomInset: true,
appBar: AppBar(
title: const Text('Card with TextformField'),
),
floatingActionButton: Visibility(
visible: !keyboardIsOpen,
child: FloatingActionButton(
onPressed: addCard >= 6 ? null : incrementcard,
child: const Icon(Icons.add),
),
),
body: ListView(
shrinkWrap: true,
physics: const ScrollPhysics(),
children: [
Visibility(visible: cardOneVisibility, child: cardslist(0)),
Visibility(visible: cardTwoVisibility, child: cardslist(1)),
Visibility(visible: cardThreeVisibility, child: cardslist(2)),
Visibility(visible: cardFourVisibility, child: cardslist(3)),
Visibility(visible: cardFiveVisibility, child: cardslist(4)),
Visibility(visible: cardSixVisibility, child: cardslist(5)),
],
),
);
}
Widget cardslist(int index) {
if (name.length <= index) {
name.add(TextEditingController(text: ""));
id.add(TextEditingController(text: ""));
}
return Card(
margin: EdgeInsets.all(10),
child: Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Container(
margin: EdgeInsets.all(10), child: Text('Team Name: ')),
Expanded(
child: TextFormField(
controller: name[index],
decoration: InputDecoration(hintText: 'Team Name'),
),
),
Container(
margin: EdgeInsets.all(10),
child: Text('Team Id: '),
),
Expanded(
child: TextFormField(
controller: id[index],
decoration: InputDecoration(hintText: 'Team Id'),
),
),
],
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
GestureDetector(
child: Container(
width: 50,
height: 50,
margin: EdgeInsets.all(10),
decoration: BoxDecoration(
shape: BoxShape.rectangle,
color: Colors.grey,
),
child: Center(
child: Text('IT'),
),
),
),
GestureDetector(
child: Container(
width: 50,
height: 50,
margin: EdgeInsets.all(10),
decoration: BoxDecoration(
shape: BoxShape.rectangle,
color: Colors.grey,
),
child: Center(
child: Text('DEV'),
),
),
),
GestureDetector(
child: Container(
width: 50,
height: 50,
margin: EdgeInsets.all(10),
decoration: BoxDecoration(
shape: BoxShape.rectangle,
color: Colors.grey,
),
child: Center(
child: Text('TEST'),
),
),
),
GestureDetector(
child: Container(
width: 50,
height: 50,
margin: EdgeInsets.all(10),
decoration: BoxDecoration(
shape: BoxShape.rectangle,
color: Colors.grey,
),
child: Center(
child: Text('HR'),
),
),
),
],
)
],
),
);
}
}

Is there a way of making beautiful dropdown menu in flutter?

I want to make beautiful dropdown menu like this. I already tried making it with containers, but it's taking very long time. Is there any package or a way of configuring default dropdownmenu and items?
You could use a Container() Widget with Boxdecoration and as a child the DropdownButton() Widget.
Use DropdownButtonHideUnderline() as a Parent to hide the default Underline.
Sample Code:
Container(
padding: const EdgeInsets.symmetric(horizontal: 12.0),
height: 40.0,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(30.0),
color: Colors.yellow,
),
child: DropdownButtonHideUnderline(
child: DropdownButton() // your Dropdown Widget here
),
);
try this:
import 'package:flutter/material.dart';
void main() => runApp(ExampleApp());
class ExampleApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: PopMenu(),
);
}
}
class PopMenu extends StatefulWidget {
#override
_PopMenuState createState() => _PopMenuState();
}
class _PopMenuState extends State<PopMenu> {
List<String> _menuList = ['menu 1', 'menu 2', 'menu 3'];
GlobalKey _key = LabeledGlobalKey("button_icon");
OverlayEntry _overlayEntry;
Offset _buttonPosition;
bool _isMenuOpen = false;
void _findButton() {
RenderBox renderBox = _key.currentContext.findRenderObject();
_buttonPosition = renderBox.localToGlobal(Offset.zero);
}
void _openMenu() {
_findButton();
_overlayEntry = _overlayEntryBuilder();
Overlay.of(context).insert(_overlayEntry);
_isMenuOpen = !_isMenuOpen;
}
void _closeMenu() {
_overlayEntry.remove();
_isMenuOpen = !_isMenuOpen;
}
OverlayEntry _overlayEntryBuilder() {
return OverlayEntry(
builder: (context) {
return Positioned(
top: _buttonPosition.dy + 70,
left: _buttonPosition.dx,
width: 300,
child: _popMenu(),
);
},
);
}
Widget _popMenu() {
return Material(
child: Container(
width: 300,
height: 300,
decoration: BoxDecoration(
color: Color(0xFFF67C0B9),
borderRadius: BorderRadius.circular(4),
),
child: Column(
mainAxisSize: MainAxisSize.min,
children: List.generate(
_menuList.length,
(index) {
return GestureDetector(
onTap: () {},
child: Container(
alignment: Alignment.center,
width: 300,
height: 100,
child: Text(_menuList[index]),
),
);
},
),
),
),
);
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Container(
key: _key,
width: 300,
height: 50,
decoration: BoxDecoration(
color: Color(0xFFF5C6373),
borderRadius: BorderRadius.circular(25),
),
child: Row(
children: [
Expanded(
child: Center(child: Text('menu 1')),
),
IconButton(
icon: Icon(Icons.arrow_downward),
color: Colors.white,
onPressed: () {
_isMenuOpen ? _closeMenu() : _openMenu();
},
),
],
),
),
),
);
}
}

How can I create a function that pronounces the word when it's clicked?

I have this app for kids with vocabulary and I would like to know how I can create a function that pronounces the word that is written in English. I saw that Google has a Google translator API but couldn't find information on how to use it. Do you guys have any idea on how I can achieve that?
class AnimalsScreen extends StatelessWidget {
final DocumentSnapshot animals;
AnimalsScreen(this.animals);
#override
Widget build(BuildContext context) {
return Column(
children: <Widget>[
Padding(
padding: const EdgeInsets.all(10.0),
child: Card(
elevation: 7.0,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(50)
),
child: Column(
children: <Widget>[
Container(
height: 350.0,
width: 350.0,
decoration: BoxDecoration(
image: DecorationImage(
image: NetworkImage(animals.data["image"]
),
fit: BoxFit.fill),
borderRadius: BorderRadius.only(
topLeft: Radius.circular(50),
topRight: Radius.circular(50)))
),
Container(
height: 70.0,
width: 300.0,
child: Padding(
padding: const EdgeInsets.all(2.0),
child: Center(
child: AutoSizeText(animals.data["name"],
style: TextStyle(
fontFamily: 'Twiddlestix',
fontSize: 25,
fontWeight: FontWeight.bold),
textAlign: TextAlign.center,
minFontSize: 15,
),
)
),
),
],
),
),
),
],
);
}
}
Just check out this example which i have made using your ui i have just passed the static string to it. There is a plugin named flutter_tts maybe this can work for you. Just check the example:
Link for the plugin : https://pub.dev/packages/flutter_tts
import 'package:auto_size_text/auto_size_text.dart';
import 'package:flutter/material.dart';
import 'package:flutter_tts/flutter_tts.dart';
void main() => runApp(ApiCalling());
class ApiCalling extends StatefulWidget {
#override
_ApiCallingState createState() => _ApiCallingState();
}
enum TtsState { playing, stopped }
class _ApiCallingState extends State<ApiCalling> {
bool showLoader = false;
FlutterTts flutterTts;
TtsState ttsState = TtsState.stopped;
String _newVoiceText = 'CAT';
double volume = 0.5;
double pitch = 1.0;
double rate = 0.5;
#override
void initState() {
super.initState();
flutterTts = FlutterTts();
initSpeak();
}
initSpeak() {
flutterTts.setStartHandler(() {
setState(() {
ttsState = TtsState.playing;
});
});
flutterTts.setCompletionHandler(() {
setState(() {
ttsState = TtsState.stopped;
});
print('Speaking End');
});
flutterTts.setErrorHandler((msg) {
setState(() {
ttsState = TtsState.stopped;
});
});
}
#override
void dispose() {
super.dispose();
flutterTts.stop();
}
Future _speak() async {
await flutterTts.setVolume(volume);
await flutterTts.setSpeechRate(rate);
await flutterTts.setPitch(pitch);
if (_newVoiceText != null) {
if (_newVoiceText.isNotEmpty) {
var result = await flutterTts.speak(_newVoiceText);
if (result == 1) setState(() => ttsState = TtsState.playing);
}
}
}
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Padding(
padding: const EdgeInsets.all(10.0),
child: GestureDetector(
onTap: () {
_speak();
},
child: Card(
elevation: 7.0,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(50)),
child: Column(
children: <Widget>[
Container(
height: 350.0,
width: 350.0,
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage(
'images/cat.jpg',
),
fit: BoxFit.fill),
borderRadius: BorderRadius.only(
topLeft: Radius.circular(50),
topRight: Radius.circular(50)))),
Container(
height: 70.0,
width: 300.0,
child: Padding(
padding: const EdgeInsets.all(2.0),
child: Center(
child: AutoSizeText(
'CAT',
style: TextStyle(
fontFamily: 'Twiddlestix',
fontSize: 25,
fontWeight: FontWeight.bold),
textAlign: TextAlign.center,
minFontSize: 15,
),
)),
),
],
),
),
),
),
],
),
),
),
);
}
}
Let me know if it works.
You can try this package, https://pub.dev/packages/text_to_speech_api or look for any other text to speech https://pub.dev/flutter/packages?q=text+to+speech .I didn't try any of them but looks like working.
Hope it helps!