Hello friends I am learning to build apps in Flutter. I have a FutureBuilder widget which retrieves Data from the server and displays them.
Here is the code:
FutureBuilder(
future: fetchBoxes(),
builder: (BuildContext context,
AsyncSnapshot<List<Box>> snapshot) {
switch (snapshot.connectionState) {
case ConnectionState.none:
return Text('no connection');
case ConnectionState.active:
case ConnectionState.waiting:
return Center(
child: CircularProgressIndicator(),
);
break;
case ConnectionState.done:
if (snapshot.hasError) {
return Text('error');
} else {
if (snapshot.hasData) {
return ListView.builder(
shrinkWrap: true,
itemCount: snapshot.data.length,
itemBuilder: (BuildContext context,
int position) {
/* String price =
snapshot.data[position]['price'];*/
/* print(snapshot
.data[1].user_id);*/
// inspect(snapshot.data);
return Card();
and I want to implement it inside this Widget for getting scrollable widget:
My code :
#override
Widget build(BuildContext context) {
return SafeArea(
minimum: const EdgeInsets.only(
top: 20.0, right: 5.0, left: 5.0, bottom: 10.0),
child: Center(
child: Scaffold(
backgroundColor: Color(0xFFF6F7F8),
body: Stack(
children: [
Container(
child: SingleChildScrollView(
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [
Container(
padding: EdgeInsets.all(10),
child: ElevatedButton.icon(
style: ElevatedButton.styleFrom(
primary: KBlue,
shape: RoundedRectangleBorder(
borderRadius:
BorderRadius.circular(30))),
onPressed: () {
showDialog(
context: context,
builder: (BuildContext context) =>
_addNewBox(context),
);
},
label: Text(
'Ajouter un nouveau box',
style: TextStyle(color: Colors.white),
),
icon: Icon(
CommunityMaterialIcons.plus,
color: Colors.white,
),
),
);
How can I implement scrollable widget correctly?
Related
I am trying to navigate to a route and this exception happen. Have look at my code and I don't think I have a FAB and Hero inside this route. Is it because when you tap on each List item, it will show a dialog with Gridview on it? Someone care to explain to me how can this exception happened? It doesn't produce any error on user thought, just throw an exception.
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("Daftar Dokter")),
body: ListView.separated(
separatorBuilder: (BuildContext context, int i) => Divider(color: Colors.grey[400]),
itemCount: widget.data.length,
itemBuilder: (context, index) {
Doctor doctor = widget.data[index];
return InkWell(
onTap: (){
_buildDialog(context, scheduleService, doctor.doctorId);
},
child: Row(
children: <Widget>[
Padding(
padding: const EdgeInsets.all(8.0),
child: SizedBox(
width: 50,
height: 50,
child: Placeholder(),
),
),
Flexible(
child: SizedBox(
child: ListTile(
title: Text(doctor.name),
subtitle: Text(doctor.specializationName),
),
)
)
],
),
);
}
)
);
}
}
Hope it will solve your issue:
onItem Builder:
itemBuilder: (context, index) {
return Hero(
tag: "itemTag $index",
child: Material(
child: InkWell(
onTap: () {
// _buildDialog(context, scheduleService, doctor.doctorId);
Navigator.of(context).push(MaterialPageRoute(
builder: (context) => Wisgets(
tag: "itemTag $index",
)));
},
child: Row(
children: <Widget>[
Text("Item $index"),
],
),
),
),
);
},
Child Widget for row
class Wisgets extends StatelessWidget {
final String tag;
const Wisgets({Key? key, required this.tag}) : super(key: key);
#override
Widget build(BuildContext context) {
return Hero(
tag: tag,
child: Scaffold(
appBar: AppBar(
title: Text("Child"),
),
body: Column(
children: [
Text("got $tag"),
],
),
),
);
}
}
I am currently trying to implement a list of dimissable widget items in combination with provider state management, but after hours of searching online i can't find a solution, so decide to post it here.
Here is my code
import 'package:crypto_trader_app/models/strategy.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:intl/intl.dart';
import '../providers/strategies.dart';
import '../widgets/strategy_item.dart';
import '../widgets/app_drawer.dart';
import './edit_strategy_screen.dart';
class StrategiesScreen extends StatelessWidget {
static const routeName = '/strategies';
Future<void> _refreshStrategies(BuildContext context) async {
await Provider.of<Strategies>(context, listen: false)
.fetchAndSetStrategies();
}
#override
Widget build(BuildContext context) {
print('rebuilding...');
return Scaffold(
appBar: AppBar(
title: const Text('Your Strategies'),
actions: <Widget>[
IconButton(
icon: const Icon(Icons.add),
onPressed: () {
Navigator.of(context).pushNamed(EditStrategyScreen.routeName);
},
),
],
),
drawer: AppDrawer(),
body: FutureBuilder(
future: _refreshStrategies(context),
builder: (ctx, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return Center(
child: CircularProgressIndicator(),
);
} else if (snapshot.hasError) {
return Center(
child: Text("ERROR: ${snapshot.error}"),
);
} else {
return buildStrategyItems(context);
}
},
),
);
}
Widget buildStrategyItems(BuildContext context) {
return RefreshIndicator(
onRefresh: () => _refreshStrategies(context),
child: Consumer<Strategies>(
builder: (ctx, strategiesData, _) => Padding(
padding: EdgeInsets.all(8),
child: ListView.builder(
itemCount: strategiesData.strategies.length,
itemBuilder: (ctx, i) {
final strategy = strategiesData.strategies[i];
return Column(
children: [
Dismissible(
key: UniqueKey(),
background: Container(
color: Colors.red,
child: Icon(
Icons.delete,
color: Colors.white,
size: 40,
),
alignment: Alignment.centerRight,
padding: EdgeInsets.only(right: 30),
),
direction: DismissDirection.endToStart,
onDismissed: (direction) {
// remove the strategy item from the list
strategiesData.strategies.removeAt(i);
Provider.of<Strategies>(ctx, listen: false)
.deleteStrategy(strategy.name);
// Then show a snackbar.
Scaffold.of(ctx).showSnackBar(SnackBar(
content: Text("Strategy successfully deleted")));
},
child: Card(
elevation: 3,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(2.0)),
child: InkWell(
onTap: () {
Navigator.of(ctx).pushNamed(
EditStrategyScreen.routeName,
arguments: strategy.name);
},
child: Padding(
padding: EdgeInsets.all(1),
child: ListTile(
leading: CircleAvatar(
child: Padding(
padding: EdgeInsets.all(5),
child: FittedBox(
child:
Text(strategy.asset.name.toUpperCase()),
),
),
),
title: Text(strategy.name),
subtitle: Text(
DateFormat('dd MMM yyyy')
.format(strategy.dateStarted),
style: TextStyle(fontSize: 10),
),
trailing: Text('1 mins'),
),
),
),
),
),
],
);
},
),
),
),
);
}
}
Essentially every time i swipe to delete a list, then click on a different item and go back to the list i get the following
I would really appreciate if you could help me figure this one out
lets try to use this
key: UniqueKey(),
I am trying to make it scrollable...enter image description here For some reason its not not scrolling and i tried adding singleChildScrollview still not working.... Pls look at the picture to understand better... so i posted the full code so that you guys can help me better... This was the error i got "Consider applying a flex factor (e.g. using an Expanded widget) to force the children of the RenderFlex to fit within the available space instead of being sized to their natural size. This is considered an error condition because it indicates that there is content that cannot be seen. If the content is legitimately bigger than the available space, consider clipping it with a ClipRect widget before putting it in the flex, or using a scrollable container rather than a Flex, like a ListView."
import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/material.dart';
import 'package:memoryblog/helper/authenticate.dart';
import 'package:memoryblog/services/auth.dart';
import 'package:memoryblog/services/database.dart';
import 'package:memoryblog/views/create_blog.dart';
class MemoryRoom extends StatefulWidget {
#override
_MemoryRoomState createState() => _MemoryRoomState();
}
class _MemoryRoomState extends State<MemoryRoom> {
AuthMethod authMethod = new AuthMethod();
DatabaseMethods databaseMethod = new DatabaseMethods();
Stream blogsStream;
Widget BlogsList(){
return Container(
child: blogsStream != null ? Column(
children: <Widget>[
StreamBuilder(
stream: blogsStream,
builder: (context, snapshot){
if(snapshot.data == null) return CircularProgressIndicator();
return ListView.builder(
padding: EdgeInsets.symmetric(horizontal: 16),
itemCount: snapshot.data.documents.length,
shrinkWrap: true,
itemBuilder: (context, index){
return BlogsTile(
authorName: snapshot.data.documents[index].data['memoryName'],
title: snapshot.data.documents[index].data['title'],
description: snapshot.data.documents[index].data['desc'],
imgUrl: snapshot.data.documents[index].data['imgUrl'],
);
}
);
},
)
],
) : Container(
alignment: Alignment.center,
child: CircularProgressIndicator(),
)
);
}
#override
void initState() {
// TODO: implement initState
databaseMethod.getData().then((result){
setState(() {
blogsStream = result;
});
});
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Row(
children: <Widget>[
Text(
"Memory"
),
Text(
"Blog",
style: TextStyle(
color: Colors.blue
),
)
],
),
backgroundColor: Colors.transparent,
elevation: 0.0,
actions: <Widget>[
GestureDetector(
onTap: (){
authMethod.signOut();
Navigator.pushReplacement(context, MaterialPageRoute(
builder: (context) => Authenticate()
));
},
child: Container(
padding: EdgeInsets.symmetric(horizontal: 16),
child: Icon(Icons.power_settings_new)),
)
],
),
body: BlogsList(),
floatingActionButton: Container(
padding: EdgeInsets.symmetric(vertical: 20),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
FloatingActionButton(
onPressed: (){
Navigator.push(context, MaterialPageRoute(
builder: (context) => CreateBlog()
));
},
child: Icon(Icons.add),
)
],
),
),
);
}
}
class BlogsTile extends StatelessWidget {
String imgUrl, title, description, authorName;
BlogsTile({#required this.imgUrl, #required this.title, #required this.description, #required this.authorName,});
#override
Widget build(BuildContext context) {
return Container(
margin: EdgeInsets.only(bottom: 16),
height: 170,
child: Stack(
children: <Widget>[
ClipRRect(
borderRadius: BorderRadius.circular(6),
child: CachedNetworkImage(
imageUrl: imgUrl,
width: MediaQuery.of(context).size.width,
fit: BoxFit.cover,
)
),
Container(
height: 170,
decoration: BoxDecoration(
color: Colors.black45.withOpacity(0.3),
borderRadius: BorderRadius.circular(6)
),
),
Container(
width: MediaQuery.of(context).size.width,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Text(
title,
textAlign: TextAlign.center,
style: TextStyle(fontSize: 25, fontWeight: FontWeight.w500),
),
SizedBox(height: 4,),
Text(
description,
textAlign: TextAlign.center,
style: TextStyle(fontSize: 17, fontWeight: FontWeight.w400),
),
SizedBox(height: 4,),
Text(authorName)
],
),
)
],
),
);
}
}
Use ListView in place of the column. OR
Wrap Column with SingleChildScrollView
return Container(
child: blogsStream != null
? ListView(
children: <Widget>[
StreamBuilder(
stream: blogsStream,
builder: (context, snapshot) {
if (snapshot.data == null) return CircularProgressIndicator();
return ListView.builder(
padding: EdgeInsets.symmetric(horizontal: 16),
itemCount: snapshot.data.documents.length,
shrinkWrap: true,
itemBuilder: (context, index) {
return BlogsTile(
authorName:
snapshot.data.documents[index].data['memoryName'],
title: snapshot.data.documents[index].data['title'],
description:
snapshot.data.documents[index].data['desc'],
imgUrl: snapshot.data.documents[index].data['imgUrl'],
);
});
},
)
],
)
: Container(
alignment: Alignment.center,
child: CircularProgressIndicator(),
),
);
I am struggling to understand why there is a yellow space between my two widgets... I am using a listView widget which use a snapshot to create a list
Here is my code
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: SingleChildScrollView(
child: Padding(
padding: EdgeInsets.symmetric(horizontal: 24.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
Text(
'My least tested groups',
),
Container(
color: Colors.yellowAccent,
child: SchoolList(),
),
],
),
),
),
),
);
}
And this is the Widget
class SchoolList extends StatelessWidget {
#override
Widget build(BuildContext context) {
return StreamBuilder<QuerySnapshot>(
stream: myStream1,
builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {
if (snapshot.hasError) return new Text('Error: ${snapshot.error}');
switch (snapshot.connectionState) {
case ConnectionState.waiting:
return new Text(
'Loading...',
style: kSendButtonTextStyle.copyWith(color: kColorText),
);
default:
return new ListView(
shrinkWrap: true,
physics: ClampingScrollPhysics(),
children:
snapshot.data.documents.map((DocumentSnapshot document) {
return Container(
height: 100,
width: 100,
color: Colors.white,
child: Text('xxx'));
}).toList(),
);
}
},
);
}
}
Can anyone understand why I have a yellow gap and more importantly how to get rid of it?
I think the ListView trying to applying top padding for status bar.
you can remove it by setting padding: const EdgeInsets.all(0.0) in the ListView widget.
I would like to change all app language without reload app. I used flutter_i18n
I have a switch language button on appBar and AppHomeScreen in body, here is build function in MyHomePage class:
addClickFn(model) {
FocusScope.of(context).requestFocus(FocusNode());
Navigator.push<dynamic>(
context,
MaterialPageRoute<dynamic>(
builder: (BuildContext context) => MyPopupScreen(callback: (c, id) => { }),
fullscreenDialog: true),
);
}
#override
Widget build(BuildContext context) {
return ScopedModelDescendant<ResponseDataModel>(
builder: (context, _, model) => Scaffold(
backgroundColor: AppTheme.white,
body: FutureBuilder<bool>(
future: getData(),
builder: (BuildContext context, AsyncSnapshot<bool> snapshot) {
if (!snapshot.hasData) {
return const SizedBox();
} else {
return Padding(
padding: EdgeInsets.only(
top: MediaQuery.of(context).padding.top),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
appBar(),
Expanded(
child: FutureBuilder<bool>(
future: getData(),
builder: (BuildContext context,
AsyncSnapshot<bool> snapshot) {
if (!snapshot.hasData) {
return const SizedBox();
} else {
return AppHomeScreen(
addClickFn: () => addClickFn(model));
}
},
),
),
],
),
);
}
},
),
));
}
appBar with onTap switch button function:
Widget appBar() {
return SizedBox(
height: AppBar().preferredSize.height,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Padding(
padding: const EdgeInsets.only(top: 8, left: 8),
child: Container(
width: AppBar().preferredSize.height - 8,
height: AppBar().preferredSize.height - 8,
),
),
Expanded(
child: Center(
child: Padding(
padding: const EdgeInsets.only(top: 4),
child: Text(
FlutterI18n.translate(context, "title"),
style: TextStyle(
fontSize: 22,
color: AppTheme.darkText,
fontWeight: FontWeight.w700,
),
),
),
),
),
Padding(
padding: const EdgeInsets.only(top: 8, right: 8),
child: Container(
width: AppBar().preferredSize.height - 8,
height: AppBar().preferredSize.height - 8,
color: Colors.white,
child: Material(
color: Colors.transparent,
child: InkWell(
borderRadius:
BorderRadius.circular(AppBar().preferredSize.height),
child: Image.asset(
'icons/flags/png/' + currentLang.languageCode + '.png',
package: 'country_icons'),
onTap: () async {
setState(() {
currentLang = currentLang.languageCode == 'vn'
? new Locale('gb')
: new Locale('vn');
});
await FlutterI18n.refresh(context, currentLang);
},
),
),
),
),
],
),
);
}
In AppHomePage I included BottomBarView with DashboardScreen as tab body
#override
Widget build(BuildContext context) {
return Container(
color: AppTheme.background,
child: Scaffold(
backgroundColor: Colors.transparent,
body: FutureBuilder<bool>(
future: getData(),
builder: (BuildContext context, AsyncSnapshot<bool> snapshot) {
if (!snapshot.hasData) {
return const SizedBox();
} else {
return Stack(
children: <Widget>[
tabBody,
bottomBar(),
],
);
}
},
),
),
);
}
Future<bool> getData() async {
await Future<dynamic>.delayed(const Duration(milliseconds: 200));
return true;
}
Widget bottomBar() {
return Column(
children: <Widget>[
const Expanded(
child: SizedBox(),
),
BottomBarView(
tabIconsList: tabIconsList,
addClick: () {
if (widget.addClickFn != null) widget.addClickFn();
},
changeIndex: (int index) {
if (index == 0) {
animationController.reverse().then<dynamic>((data) {
if (!mounted) {
return;
}
setState(() {
tabBody =
DashboardScreen(animationController: animationController);
});
});
}
},
),
],
);
}
And in DashboardScreen I show a label:
#override
Widget build(BuildContext context) {
return Container(
color: AppTheme.background,
child: Scaffold(
backgroundColor: Colors.transparent,
body: Stack(
children: <Widget>[
getMainListViewUI(),
// getAppBarUI(),
SizedBox(
height: MediaQuery.of(context).padding.bottom,
)
],
),
),
);
}
Widget getMainListViewUI() {
return ListView(
scrollDirection: Axis.vertical,
semanticChildCount: 10,
children: <Widget>[
Container(
padding:
EdgeInsets.only(top: 0.0, left: 24, right: 24, bottom: 24.0),
child: Text(FlutterI18n.translate(context, "label.welcome"),
textAlign: TextAlign.left,
style: TextStyle(
fontFamily: AppTheme.fontName,
fontWeight: FontWeight.w700,
fontSize: 30 + 6 - 6 * topBarOpacity,
letterSpacing: 1.2,
color: AppTheme.darkerText,
))),
],
);
}
When I click switch language button, all text in current context (title) translates very well, but in DashboardScreen (label.welcome) are not.
And when I click add button on bottomBar to redirect to MyPopupScreen then close this popup, text in DashboardScreen has been translated.
How can I change all text in DashboardScreen when click switch language button on MyHomePage?
Sorry for my bad english!!!
You call FlutterI18n.refresh with the old currentLang value.
Try this:
setState(() {
currentLang = currentLang.languageCode == 'vn'
? new Locale('gb')
: new Locale('vn');
FlutterI18n.refresh(context, currentLang);
});