The render frames goes crazy with multiple image in scroll - flutter

Hello I was trying to do something like the Instagram Stories, but when I use more than 6 pictures the Flutter Performance of Android Studio goes crazy, also my Pc. And I was wondering if there is something to prevent it.
Main Widget
class Story extends StatelessWidget {
#override
Widget build(BuildContext context) {
return SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: Row(
children: <Widget>[
AddStory(),
PeopleStories(),
],
),
);
}
}
Second Widget
class PeopleStories extends StatelessWidget {
final List<String> storiesPic = [
'https://images.unsplash.com/photo-1536896407451-6e3dd976edd1?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1234&q=80',
'https://images.unsplash.com/photo-1553457055-88e354f1257c?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1234&q=80',
'https://images.unsplash.com/photo-1545064189-2d901f702a28?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1234&q=80',
'https://images.unsplash.com/photo-1501943416256-08140ba03763?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1436&q=80',
'https://images.unsplash.com/photo-1572151510493-38eb612d23be?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1268&q=80',
'https://images.unsplash.com/photo-1548536154-b47a70d27d8e?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1234&q=80',
// 'https://images.unsplash.com/photo-1582129617595-c657a072c9b9?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=3662&q=80',
// 'https://images.unsplash.com/photo-1559870904-406aeea0a89c?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=934&q=80'
];
#override
Widget build(BuildContext context) {
return Row(
children: _buildStoriesList(),
);
}
List<StoryDesign> _buildStoriesList() {
List<StoryDesign> widgets = [];
int i = 0;
storiesPic.forEach((pic) {
++i;
widgets.add(StoryDesign(pic));
});
return widgets;
}
}
Design of the widget, if there is something it could do the multiple rendering.
class StoryDesign extends StatelessWidget {
StoryDesign(this.profilePic);
final String profilePic;
#override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.only(
left: kMediumSeparation / 2,
top: kCommonSeparation,
right: kMediumSeparation / 2,
bottom: kHugeSeparation),
child: InkWell(
onTap: () => print('profile bubble tapped'),
borderRadius: BorderRadius.all(Radius.circular(35.0)),
child: CircleAvatar(
backgroundImage: NetworkImage(profilePic),
radius: 35.0,
backgroundColor: kDefaultColorLoading,
),
),
);
}
}

I think the most probable reason could be the big size of your images.
Also use CachedNetworkImage to load your images faster.

I think it is because of one the image is to big, this one https://images.unsplash.com/photo-1582129617595-c657a072c9b9?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=3662&q=80

Related

how to achieve a functionality like linear loading bar which will load up as user move between various screens

I am using android studio and flutter. I want to build the screen as shown below in the image:screen Image
let's say I have 4 screens. on the first screen, the bar will load up to 25%. the user will move to next screen by clicking on continue, the linearbar will load up to 50% and so on. the user will get back to previous screens by clicking on the back button in the appbar.
I tried stepper but it doesn't serve my purpose.
You can use the widget LinearProgressIndicator(value: 0.25,) for the first screen and with value: 0.5 for the second screen etc.
If you want to change the bar value within a screen, just use StatefullWidget's setState(), or any state management approaches will do.
import 'package:flutter/material.dart';
class ProgressPage extends StatefulWidget {
const ProgressPage({super.key});
#override
State<ProgressPage> createState() => _ProgressPageState();
}
class _ProgressPageState extends State<ProgressPage> {
final _pageController = PageController();
final _pageCount = 3;
int? _currentPage;
double? _screenWidth;
double? _unit;
double? _progress;
#override
void initState() {
super.initState();
_pageController.addListener(() {
_currentPage = _pageController.page?.round();
setState(() {
_progress = (_currentPage! + 1) * _unit!;
});
});
}
#override
void didChangeDependencies() {
super.didChangeDependencies();
_screenWidth = MediaQuery.of(context).size.width;
_unit = _screenWidth! / _pageCount;
_progress ??= _unit;
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('HOZEROGOLD')),
body: Column(
children: [
Align(
alignment: Alignment.topLeft,
child: Container(
color: Colors.yellow,
height: 10,
width: _progress,
),
),
Expanded(
child: PageView(
controller: _pageController,
children: _createPage(),
),
),
],
),
);
}
List<Widget> _createPage() {
return List<Widget>.generate(
_pageCount,
(index) => Container(
color: Colors.white,
child: Center(
child: ElevatedButton(
onPressed: () => _moveNextPage(),
child: Text('NEXT $index'),
),
),
),
);
}
void _moveNextPage() {
if (_pageController.page!.round() == _pageCount-1) {
_pageController.jumpToPage(0);
} else {
_pageController.nextPage(
curve: Curves.bounceIn,
duration: const Duration(milliseconds: 100));
}
}
}
HAPPY CODING! I hope it will be of help.

flutter, How to judge whether another widget is in the tree

Actually, I have a parent widget, and It has some of the child widgets in its Column.
like this
Container(
width: double.infinity,
color: Colors.white,
padding: EdgeInsets.fromLTRB(20.0, 50.0, 20.0, 0.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Title(),
SizedBox(height: 80.0,),
confirmLoginType(),
SizedBox(height: 10.0),
LoginButton(),
PolicyTips(
key: IndexGlobalKey.policyTipsKey,
updateState: receiveMessageUpdateState
),
Bottom()
],
),
),
in the PolicyTips, I pass a key to it, and I want to get the key in the LoginButton , but It has always been null when I get currentState.
The code is below:LoginButton
class LoginButton extends StatefulWidget {
LoginButton({Key key}) : super(key: key);
#override
_LoginButtonState createState() => _LoginButtonState();
}
class _LoginButtonState extends State<LoginButton> {
#override
Widget build(BuildContext context) {
policyTipsKey = IndexGlobalKey.policyTipsKey.currentState;
return Container(
child: Text()
)
}
}
what can I do? help me please, thanks.
This is IndexGlobalKey code.
class IndexGlobalKey {
static final GlobalKey<_PolicyTipsState> policyTipsKey = GlobalKey<_PolicyTipsState>();
static GlobalKey<_FormState> phoneLoginKey = GlobalKey<_FormState>();
static GlobalKey<_FormForIdCardLoginState> idCardLoginKey = GlobalKey<_FormForIdCardLoginState>();
}
Build method of _LoginButtonState runs before PolicyTips renders and before IndexGlobalKey.policyTipsKey is actually set. The reason is LoginButton goes before PolicyTips in column. Thats why you get null when you call IndexGlobalKey.policyTipsKey.currentState from build of _LoginButtonState.
To solve this you need to call IndexGlobalKey.policyTipsKey.state right where you use it. For example, when you need to get policy tips state on button tap just use it inside onPressed callback:
class _LoginButtonState extends State<LoginButton> {
#override
Widget build(BuildContext context) {
// An example of your button
return TextButton(
onPressed: () {
final policyTipsState = IndexGlobalKey.policyTipsKey.currentState;
// Here you can use policyTipsState
},
child: Text('button'),
);
}
}

How to expand a widget in ListView ontap?

I have created a ListView with container boxes as widgets. I want a specific container to expand onTap upto a specific screen height and width. I need help in implementing this in flutter. I have made a prototype on AdobeXD.
AdobeXD Prototype GIF
I am new to flutter, any kind of help is appreciated.
A flutter plugin called flutter swiper might help you achieve what you want to achieve.
Visit this pub dev and you can read documentation.
Here you go brother, Although its not blurring the background but I think it will get you going.
It's working something like this:
Below the code which you can copy paste. I have added comments in the code for understanding it in better way. Cheers :)
import 'package:flutter/material.dart';
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: HomeApp(),
);
}
}
class HomeApp extends StatefulWidget {
#override
_HomeAppState createState() => _HomeAppState();
}
class _HomeAppState extends State<HomeApp> {
// Items in the list --> Custom Widgets
List<Widget> arr = [
ListContainerHere(),
ListContainerHere(),
ListContainerHere(),
ListContainerHere(),
ListContainerHere(),
ListContainerHere(),
];
Widget getListWidget(List<Widget> items) {
List<Widget> list = new List<Widget>();
for (var i = 0; i <= items.length; i++) {
list.add(new ListContainerHere(
index: i,
));
}
return Row(children: list);
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Flutter App :)"),
),
body: Center(
// Using a 'Row' as Horizontal ListView
child: SingleChildScrollView(
scrollDirection: Axis.horizontal, child: getListWidget(arr)),
),
);
}
}
// Widgets that will be rendered in the Horizontal Row
class ListContainerHere extends StatefulWidget {
final int index;
ListContainerHere({this.index});
#override
_ListContainerHereState createState() => _ListContainerHereState();
}
class _ListContainerHereState extends State<ListContainerHere> {
// Varibale to change the height and width accordingly
// Initally no item will be expanded
bool isExpanded = false;
#override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.all(8.0),
child: GestureDetector(
onTap: () {
// Changing the value of 'isExpanded' when an item is tapped in the List
setState(() {
isExpanded = !isExpanded;
});
},
// AnimatedContainer for slowing down the changing
child: AnimatedContainer(
duration: Duration(milliseconds: 150),
// Changing the width and height
height: isExpanded ? 250 : 150,
width: isExpanded ? 250 : 150,
// Decoration Portion of the Container
decoration: BoxDecoration(
color: Colors.blue, borderRadius: BorderRadius.circular(15.0)),
),
),
);
}
}

Calling a function after Widget build(BuildContext context)

I am into flutter to port my android app from java. One thing that is evident in flutter is widgets. Now my biggest obstacle to make my app work as it was on android is starting an async task to request data from the server. I have a custom progress dialog that can be shown or hidden.
class MySelection extends StatefulWidget {
#override
State<StatefulWidget> createState() {
return MySelectionState();
}
}
class MySelectionState extends State<MySelection> {
final globalKey = new GlobalKey<ScaffoldState>();
ProgressDialog progressDialog = ProgressDialog.getProgressDialog("Loading books ...");
List<Book> books;
void requestData() async {
EventObject eventObject = await getBooks();
books = eventObject.object;
populateData();
}
#override
Widget build(BuildContext context) {
if (books == null) {
books = List<Book>();
requestData();
}
var appBar = AppBar();
return Scaffold(
appBar: AppBar(
title: Text('Set up your Collection'),
actions: <Widget>[
IconButton(
icon: Icon(Icons.refresh),
onPressed: () {
books = List<Book>();
requestData();
},
),
],
),
body: SingleChildScrollView(
child: Stack(
Container(
height: (MediaQuery.of(context).size.height - (appBar.preferredSize.height * 2)),
padding: const EdgeInsets.symmetric(horizontal: 10),
margin: EdgeInsets.only(top: 50.0),
child: ListView.builder(
physics: BouncingScrollPhysics(),
itemCount: books.length,
itemBuilder: bookListView,
),
),
Container(
height: (MediaQuery.of(context).size.height),
padding: const EdgeInsets.symmetric(horizontal: 10),
child: progressDialog,
),
],
),
),
}
}
Now, this code works well when I don't call the progress dialog unlike when I try to do that by calling my progressdialog widget.
if (books == null) {
progressDialog.showProgress();
books = List<Book>();
requestData();
}
It throws the error that
The method 'showProgress' was called on null. Receiver: null Tried
calling: showProgress()
Of course, the reason is that I am calling this before its widget is even created. Now my question is how can I do this because I can't afford to put a button for the user to click. I just want this to work on its own once the user is on this particular screen.
import 'package:flutter/scheduler.dart';
#override
void initState() {
super.initState();
SchedulerBinding.instance.addPostFrameCallback((timeStamp) {
// add your code which you want to execute after your build is complete
});
}
Thanks.

Is possible to make Multiple flutter pages in one app?

I went to convert book to android app the book has 100 page ,
should I create page(activity) for each page ? or any other ways to do this?
You can use PageView or its builder constructor for this, here is the basic example
PageView.builder(
itemCount: 100,
itemBuilder: (_, index) => YourPage(list[index]),
)
Update:
Create two widgets like this.
// It only shows Text
class TextPage extends StatelessWidget {
final String text;
const TextPage({#required this.text});
#override
Widget build(BuildContext context) {
return Text(text, style: TextStyle(fontSize: 20));
}
}
// It only shows Image from assets
class ImagePage extends StatelessWidget {
final String image;
const ImagePage({#required this.image});
#override
Widget build(BuildContext context) {
return Image.asset(image);
}
}
Now in your main class, use them as
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: PageView(
children: <Widget>[
TextPage(text: "This screen only has text"), // 1st screen only text
ImagePage(image: "assets/images/chocolate_pic.png"), // 2nd screen only image
Column( // 3rd screen will have both
children: <Widget>[
TextPage(text: "This is the text followed by an image"),
ImagePage(image: "assets/images/chocolate_pic.png"),
],
),
],
),
);
}