infinite_scroll_pagination loading all the pages altogether: Flutter - flutter

I am making a Flutter Application where I am using Lazy Loading to load the data from server.
Now, the page I have made consists of following widgets in order-
Stack (with a button and a container)
SizedBox (for spacing)
SliverPagedList (to show lazy-loaded data).
Now, since the SliverPagedList is a Sliver widget I am using a CustomScrollView for the preceding widgets (Stack and SizedBox). I referred- https://pub.dev/packages/infinite_scroll_pagination/example#:~:text=Preceding/Following%20Items
The problem-
All the pages are fetched all together even when I have not reached the end of the page.
My code is-
class CategoryArticlePage extends StatefulWidget {
CategoryArticlePage({required this.category});
Category category;
#override
State<CategoryArticlePage> createState() => _CategoryArticlePageState();
}
class _CategoryArticlePageState extends State<CategoryArticlePage> {
SharedPreferences? _sharedPreferences;
final PostService _postService = PostService();
// List<posts.Post2>? _posts;
Future<void>? _loadData;
final PagingController<int, posts.Post2> _pageController =
PagingController(firstPageKey: 0);
#override
void initState() {
// _loadData = _loadArticles(); //without paging
_pageController.addPageRequestListener((pageKey) {
_loadArticles(pageKey);
});
super.initState();
}
Future<void> _loadArticles(int pageKey) async {
try {
_sharedPreferences ??= await SharedPreferences.getInstance();
final _posts = await _postService.getAllPostsForCategory(
token: _sharedPreferences!.getString(BEARER_TOKEN)!,
categoryid: widget.category.categoryId,
pageKey: pageKey,
pageSize: PAGE_SIZE);
final isLastPage = _posts.length < PAGE_SIZE;
if (isLastPage) {
_pageController.appendLastPage(_posts);
} else {
final nextPageKey = pageKey + 1;
_pageController.appendPage(_posts, nextPageKey);
}
} catch (error) {
_pageController.error = error;
}
}
#override
Widget build(BuildContext context) {
final height = MediaQuery.of(context).size.height -
// _appBar.preferredSize.height -
MediaQuery.of(context).padding.top -
MediaQuery.of(context).padding.bottom;
final width = MediaQuery.of(context).size.width;
return Scaffold(
body: SafeArea(
child: Consumer<CategoryProvider>(
builder: ((context, categoryProvider, child) {
return RefreshIndicator(
onRefresh: () {
return Future.sync(
() => _pageController.refresh(),
);
},
child: CustomScrollView(
slivers: <Widget>[
SliverToBoxAdapter(
child: Column(
children: [
Stack(
children: [
Container(
decoration: categoryTopDecoration,
padding: EdgeInsets.only(
left: 2,
right: 2,
bottom: 2,
),
alignment: Alignment.bottomLeft,
height: height * 0.4,
child: ListTile(
title: Text(
'${widget.category.categoryName}',
style: TextStyle(
fontSize: 40.sp,
fontWeight: FontWeight.bold,
),
),
subtitle: Text(
'${widget.category.categoryDescription}',
style: TextStyle(
fontSize: 20.sp,
fontWeight: FontWeight.w700,
),
),
),
),
Positioned(
right: 10,
top: 10,
child: Padding(
padding: EdgeInsets.only(
right: 4,
),
child: OutlinedButton(
onPressed: () async {
if (categoryProvider.subscribedCategoriesIDs
.contains(widget.category.categoryId)) {
bool result = await categoryProvider
.unsubscribeFromCategory(
token: _sharedPreferences!
.getString(BEARER_TOKEN)!,
userid: _sharedPreferences!
.getInt(USER_ID)!,
categoryid:
widget.category.categoryId);
} else {
bool result = await categoryProvider
.subscribeToCategory(
token: _sharedPreferences!
.getString(BEARER_TOKEN)!,
userid: _sharedPreferences!
.getInt(USER_ID)!,
categoryid:
widget.category.categoryId);
}
},
child: (categoryProvider
.subscribedCategoriesIDs
.contains(widget.category.categoryId)
? Text('Subscribed')
: Text('Subscribe')),
),
),
),
],
),
SizedBox(
height: height * 0.02,
),
],
),
),
PagedSliverList<int, posts.Post2>.separated(
pagingController: _pageController,
builderDelegate: PagedChildBuilderDelegate<posts.Post2>(
animateTransitions: true,
// [transitionDuration] has a default value of 250 milliseconds.
transitionDuration: const Duration(milliseconds: 500),
itemBuilder: (context, item, index) {
return Padding(
padding: EdgeInsets.only(
bottom: 2,
top: 2,
),
child: GestureDetector(
onTap: () {
Get.to(() => ExploreViewArticle(
post: item,
sharedPreferences: _sharedPreferences!));
},
child: ListTile(
leading: SizedBox(
child: SizedBox(
height: 100,
width: 100,
child: CachedNetworkImage(
imageUrl:
'https://<blobstorage>/imagecontainer/${item.image}',
placeholder: (context, url) => Center(
child: Container(
height: 50,
width: 50,
child: DataLoadingIndicator(),
),
),
errorWidget: (context, url, error) =>
Image.asset(
'images/category_default.jpg'),
fit: BoxFit.cover,
),
),
),
title: Text('${item.title}'),
),
),
);
},
),
separatorBuilder: (context, index) {
return Container(
height: 2,
color: Colors.black,
);
},
),
],
),
);
}),
),
),
);
}
#override
void dispose() {
log('CategoryArticlePage dispose called');
_pageController.dispose();
super.dispose();
}
}

Related

How to wait for a request to complete using ObservableFuture?

When I transition to a screen where I get a list of information via an API, it initially gives an error:
_CastError (Null check operator used on a null value)
and only after loading the information, the screen is displayed correctly.
I am declaring the variables like this:
#observable
ObservableFuture<Model?>? myKeys;
#action
getKeys() {
myKeys = repository.getKeys().asObservable();
}
How can I enter the page only after loading the information?
In button action I tried this but to no avail!
await Future.wait([controller.controller.getKeys()]);
Modular.to.pushNamed('/home');
This is the page where the error occurs momentarily, but a short time later, that is, when the api call occurs, the data appears on the screen.
class MyKeyPage extends StatefulWidget {
const MyKeyPage({Key? key}) : super(key: key);
#override
State<MyKeyPage> createState() => _MyKeyPageState();
}
class _MyKeyPageState
extends ModularState<MyKeyPage, KeyController> {
KeyController controller = Modular.get<KeyController>();
Widget countKeys() {
return FutureBuilder(
builder: (BuildContext context, AsyncSnapshot<dynamic> snapshot) {
final count =
controller.myKeys?.value?.data!.length.toString();
if (snapshot.connectionState == ConnectionState.none &&
!snapshot.hasData) {
return Text('..');
}
return ListView.builder(
scrollDirection: Axis.vertical,
shrinkWrap: true,
itemCount: 1,
itemBuilder: (context, index) {
return Text(count.toString() + '/5');
});
},
future: controller.getCountKeys(),
);
}
#override
Widget build(BuildContext context) {
Size _size = MediaQuery.of(context).size;
return controller.getCountKeys() != "0"
? TesteScaffold(
removeHorizontalPadding: true,
onBackPressed: () => Modular.to.navigate('/exit'),
leadingIcon: ConstantsIcons.trn_arrow_left,
title: '',
child: Container(
width: double.infinity,
child: Padding(
padding: const EdgeInsets.only(left: 24),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Keys',
style: kHeaderH3Bold.copyWith(
color: kBluePrimaryTrinus,
),
),
countKeys(),
],
),
),
),
body: Observer(builder: (_) {
return Padding(
padding: const EdgeInsets.only(bottom: 81),
child: Container(
child: ListView.builder(
padding: EdgeInsets.only(
left: 12.0,
top: 2.0,
right: 12.0,
),
itemCount:
controller.myKeys?.value?.data!.length,
itemBuilder: (context, index) {
var typeKey = controller
.myKeys?.value?.data?[index].type
.toString();
var id =
controller.myKeys?.value?.data?[index].id;
final value = controller
.myKeys?.value?.data?[index].value
.toString();
return GestureDetector(
onTap: () {
.
.
},
child: CardMeyKeys(
typeKey: typeKey,
value: value!.length > 25
? value.substring(0, 25) + '...'
: value,
myKeys: pixController
.minhasChaves?.value?.data?[index].type
.toString(),
),
);
},
),
),
);
}),
bottomSheet: ....
)
: TesteScaffold(
removeHorizontalPadding: true,
onBackPressed: () => Modular.to.navigate('/exit'),
leadingIcon: ConstantsIcons.trn_arrow_left,
title: '',
child: Container(
width: double.infinity,
child: Padding(
padding: const EdgeInsets.only(left: 24),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'...',
style: kHeaderH3Bold.copyWith(
color: kBluePrimaryTrinus,
),
),
],
),
),
),
body: Padding(
padding: const EdgeInsets.only(bottom: 81),
child: Container(
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Image.asset(
'assets/images/Box.png',
fit: BoxFit.cover,
width: 82.75,
height: 80.91,
),
SizedBox(
height: 10,
),
],
),
), //Center
),
),
bottomSheet: ...
);
}
List<ReactionDisposer> disposers = [];
#override
void initState() {
super.initState();
controller.getKeys();
}
#override
void dispose() {
disposers.forEach((toDispose) => toDispose());
super.dispose();
}
}
Initially the error occurs in this block
value: value!.length > 25
? value.substring(0, 25) + '...'
: value,
_CastError (Null check operator used on a null value)
I appreciate if anyone can help me handle ObservableFuture correctly!
You need to call the "future" adding
Future.wait
(the return type of getKeys) keys=await Future.wait([
controller.getKeys();
]);
The problem is your getKeys function isn't returning anything, so there's nothing for your code to await. You need to return a future in order to await it.
Future<Model?> getKeys() {
myKeys = repository.getKeys().asObservable();
return myKeys!; // Presumably this isn't null anymore by this point.
}
...
await controller.controller.getKeys();
Modular.to.pushNamed('/home');

Why does a Container in a SingleChildScrollView not constrain content?

I'm pretty new both to Flutter/Dart and Stack Overflow. I started with some trip ETA code and modified it to be an initiative turn tracker for a fantasy RPG tabletop game.
My intent is to keep the End Encounter button on the screen at all times, and have the timeline content scroll in a window above it.
I added a SingleChildScrollView into _TurnSectionState at line 178, but as soon as I add a Container into it I get the overflow. I tried for about 3 hours before asking for help here.
final data = _data(1);
return Scaffold(
appBar: TitleAppBar(widget._title),
body: Center(
child: SingleChildScrollView(
child: SizedBox(
width: 380.0,
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Padding(
padding: const EdgeInsets.all(20.0),
child: _MissionName(
timeSliceInfo: data,
),
),
const Divider(height: 1.0),
_TurnSection(processes: data.deliveryProcesses),
const Divider(height: 1.0),
const Padding(
padding: EdgeInsets.all(20.0),
child: _OnTimeBar(),
),
],
),
),
),
),
);
}
}
// Mission name
class _MissionName extends StatelessWidget {
const _MissionName({
Key? key,
required this.timeSliceInfo,
}) : super(key: key);
final _TimeSliceInfo timeSliceInfo;
#override
Widget build(BuildContext context) {
return Row(
children: [
Text(
missions[currentMission].getTitle(),
style: const TextStyle(
fontWeight: FontWeight.bold,
),
),
],
);
}
}
// Lists items in each turn
class _InnerTimeline extends StatefulWidget {
const _InnerTimeline({
required this.messages,
});
final List<ActivationLineItem> messages;
#override
State<_InnerTimeline> createState() => _InnerTimelinePageState();
}
class _InnerTimelinePageState extends State<_InnerTimeline> {
#override
initState() {
super.initState();
}
#override
Widget build(BuildContext context) {
bool isEdgeIndex(int index) {
return index == 0 || index == widget.messages.length + 1;
}
// Interior connector lines
return Padding(
padding: const EdgeInsets.symmetric(vertical: 8.0),
child: FixedTimeline.tileBuilder(
theme: TimelineTheme.of(context).copyWith(
nodePosition: 0,
connectorTheme: TimelineTheme.of(context).connectorTheme.copyWith(
thickness: 1.0,
),
indicatorTheme: TimelineTheme.of(context).indicatorTheme.copyWith(
size: 10.0,
position: 0.5,
),
),
builder: TimelineTileBuilder(
indicatorBuilder: (_, index) =>
!isEdgeIndex(index) ? Indicator.outlined(borderWidth: 1.0) : null,
startConnectorBuilder: (_, index) => Connector.solidLine(),
endConnectorBuilder: (_, index) => Connector.solidLine(),
contentsBuilder: (_, index) {
if (isEdgeIndex(index)) {
return null;
}
// Line item (init value + icon + text)
return Padding(
padding: const EdgeInsets.only(left: 8.0),
child: Row(children: [
Text(widget.messages[index - 1].tick.toString()),
const SizedBox(width: 6),
Image(
image: AssetImage(widget.messages[index - 1].thumbnail),
width: 20,
height: 20),
const SizedBox(width: 6),
Expanded(
child: Text(widget.messages[index - 1].message,
overflow: TextOverflow.ellipsis, maxLines: 1))
]));
},
itemExtentBuilder: (_, index) => isEdgeIndex(index) ? 10.0 : 30.0,
nodeItemOverlapBuilder: (_, index) =>
isEdgeIndex(index) ? true : null,
itemCount: widget.messages.length + 2,
),
),
);
}
}
// Outer timeline (List of turns)
class _TurnSection extends StatefulWidget {
const _TurnSection({Key? key, required processes})
: _processes = processes,
super(key: key);
final List<TurnContents> _processes;
#override
_TurnSectionState createState() => _TurnSectionState();
}
class _TurnSectionState extends State<_TurnSection> {
bool isExpanded = false;
#override
Widget build(BuildContext context) {
return DefaultTextStyle(
style: const TextStyle(
color: Color(0xff9b9b9b), // Nobel Gray
fontSize: 12.5,
),
child: SingleChildScrollView(
child: SizedBox(
height: 480,
child: Column(
children: [
FixedTimeline.tileBuilder(
theme: TimelineThemeData(
nodePosition: 0,
color: const Color(0xff989898), // Spanish Gray
indicatorTheme: const IndicatorThemeData(
position: 0,
size: 20.0, // Outer timeline circle size
),
connectorTheme: const ConnectorThemeData(
thickness: 2.5, // Outer timeline line thickness
),
),
builder: TimelineTileBuilder.connected(
connectionDirection: ConnectionDirection.before,
itemCount: widget._processes.length,
contentsBuilder: (_, index) {
if (widget._processes[index].isCompleted) return null;
return GestureDetector(
onTap: () {
int turnNum = widget._processes[index].getTurnNum();
if (turnNum == currentTurn) {
// Ask if ready for next turn
showDialog<String>(
context: context,
builder: (BuildContext context) => AlertDialog(
title: const Text('Next Turn?'),
content: Text('Ready to start turn ?' +
(currentTurn + 1).toString()),
actions: <Widget>[
TextButton(
onPressed: () =>
Navigator.pop(context, 'Yes'),
child: const Text('Yes'),
),
TextButton(
onPressed: () => Navigator.pop(context, 'No'),
child: const Text('No'),
),
],
),
).then((value) {
if (value == 'Yes') {
currentTurn++; // Move to the next turn
setState(() {}); // Draw the screen
}
});
}
},
child: Padding(
padding: const EdgeInsets.only(left: 8.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: [
Text(
widget._processes[index]
.getName(), // Turn name font size
style:
DefaultTextStyle.of(context).style.copyWith(
fontSize: 18.0,
),
),
_InnerTimeline(
messages:
widget._processes[index].getMessages()),
],
),
),
);
},
indicatorBuilder: (_, index) {
if (index <= currentTurn) {
return const DotIndicator(
color: Color(0xff66c97f), // Emerald Green dot
child: Icon(
Icons.check,
color: Colors.white,
size: 12.0,
),
);
} else {
return const OutlinedDotIndicator(
borderWidth: 2.5,
);
}
},
connectorBuilder: (_, index, ___) => SolidLineConnector(
color: index <= currentTurn
? const Color(0xff66c97f) // Emerald Green connector
: null, // Green
),
),
),
],
),
),
),
);
}
}
class _OnTimeBar extends StatelessWidget {
const _OnTimeBar({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Row(
children: [
MaterialButton(
onPressed: () {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text('On Time!'),
),
);
},
elevation: 0,
shape: const StadiumBorder(),
color: const Color(0xff66c97f),
textColor: Colors.white,
child: const Text('End Encounter'),
),
const Spacer(),
const SizedBox(width: 12.0),
],
);
}
}
/*
List<TurnContents> buildTimeline() {
List<TurnContents> turns;
return turns;
}
*/
_TimeSliceInfo _data(int id) => _TimeSliceInfo(
id: id,
date: DateTime.now(),
deliveryProcesses: ImpulseBuilder().buildTimeline(),
);
class _TimeSliceInfo {
const _TimeSliceInfo({
required this.id,
required this.date,
required this.deliveryProcesses,
});
final int id;
final DateTime date;
final List<TurnContents> deliveryProcesses;```
}
[1]: https://i.stack.imgur.com/mGd5X.png
use Expanded and in SingleChildScrollView add physics:ScrollPhysics()
Expanded(
child: Container(
child: SingleChildScrollView(
physics: ScrollPhysics(),
child: Column(
children: []
)
)
)
);

Why i am not able to use setState Under GestureDetector

Why I am not able to use setState Under GestureDetector Using onTap:
After I use setState I got an error like: The function 'setState' isn't defined.
Try importing the library that defines 'setState', And VS Code editor show me
Error like: correcting the name to the name of an existing function, or defining a function named 'setState'.dart(undefined_function).
I try to fix different ways please tell me where is my problem
Thank you
Some Flutter Import Link ::::::::::
class ParsingMap extends StatefulWidget {
const ParsingMap({Key? key}) : super(key: key);
#override
_ParsingMapState createState() => _ParsingMapState();
}
class _ParsingMapState extends State<ParsingMap> {
Future<ApiList>? data;
#override
void initState() {
super.initState();
Network network = Network("https://fakestoreapi.com/products");
data = network.loadPosts();
// print(data);
setState(() {});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.white,
elevation: 0,
leading: Icon(Icons.arrow_left, color: Colors.black),
actions: [
Icon(Icons.search, color: Colors.black),
SizedBox(width: 10),
Icon(Icons.home_filled, color: Colors.black),
SizedBox(width: 8)
],
),
body: Center(
child: Container(
child: FutureBuilder(
future: data,
builder: (context, AsyncSnapshot<ApiList> snapshot) {
List<Api> allPosts;
if (snapshot.hasData) {
allPosts = snapshot.data!.apis!;
return createListView(allPosts, context);
}
return CircularProgressIndicator();
},
),
),
),
);
}
}
class Network {
final String url;
Network(this.url);
Future<ApiList> loadPosts() async {
final response = await get(Uri.parse(url));
if (response.statusCode == 200) {
// print(response.body);
return ApiList.fromJson(json.decode(response.body));
} else {
throw Exception("Faild To get posts");
}
}
}
Widget createListView(List<Api> data, BuildContext context) {
return ListView(
children: [
Container(
height: 300,
margin: EdgeInsets.symmetric(vertical: 16),
child: ListView.builder(
itemCount: data.length,
scrollDirection: Axis.horizontal,
physics: BouncingScrollPhysics(),
padding: EdgeInsets.symmetric(horizontal: 16),
itemBuilder: (context, index) {
int selectedIndex = 0;
return GestureDetector(
onTap: () {
setState(() {
selectedIndex = index;
});
},
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 10),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"${data[index].category}",
style: TextStyle(
fontWeight: FontWeight.bold,
color: selectedIndex == index
? Colors.black
: Colors.black38),
),
Container(
margin: EdgeInsets.only(
top: 5,
),
height: 2,
width: 30,
color: selectedIndex == index
? Colors.black
: Colors.transparent,
)
],
),
),
);
},
),
),
],
);
}
Put top-level createListView function in _ParsingMapState class.
class _ParsingMapState extends State<ParsingMap> {
// ...
Widget createListView(...) {}
}

How to Hide a card in flutter

I make one page to edit data by user.In this page I have two card.In the first card, I can see the user's picture.In the second card, I can see the user’s picture after selecting them from the phone or the picture they want to update.But now my problem is, how can I hide the first card if the second card appears after the user selects an image from the phone.I know it can be done by using Visibility in Java, but I'm a new filter developer and I don't know how to do it. I searched a lot and couldn't solve the problem.
Card 1:
child: Card(
child: new Column(
children: <Widget>[
Image.network(image, width: 385,height: 300,
fit: BoxFit.cover,
),
OutlineButton(
onPressed: chooseImage,
child: Text('Choose Image'),
),
])
),
Card 2:
Card(
child: SizedBox(
width: 400.0,
height: 300.0,
child: new Padding(
padding:
const EdgeInsets.only(top: 2.0, bottom: 2.0),
child: Expanded(flex: 1,
child: showImage(),
)
),
),
),
Full page:
class update_profilettt extends StatefulWidget {
var PostID;
update_profilettt({Key key, this.PostID}) : super(key: key);
#override
_update_profiletttState createState() => new _update_profiletttState(PostID);
}
class _update_profiletttState extends State<update_profilettt> {
MyPreferences _myPreferences = MyPreferences();
var PostID;
String uploadEndPoint;
_update_profiletttState(this. PostID);
Future<File> file;
String status = '';
String base64Image;
File tmpFile;
String errMessage = 'Error Uploading Image';
var data;
var _name = "";
// var _genderController = new TextEditingController();
var _nameController = new TextEditingController();
chooseImage() {
setState(() {
file = ImagePicker.pickImage(source: ImageSource.gallery);
});
setStatus('');
}
setStatus(String message) {
setState(() {
status = message;
});
}
startUpload() {
setStatus('Uploading Image...');
if (null == tmpFile) {
setStatus(errMessage);
return;
}
String NameImage =DateTime.now().millisecondsSinceEpoch.toString();
upload(NameImage);
}
upload(String NameImage) {
uploadEndPoint = 'http://xxxxxxx/up.php?id='+widget.PostID.toString();
print('yeyyyyddyy $uploadEndPoint');
http.post(uploadEndPoint, body: {
'id': widget.PostID.toString(),
}).then((result) {
setStatus(result.statusCode == 200 ? result.body : errMessage);
}).catchError((error) {
setStatus(error);
});
}
Widget showImage() {
return FutureBuilder<File>(
future: file,
builder: (BuildContext context, AsyncSnapshot<File> snapshot) {
if (snapshot.connectionState == ConnectionState.done &&
null != snapshot.data) {
tmpFile = snapshot.data;
base64Image = base64Encode(snapshot.data.readAsBytesSync());
return Flexible(
child: Card(
margin:EdgeInsets.all(10) ,
child: Image.file(
snapshot.data,
fit: BoxFit.cover,
),
),
);
} else if (null != snapshot.error) {
return const Text(
'Error Picking Image',
textAlign: TextAlign.center,
);
} else {
return const Text(
'',
textAlign: TextAlign.center,
);
}
},
);
}
Future<String> _ShowDialog(String msg) async {
return showDialog<String>(
context: context,
barrierDismissible: false, // user must tap button!
builder: (BuildContext context) {
return new AlertDialog(
title: new Text('Rewind and remember'),
content: new SingleChildScrollView(
child: new ListBody(
children: <Widget>[
new Text(msg),
],
),
),
actions: <Widget>[
new FlatButton(
child: new Text('Close'),
onPressed: () {
Navigator.of(context).pop();
},
),
],
);
},
);
}
void _editData() async {
// String NameImage =DateTime.now().millisecondsSinceEpoch.toString();
var url = 'http://xxxxxxxxxx/up.php?id='+widget.PostID.toString();
var response = await http.post(url, body: {
'id': widget.PostID.toString(),
// "id": _userController.text,
"name": _nameController.text,
"image": base64Image,
// "gender": _genderController.text,
});
if (response.statusCode == 200) {
_ShowDialog("Updated Successfully");
} else {
_ShowDialog("Updated Failer");
}
//onEditedAccount();
//print(_adresseController.text);
}
_fetchData() async {final url = "http://xxxxxxxx/nhy.php?id=${widget.PostID}";
final response = await http.get(url);
if (response.statusCode == 200) {
final map = json.decode(response.body);
final videosMap = map["result"];
setState(() {
this.data = videosMap;
_name = data[0]['name'];
image = data[0]['image'];
// _gender = data[0]['gender'];
print(data);
});
}
}
#override
void initState() {
super.initState();
_fetchData();
}
#override
Widget build(BuildContext context) {
_nameController= new TextEditingController(text: _name);
if(chooseImage !=null){
}
return new Scaffold(
appBar: AppBar(
title: Text("Edit Post"),
),
body: new Center(
child: data == null
? new CircularProgressIndicator()
: new ListView(
children: <Widget>[
new Padding(
padding: const EdgeInsets.fromLTRB(5, 10, 5, 5),
child: Column(
children: <Widget>[
new Padding(
padding:
const EdgeInsets.only(top: 10.0, bottom: 10.0),
child: Expanded(flex: 1,
child: Container(
child: Card(
child: new Column(
children: <Widget>[
Image.network(image, width: 385,height: 300,
fit: BoxFit.cover,
),
OutlineButton(
onPressed: chooseImage,
child: Text('Choose Image'),
),
])
),
),
),
),
Card(
child: SizedBox(
width: 400.0,
height: 300.0,
child: new Padding(
padding:
const EdgeInsets.only(top: 2.0, bottom: 2.0),
child: Expanded(flex: 1,
child: showImage(),
)
),
),
),
Card (
child: Column(
children: <Widget>[
SizedBox(
height: 10.0,
),
Container(
margin: EdgeInsets.all(4),
child: TextField(
maxLength: 10,
decoration: InputDecoration(
border: OutlineInputBorder(),
labelText: 'Name',
filled: true,
hintText: ''),
controller: _nameController,
),
),
SizedBox(
height: 5.0,
),
),
SizedBox(
height: 5.0,
),
),
),
),
),
SizedBox(
height: 5.0,
),
]
)
),
SizedBox(
width: double.infinity,
child: new FlatButton(
child: const Text('Update'),color: Colors.amber,
padding: EdgeInsets.fromLTRB(100, 18, 100, 18),
onPressed: () { _editData();
},
),
),
SizedBox(
height: 10.0,
),
],
),
)
],
),
));
}
}
There is a Visibility widget in flutter too you can wrap your card with it
Example
bool visibilityController = true;
true for visibile and false for not visible
so when select the card use setstate to toggle it.
setState(() {
});
Visibility(
visible: visibilityController,
child : //Your card
),
Hope this is what you wished for.
For your code
you can do this when your showimage() gets an image
Widget showImage() {
return FutureBuilder<File>(
future: file,
builder: (BuildContext context, AsyncSnapshot<File> snapshot) {
if (snapshot.connectionState == ConnectionState.done &&
null != snapshot.data) {
tmpFile = snapshot.data;
base64Image = base64Encode(snapshot.data.readAsBytesSync());
setState(() {
// added here
visibilityController = false;
});
return ........ your code

How do I fix a flickering (blinking) menu screen?

I have added a GIF where you can see that when I click on favourite (heart) menu it loads smoothly and doesn't flick but when I click on side menu it flicks
I am working on an app and I am trying to resolve an issue, there is a screen whenever I click it, it flicks or blinks, it kind of refreshes. All the content it contain refresh, like if I click it I feel like I come on that screen then the items come there later on, it happens in few frictions of seconds but it is too annoying. I tried everything but still.
I tried to slow down the animation globally by using time dilation but it is still happening.
const String logo = "assets/profile/images/stadia_logo.svg";
class ProfileScreen extends StatefulWidget {
#override
_ProfileScreenState createState() => _ProfileScreenState();
}
class _ProfileScreenState extends State<ProfileScreen> {
#override
Widget build(BuildContext context) {
final user = Provider.of<User>(context);
final StorageService ref = StorageService();
final screenHeight = MediaQuery.of(context).size.height;
final screenWidth = MediaQuery.of(context).size.width;
final logoHeight = screenHeight * 0.4;
return Scaffold(
backgroundColor: Colors.white,
body: FutureBuilder(
future: ref.getProfileUrl(user.uid),
builder: (BuildContext context, AsyncSnapshot<String> url) {
if (url.connectionState == ConnectionState.waiting) {
return Loading(
size: 20,
);
}
if (url.hasData) {
return StreamBuilder<DocumentSnapshot>(
stream: DatabaseService(uid: user.uid).userData,
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return Loading(
size: 15,
);
}
if (snapshot.data == null) {
return Loading(
size: 15,
);
}
var userData = snapshot.data;
String _imageUrl = url.data;
if (snapshot.hasData) {
List books = userData['audio_read'];
if (books == null) {
return Loading(
size: 15,
);
//this
}
return Scaffold(
body: Stack(
children: <Widget>[
Transform.translate(
offset: Offset(screenWidth * 0.4, 10),
child: Transform.rotate(
angle: -0.1,
child: SvgPicture.asset(
logo,
height: logoHeight,
color: logoTintColor,
),
),
),
SingleChildScrollView(
child: Column(
children: <Widget>[
SizedBox(
height: 60,
),
Padding(
padding: const EdgeInsets.symmetric(
horizontal: 16.0),
child: Column(
crossAxisAlignment:
CrossAxisAlignment.start,
children: <Widget>[
//
createFirstNameHeader(
user, ref, userData),
Padding(
padding: const EdgeInsets.only(
right: 16.0, bottom: 16, top: 16),
child: Material(
elevation: 4,
borderRadius:
const BorderRadius.all(
Radius.circular(12)),
child: Padding(
padding: const EdgeInsets.only(
left: 16.0,
right: 16.0,
top: 16.0,
bottom: 32.0),
child: Column(
crossAxisAlignment:
CrossAxisAlignment.start,
children: <Widget>[
Row(
children: <Widget>[
Text(
"TOTAL TALES PLAYED",
style:
hoursPlayedLabelTextStyle,
),
],
),
SizedBox(
height: 4,
),
Text(
"${books.length.toString()} ${books.length > 1 ? "Tales" : "Tale"}",
style: hoursPlayedTextStyle
.copyWith(
color: Color(
0xff5E17EB)),
)
],
),
),
),
),
ContentHeadingWidget(
heading: "Continue listening"),
for (var i = books.length - 1;
i >= 0;
i--)
books.length > 0
? Slidable(
actionExtentRatio: 0.25,
actionPane:
SlidableDrawerActionPane(),
secondaryActions: <Widget>[
IconSlideAction(
caption: 'Delete',
color: Colors.red,
icon: Icons.delete,
onTap: () => {
_deletePressed(
user,
books.elementAt(
i)[
'audio_id']),
}),
],
child: LastReadBook(
audioId: books.elementAt(
i)['audio_id'],
audio_index: int.parse(
books.elementAt(i)[
'audio_index']),
audioSeek: books.elementAt(
i)['audio_seek'],
total: books.elementAt(
i)['total'],
progress: int.parse(books.elementAt(i)['audio_index']) /
books.elementAt(
i)["totalIndex"],
description:
"${books.elementAt(i)["audio_index"]} of ${books.elementAt(i)["totalIndex"]} episodes",
image: books
.elementAt(i)['image']),
)
: Loading(
size: 15,
),
],
),
),
],
),
)
],
),
);
} else {
return Loading(
size: 15,
);
}
});
} else {
return Loading(
size: 15,
);
}
}),
);
}
Padding createFirstNameHeader(
User user, StorageService ref, DocumentSnapshot userData) {
return Padding(
padding: const EdgeInsets.symmetric(
vertical: 16.0,
),
child: Row(
children: <Widget>[
createProfileImage(user, ref),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 10.0),
child: RichText(
text: TextSpan(
children: [
TextSpan(
text: 'Hello',
style: userNameTextStyle,
),
TextSpan(text: '\n'),
TextSpan(
text: userData['firstname'], style: userNameTextStyle),
],
),
),
),
],
),
);
}
createProfileImage(User user, StorageService ref) {
return StreamBuilder(
stream: Firestore.instance
.collection("Users")
.document(user.uid)
.snapshots(),
builder: (context, AsyncSnapshot<DocumentSnapshot> snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
// return Center(
// child: CircularProgressIndicator(),
// );
return Loading(
size: 15,
);
}
if (snapshot.data == null) {
return Loading(
size: 15,
);
}
print(snapshot.data.data);
return GestureDetector(
onTap: () async {
if (user.uid != HomeScreen.defaultUID) {
dynamic imageFromUser = await ref.getImage();
await ref.addImageToFirebase(user.uid, imageFromUser);
} else {
createAccountDialouge(context);
}
},
child: RoundedImageWidget(
imagePath: snapshot.data["profile_image"],
icon: Icons.photo_camera,
showIcon: true),
);
});
}
createAccountDialouge(BuildContext context) {
return showDialog(
context: context,
child: CupertinoAlertDialog(
title: Text('Avid Tale Would Like to Enable Full Access'),
content: Text('Creating an account will enable access to this feature'),
actions: <Widget>[
CupertinoDialogAction(
child: Text('Cancel'),
onPressed: () {
Navigator.pop(context);
},
),
CupertinoDialogAction(
child: Text('Register'),
onPressed: () {
Navigator.pop(context);
Navigator.push(
context,
MaterialPageRoute(
builder: (context) {
return RegisterScreen();
},
),
);
},
)
],
),
);
}
void _deletePressed(user, bookId) async {
DatabaseService userService = DatabaseService(uid: user.uid);
DocumentSnapshot documentSnapshot =
await Firestore.instance.collection("Users").document(user.uid).get();
var data = documentSnapshot.data["audio_read"];
data.retainWhere((element) => element["audio_id"] != bookId);
await userService.updateUserData({'audio_read': FieldValue.delete()});
await userService
.updateUserData({'audio_read': FieldValue.arrayUnion(data)});
}
}
Every time you delete an item, it triggers a new event in the Stream. As the Stream is retrieving/processing the new data it goes into this if block of code as the connectionState changes to waiting:
if (snapshot.connectionState == ConnectionState.waiting) {
return Loading(
size: 15,
);
}
Simply removing this block of code will should stop the "flickering". You may need to include other checks of data availability if necessary for your application.