How to attach flutter swiper to any scroll views?I have horizontal swiper,i scroll down my ui and then i scroll back(up), as a rezult i get Exception 'ScrollController not attached to any scroll views'.
What i should do to fix it.Could you help me?
class SwiperTop extends StatelessWidget {
MBloc _Bloc = BlocProvider.getBloc<MBloc>();
#override
Widget build(BuildContext context) {
return Container(
height: 284.0,
child: StreamBuilder(
initialData: List<MEntity>(),
stream: _mBloc.listMoviesFlux,
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (!snapshot.hasData) return Container(height: 1, width: 1);
return Swiper(
loop: true,
itemCount: snapshot.data.length,
itemBuilder: (BuildContext context, int index) {
return _itemM(snapshot.data[index], context, index);
},
viewportFraction: 0.8,
scale: 0.8,
autoplay: true,
duration: 300,
autoplayDelay: 3000,
index: 0,
);
}),
);
}
}
Related
The page got an error "A RenderFlex overflowed by 80 pixels on the bottom". How can you fix it?
class FavNews extends StatelessWidget {
final FavoritesController controller = Get.find();
FavNews({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Obx(() {
return SizedBox(
height: MediaQuery.of(context).size.height,
child: ListView.builder(
itemCount: controller.news.length,
itemBuilder: (BuildContext context, int index) {
return FavNewsItem(
article: controller.news.keys.toList()[index],
index: index,
);
}),
);
});
}
}
Put it Sizedbox inside a SingleChildScrollView widget.
return SingleChildScrollView(
child: SizedBox(
height: MediaQuery.of(context).size.height,
child: ListView.builder(
itemCount: controller.news.length,
itemBuilder: (BuildContext context, int index) {
return FavNewsItem(
article: controller.news.keys.toList()[index],
index: index,
);
}),)
Just try it. It may work
The issue is with the height of your SizedBox.
MediaQuery.of(context).size.height return the height of your entire screen including statusbar, appbar and system gestires at the bottom.
With ListView.builder you can use shrinkWrap: true that will use only the space that it acutally need to use.
Example:
return SingleChildScrollView(
child: ListView.builder(
shrinkWrap: true,
itemCount: controller.news.length,
itemBuilder: (BuildContext context, int index) {
return FavNewsItem(
article: controller.news.keys.toList()[index],
index: index,
);
}),
),
);
do not hardcoat the height while using the scrollbar remove the height attribute and it'll work just fine
final FavoritesController controller = Get.find();
FavNews({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Obx(() {
return SizedBox(
child: ListView.builder(
itemCount: controller.news.length,
itemBuilder: (BuildContext context, int index) {
return FavNewsItem(
article: controller.news.keys.toList()[index],
index: index,
);
}),
);
});
}
}```
you do not need sizedBox
return Obx(() {
return ListView.builder(
srinkWrap: true;
itemCount: controller.news.length,
itemBuilder: (BuildContext context, int index) {
return FavNewsItem(
article: controller.news.keys.toList()[index],
index: index,
);
}),);
}
I have an app that gets some data from firebase and than calls a class to display a widget based on the data from firebase. I tried adding a swipe up refresh but i have no idea where to put it and what to to call on refresh. I was trying it using the RefreshIndicator.
Here i will put my code in which it calls the database(firebase) and than creates an widget for each event in the database.
If you need any more information, please feel free to comment. Thank you so much for the help!
FutureBuilder(
future: databaseReference.once(),
builder: (context, AsyncSnapshot<DataSnapshot> snapshot) {
List lists = [];
if (snapshot.hasData) {
lists.clear();
Map<dynamic, dynamic> values = snapshot.data.value;
values.forEach((key, values) {
lists.add(values);
});
return new ListView.builder(
primary: false,
padding: EdgeInsets.only(left:12.0,right:12,bottom: 15,),
shrinkWrap: true,
itemCount: lists.length,
itemBuilder: (BuildContext context, int index) {
if(lists[index]["Status"]== "Active"){;
return Container(
child:EvendWidget(lists[index]["EventImage"],
Text(lists[index]["EventName"]).data,
Text(lists[index]["EventLocation"]+ ", "+lists[index]["EventCounty"] ).data,
Text(lists[index]["Date"]+ ", "+lists[index]["Time"]+ " - "+lists[index]["Time"]).data,
Text(lists[index]["Duration"]+ " H").data,
Text(lists[index]["Genre"]).data,
Text(lists[index]["Price"]).data,false));}else{return SizedBox.shrink(); };
});
}
return Container(
margin: const EdgeInsets.only(top: 300),
child:CircularProgressIndicator());
}),
Do something like this..
class HomePage extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
body: RefreshIndicator(
onRefresh: () async {
//write your code here to update the list*********
},
child: ListView.builder(
itemCount: 100,
itemBuilder: (BuildContext context, int index) {
return Text('Line $index');
}
)
),
);
}
}
You can try with below lines may be it will work for you
return RefreshIndicator(
color: Colors.blue,
onRefresh: () {
Navigator.pushReplacement(
context, MaterialPageRoute(builder: (_) => HomePage()));
},
child: ListView.builder(
....
));
** UPDATE THE QUESTION **
Now all work correctly !
I make my first backend that return to me all images in base64 string format inside a json format like that :
[
{
"base64Img":"/9j/4AAQSkZJRgABAQAASABIAAD/4QBMRXhpZgAATU0AKgAAAAgAAgESAAMAAAABAAEAAIdpAAQAAAABAAAAJgAAAAAAAqACAAQAAAABAAAAyKADAAQAAAABAAAAlgAAAAD/7QA4UGhvdG9zaG9wIDMuMAA4QklNBAQAAAAAAAA4QklNBCUAAAAA....."
}]
I take this pointing to this path : 192.168.1.20:8888/myserver/immagini/onserver/mydevicename/{name of the img}
On my pc where backend run i have several images and i want to return all of this.
Now in flutter i create a bloc :
class ImmagineBloc {
Repository _repository = Repository();
Observable <List<ImmagineCompleta>> get immagini => _immagini.stream;
** UPDATE WORKING MODE **
getImmagini(String deviceName, String immagineName) async {
List<ImmagineCompleta> Immagini = await _repository.getImmagini(deviceName, immagineName);
return Immagini;
}
I want to read the stream of every request, create the image from base 64 string ( try with one request of one image and it work, image display correctly), so create this image and put inside the list of widget for make it visible inside a grid :
** UPDATE WORKING MODE **
#override
Widget build(BuildContext context) {
return GridView.builder(
itemCount: nameOnServer.length,
gridDelegate:
SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 3),
itemBuilder: (BuildContext context, int index) {
return FutureBuilder(
future: _immagineBloc.getImmagini(
_deviceName, nameOnServer[index]),
builder: (context, snapshotData) {
return Container(
height: 200,
width: 200,
child: Image.memory(
base64Decode(snapshotData.data[0].base64img),
fit: BoxFit.cover,
));
});
}
);
}
}
How can i do that ? Read every stream before do another request and save image create from base 64 string inside a list of widget .
Inside _mediaList i wanna store all the images create from base64 conversion.
My code might not perfect, but I think this is what you want to achieve.
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Example"),
automaticallyImplyLeading: false,
),
body: GridView.builder(
itemCount: nameOnServer.length,
gridDelegate:
SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 3),
itemBuilder: (BuildContext context, int index) {
return FutureBuilder(
future: _immagineBloc.getImmagini(
_deviceName, nameOnServer[index]),
builder: (context, snapshotData) {
return Container(
height: 200,
width: 200,
child: Image.memory(
base64Decode(snapshotData.data[0].base64img),
fit: BoxFit.cover,
));
});
}));
}
Edit
The correct answer as below:
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Example"),
automaticallyImplyLeading: false,
),
body: GridView.builder(
itemCount: nameOnServer.length,
gridDelegate:
SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 3),
itemBuilder: (BuildContext context, int index) {
return FutureBuilder(
future: _immagineBloc.getImmagini(
_deviceName, nameOnServer[index]),
builder: (context, snapshotData) {
return Container(
height: 200,
width: 200,
child: Image.memory(
base64Decode(snapshotData.data[0].base64img),
fit: BoxFit.cover,
));
});
}));
}
You may use single StreamBuilder which listen the stream Stream<<List<Uint8List>> which is accumulated in bloc. Below scratch code.
bloc.dart
class Bloc {
final imageController =
StreamController<List<Uint8List>>.broadcast();
Stream<List<Uint8List>> get images => imageController.stream;
// Here you get your all images in loop
void getImages() async {
final imageList = <Uint8List>[];
for (int i = 0; i < nameOnServer.length; i++) {
final imageBase64 = await getImage(...);
final imageDecoded = base64decode(imageBase64);
// Decode image and accumulate in list
imageList.add(imageDecoded);
// which sent to sink
imageController.add(imageList);
}
}
widget.dart
final bloc = Bloc();
#override
void iniState() {
super.initState();
bloc.getImages();
}
#override
Widget build(BuildContext context) {
// Build `GridView` basis on stream.
// As list contains all images so they will displayed
// one by one
return StreamBuilder<List<Uint8List>>(
stream: bloc.images;
builder: (context, snapshot) {
// check error
if (!snapshot.hasData) {
return CircularProgressIndicator();
}
final images = snapshot.data;
return GridView.builder(
itemCount: images.length,
itemBuilder: (_, index) {
return ImageMemory(images[index]);
}
);
},
);
}
I'm trying to load data from Firestore to my flutter app , but I'm stuck in ' loading... ' text , I feel I'm missing something !
Here is the code :
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: kMainColor,
body: StreamBuilder<QuerySnapshot>(
stream:FirebaseFirestore.instance.collection(kProductsCollection).snapshots(),
builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {
if (snapshot.hasData) {
List<Product> products = [];
for (var doc in snapshot.data.docs) {
var data = doc.data();
products.add(Product(
pPrice: data[kProductName],
pName: data[kProductPrice],
pDescription: data[kProductDescription],
pImage: data[kProductImage],
pCategory: data[kProductCategory]));
}
return GridView.builder(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
childAspectRatio: .8,
),
itemBuilder: (context, index) => Text(products[index].pName),
itemCount: products.length,
);
}
else {
// I'm stuck in here
return Center(child: Text('Loading...'));
}
},
),
);
}
I'm trying to make a ListView that auto-scrolls to the newest data point.
I tired to do this by making a _scrollToBottom function that uses the .jumpTo method.
But i get a blank screen in the app, and
'child.parentData != null': is not true. in the debug console.
Any suggestions on how i can implement auto-scrolling?
Here is the relevant portions of my current code:
ScrollController _scrollController = ScrollController();
_scrollToBottom(){ _scrollController.jumpTo(_scrollController.position.maxScrollExtent);
}
#override
Widget build(BuildContext context) {
return StreamBuilder(
stream: DataShareWidget.of(context).stream,
builder: (BuildContext context, AsyncSnapshot snapshot){
if(snapshot.hasError){ return Text(snapshot.error);}
if(snapshot.hasData){
_dataFormat(snapshot.data);
return ListView.builder(
itemCount: _listViewData.length,
controller: _scrollController,
reverse: true,
shrinkWrap: true,
itemBuilder: (context, index) {
_scrollToBottom();
return ListTile(
title: AutoSizeText(_listViewData[index], maxLines: 2),
dense: true,
);
},
);
}
}
);
}
What you need is to call _scrollToBottom() method once the list is built fully.
Modification is your code (without StreamBuilder):
ScrollController _scrollController = ScrollController();
_scrollToBottom() {
_scrollController.jumpTo(_scrollController.position.maxScrollExtent);
}
#override
void initState() {
super.initState();
}
#override
Widget build(BuildContext context) {
WidgetsBinding.instance.addPostFrameCallback((_) => _scrollToBottom());
return Scaffold(
body: ListView.builder(
itemCount: 50,
// itemCount: _listViewData.length,
controller: _scrollController,
reverse: true,
shrinkWrap: true,
itemBuilder: (context, index) {
return ListTile(
title: Text('Yo Dummy Text $index'),
// title: AutoSizeText(_listViewData[index], maxLines: 2),
dense: true,
);
},
),
);
}
You need to do this and work perfectly....
ScrollController _scrollController = ScrollController();
#override
Widget build(BuildContext context) {
_scrollController.animateTo(_scrollController.position.maxScrollExtent, duration: Duration(milliseconds: 200), curve: Curves.easeOut);
return StreamBuilder(
stream: stream = Firestore.instance
.collection('your collaction')
.document('your document')
.snapshots(),
builder: (context, snapshot) {
return snapshot.hasData
? ListView.builder(
controller: _scrollController,
shrinkWrap: true,
itemCount: snapshot.data.documents.length,
itemBuilder: (context, index) =>
msgTile(snapshot.data.documents[index], user1),
)
: Text('Loading...');
},
);
}
The problem is in your StreamBuilder code. If the snapshot isn't ready you need to return something.
Try this code:
ScrollController _scrollController = ScrollController();
_scrollToBottom(){ _scrollController.jumpTo(_scrollController.position.maxScrollExtent);
}
#override
Widget build(BuildContext context) {
return StreamBuilder(
stream: DataShareWidget.of(context).stream,
builder: (BuildContext context, AsyncSnapshot snapshot){
if(snapshot.hasError){ return Text(snapshot.error);}
if(snapshot.hasData){
_dataFormat(snapshot.data);
return ListView.builder(
itemCount: _listViewData.length,
controller: _scrollController,
reverse: true,
shrinkWrap: true,
itemBuilder: (context, index) {
_scrollToBottom();
return ListTile(
title: AutoSizeText(_listViewData[index], maxLines: 2),
dense: true,
);
},
);
}
//Something waiting the snapshot
return CircularProgressIndicator();
}
);
}