I need to display categories in a scroll with 3X3 in grid view and it was working fine and slide also working fine but i cant able to achieve the dots for the scrolling .. I need like carousal . Is it possible to add dots with list view
SingleChildScrollView(
child: GridView.count(
physics: ScrollPhysics(),
padding: EdgeInsets.fromLTRB(16, 16, 16, 0),
primary: false,
childAspectRatio: 1.1,
shrinkWrap: true,
crossAxisSpacing: 0,
mainAxisSpacing: 0,
crossAxisCount: 4,
// mainAxisCount:2,
//scrollDirection: Axis.horizontal,
children: List.generate(categoryData.length, (index) {
return GestureDetector(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => ProductCategoryPage(
categoryId: categoryData[index].id,
categoryName:
categoryData[index].name)));
},
child: Column(children: [
buildCacheNetworkImage(
width: 40,
height: 40,
url: categoryData[index].image,
plColor: Colors.transparent),
Flexible(
child: Container(
margin: EdgeInsets.fromLTRB(0, 10, 0, 0),
child: Text(
categoryData[index].name,
style: TextStyle(
color: CHARCOAL,
fontWeight: FontWeight.normal,
fontSize: 12,
),
textAlign: TextAlign.center,
),
),
)
]));
}),
),
)
I need to get the scrolling dots in the list view so how to achieve that
You should implement below way
Code :
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
List<String> list = [];
int perPageItem = 16;
int pageCount;
int selectedIndex = 0;
int lastPageItemLength;
PageController pageController;
#override
void initState() {
pageController = PageController(initialPage: 0);
for (int i = 1; i <= 45; i++) {
list.add('$i');
}
var num = (list.length / perPageItem);
pageCount = num.isInt ? num.toInt() : num.toInt() + 1;
var reminder = list.length.remainder(perPageItem);
lastPageItemLength = reminder == 0 ? perPageItem : reminder;
super.initState();
}
#override
void dispose() {
pageController.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Column(
children: [
SizedBox(
height: 390,
child: PageView.builder(
controller: pageController,
itemCount: pageCount,
onPageChanged: (index) {
setState(() {
selectedIndex = index;
});
},
itemBuilder: (_, pageIndex) {
return GridView.count(
physics: NeverScrollableScrollPhysics(),
padding: const EdgeInsets.fromLTRB(16, 16, 16, 0),
primary: false,
childAspectRatio: 1.1,
shrinkWrap: true,
crossAxisSpacing: 0,
mainAxisSpacing: 0,
crossAxisCount: 4,
children: List.generate(
(pageCount - 1) != pageIndex
? perPageItem
: lastPageItemLength, (index) {
return GestureDetector(
onTap: () {},
child: Container(
width: 50,
height: 50,
margin: const EdgeInsets.all(5),
color: Colors.amber,
alignment: Alignment.center,
child: Text(
list[index + (pageIndex * perPageItem)],
style: TextStyle(color: Colors.black, fontSize: 20),
),
),
);
}),
);
}),
),
SizedBox(
height: 15,
child: ListView.builder(
shrinkWrap: true,
scrollDirection: Axis.horizontal,
itemCount: pageCount,
itemBuilder: (_, index) {
return GestureDetector(
onTap: () {
pageController.animateToPage(index, duration: Duration(milliseconds: 500), curve: Curves.easeInOut);
},
child: AnimatedContainer(
duration: Duration(milliseconds: 100),
decoration: BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(10)),
color: Colors.red
.withOpacity(selectedIndex == index ? 1 : 0.5)),
margin: EdgeInsets.all(5),
width: 10,
height: 10,
),
);
},
),
),
],
),
);
}
}
extension NumExtensions on num {
bool get isInt => (this % 1) == 0;
}
Output :
Related
my ImagePaths function is supposed to return a list and I want to access that list in my Carousel but I can't seem to figure out how to do so.. The ".lenght" and the [index] are not working and I'm not sur how to "call" them in flutter. Can someone help me please :)
here is my code for the ImagePaths function :
Future<List<String>> getImagePaths() async { final Map<String, dynamic> assets = jsonDecode(await rootBundle.loadString('AssetManifest.json')); return assets.keys .where((String key) => key.contains('photos/')) .where((String key) => key.contains('.JPG')) .toList(); }
And here is my code for my carousel :
class MyWidget extends StatefulWidget {
const MyWidget({super.key});
#override
State<MyWidget> createState() => _MyWidgetState();
}
class _MyWidgetState extends State<MyWidget> {
int activeIndex = 0;
final controller = CarouselController();
final imgList = ImagePaths();
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text("carousel try"),
centerTitle: true,
),
body: Center(
child: Column(
children: [
const SizedBox(
height: 32,
),
CarouselSlider.builder(
carouselController: controller,
options: CarouselOptions(
height: 500,
enlargeCenterPage: true,
onPageChanged: (index, reason) {
setState(() {
activeIndex = index;
});
}),
itemCount: imgList.length,
itemBuilder: (context, index, realIndex) {
final urlImage = imgList[index];
return buildImage(urlImage, index);
},
),
const SizedBox(
height: 32,
),
buildButtons()
],
),
),
);
}
Widget buildImage(String urlImage, int index) {
return Container(
margin: const EdgeInsets.symmetric(horizontal: 12),
color: Colors.grey,
child: Image.network(
urlImage,
fit: BoxFit.cover,
),
);
}
Widget buildButtons({bool stretch = false}) {
return Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
ElevatedButton(
style: ElevatedButton.styleFrom(
padding: const EdgeInsets.symmetric(horizontal: 32, vertical: 12),
),
onPressed: () {
controller.previousPage(
duration: const Duration(milliseconds: 500));
},
child: const Icon(Icons.arrow_back, size: 32),
),
stretch
? const Spacer()
: const SizedBox(
width: 32,
),
ElevatedButton(
style: ElevatedButton.styleFrom(
padding: const EdgeInsets.symmetric(horizontal: 32, vertical: 12),
),
onPressed: () {
controller.nextPage(duration: const Duration(milliseconds: 500));
},
child: const Icon(Icons.arrow_forward, size: 32),
),
stretch
? const Spacer()
: const SizedBox(
width: 32,
),
],
);
}
}
I am using smooth_page_indicator, but the Animated smooth indicator is not responding, I am pretty sure i am missing something here. i have a feeling it has something to do with how i created my list. in the application, however, the switcher shows that i have 3 main items. but still, as always, assistance would be really appreciated.
class ExploreCollections extends StatefulWidget {
const ExploreCollections({Key? key}) : super(key: key);
#override
State<ExploreCollections> createState() => _ExploreCollectionsState();
}
class _ExploreCollectionsState extends State<ExploreCollections> {
int _activeIndex = 0;
final List<Widget> _images = [
Stack(
children: [
Image.asset('assets/images/image 10.png'),
Padding(
padding: const EdgeInsets.only(left: 55.0, top: 230),
child: Text(
'Luxury \n Fashion \n &Accessories'.toUpperCase(),
style: TextStyle(
fontFamily: 'Bodoni',
fontSize: 40,
fontWeight: FontWeight.w500,
color: Colors.grey.shade700
),
),
),
Padding(
padding: const EdgeInsets.only(top: 250.0),
child: Center(
child:SvgPicture.asset('assets/iconImages/Button.svg') ,
),
),
],
),
Stack(
children: [
Image.asset('assets/images/leeloo.jpeg'),
],
),
Stack(
children: [
Image.asset('assets/images/ayaka.jpeg'),
],
),
];
#override
Widget build(BuildContext context) {
return SingleChildScrollView(
child: Stack(
children: [
CarouselSlider.builder(
options: CarouselOptions(
viewportFraction: 1,
aspectRatio: 1.8,
height: MediaQuery.of(context).size.height,
autoPlay: false,
initialPage: 0,
enableInfiniteScroll: false,
enlargeCenterPage: true,
onPageChanged: (index, reason){
_activeIndex = index;
}
),
itemCount: _images.length,
itemBuilder: (BuildContext context, int index, int realIndex) {
return _images[index];
},
),
Center(
child: buildIndicator(),
),
],
),
);
}
Widget buildIndicator(){
return AnimatedSmoothIndicator(
activeIndex: _activeIndex,
count: _images.length
);
}
}
Call setState to update the UI
onPageChanged: (index, reason) {
_activeIndex = index;
setState(() {});
}),
Constitution Card stuck at its position after performing search instead of moving to the top first position in the gridview. The searched card is supposed to appear at the the index[0] of the gridview where "Test Constitution" when filtered after performing search .
Could post images because of low reputution from Stackoverflow
Before Search
After Search
This's the code.
class _HomePageState extends State<HomePage> {
final ConstitutionController constitutionController = Get.find();
String search = "";
#override
Widget build(BuildContext context) {
final double height = MediaQuery.of(context).size.height;
return Scaffold(
appBar: AppBar(
backgroundColor: const Color(0xFF0B3C5D),
elevation: 0.0,
),
drawer: DrawerWidget(),
body: Stack(children: [
Container(
),
),
SafeArea(
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 20),
child: Column(
children: [
Text(),
),
// The Search bar
Container(
margin: const EdgeInsets.symmetric(vertical: 30),
padding:
const EdgeInsets.symmetric(horizontal: 20, vertical: 8),
child: CupertinoSearchTextField(
onChanged: ((value) {
setState(() {
search = value;
}
);
}),
autofocus: true,
itemColor: Colors.black,
itemSize: 20,
backgroundColor: const Color.fromARGB(255, 185, 204, 218),
placeholderStyle: const TextStyle(
color: Colors.black,
fontSize: 18,
),
),
),
const SizedBox(
height: 70,
),
Flexible(
child: Obx(() {
if (constitutionController.isLoading.value) {
return GridView.builder(
itemBuilder: (_, __) {
return Shimmer.fromColors(
baseColor: Colors.grey[300]!,
highlightColor: Colors.grey[100]!,
period: Duration(seconds: 2),
enabled: constitutionController.isLoading.value,
child: ShimmerGridCard());
},
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2),
);
} else {
return GridView.builder(
itemCount:
constitutionController.constitutionList.length,
gridDelegate:
SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2),
itemBuilder: (context, index) {
Constitution constitution =
constitutionController.constitutionList[index];
if (search.isEmpty) {
return InkWell(
onTap: (() {
Get.to(BranchPage(
constitutionId: constitution));
}),
child: ConstitutionCard(constitutionController
.constitutionList[index]));
}
if (constitution.title
.toLowerCase()
.contains(search)) {
return InkWell(
onTap: (() {
Get.to(BranchPage(
constitutionId: constitution));
}),
child: ConstitutionCard(constitutionController
.constitutionList[index]));
}
return null;
});
}
}),
),
],
),
),
),
]),
);
}
}
I'm getting a problem with my TabBar I want it to be scrollable (swipe left and right by gesture).
But it's not working, I have to click on the sub category name to view it but I want it to scroll right to go to the next sub category.
I set isScrollable: true, in the TabBar widget but still the same problem.
If there is any suggestion I'm here thank you :)
1st screen
2nd screen
class CategoryScreen extends StatefulWidget {
final CategoryModel categoryModel;
CategoryScreen({#required this.categoryModel});
#override
_CategoryScreenState createState() => _CategoryScreenState();
}
class _CategoryScreenState extends State<CategoryScreen>
with TickerProviderStateMixin {
int _tabIndex = 0;
#override
void initState() {
super.initState();
Provider.of<CategoryProvider>(context, listen: false)
.getSubCategoryList(context, widget.categoryModel.id.toString());
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: ResponsiveHelper.isDesktop(context)
? PreferredSize(
child: MainAppBar(), preferredSize: Size.fromHeight(80))
: null,
body: Consumer<CategoryProvider>(
builder: (context, category, child) {
return category.subCategoryList != null
? Center(
child: Scrollbar(
child: Container(
width: 1170,
child: CustomScrollView(
physics: BouncingScrollPhysics(),
slivers: [
SliverAppBar(
expandedHeight: 200,
toolbarHeight:
50 + MediaQuery.of(context).padding.top,
pinned: true,
floating: false,
backgroundColor: Theme.of(context).primaryColor,
leading: IconButton(
icon: Icon(Icons.chevron_left,
color: ColorResources.COLOR_WHITE),
onPressed: () => Navigator.pop(context)),
flexibleSpace: FlexibleSpaceBar(
title: Text(widget.categoryModel.name,
style: rubikMedium.copyWith(
fontSize: Dimensions.FONT_SIZE_LARGE,
color: Colors.white)),
titlePadding: EdgeInsets.only(
bottom: 54 +
(MediaQuery.of(context).padding.top / 2),
left: 50,
right: 50,
),
background: Container(
margin: EdgeInsets.only(bottom: 50),
child: FadeInImage.assetNetwork(
placeholder: Images.placeholder_rectangle,
image:
'${Provider.of<SplashProvider>(context, listen: false).baseUrls.categoryImageUrl}/${widget.categoryModel.image}',
fit: BoxFit.cover,
),
),
),
bottom: PreferredSize(
preferredSize: Size.fromHeight(30.0),
child: Container(
width: MediaQuery.of(context).size.width,
color: Theme.of(context).accentColor,
**child: TabBar(
controller: TabController(
initialIndex: _tabIndex,
length:
category.subCategoryList.length + 1,
vsync: this),
isScrollable: true,
unselectedLabelColor:
ColorResources.getGreyColor(context),
indicatorWeight: 3,
indicatorSize: TabBarIndicatorSize.label,
indicatorColor:
Theme.of(context).primaryColor,
labelColor: Theme.of(context)
.textTheme
.bodyText1
.color,
tabs: _tabs(category),
onTap: (int index) {
_tabIndex = index;
if (index == 0) {
category.getCategoryProductList(context,
widget.categoryModel.id.toString());
} else {
category.getCategoryProductList(
context,
category.subCategoryList[index - 1].id
.toString());
}
},
),
),
),
),**
SliverToBoxAdapter(
child: category.categoryProductList != null
? category.categoryProductList.length > 0
? GridView.builder(
gridDelegate:
SliverGridDelegateWithFixedCrossAxisCount(
crossAxisSpacing: 5,
mainAxisSpacing: 5,
childAspectRatio: 4,
crossAxisCount: ResponsiveHelper
.isDesktop(context)
? 3
: ResponsiveHelper.isTab(
context)
? 2
: 1),
itemCount:
category.categoryProductList.length,
shrinkWrap: true,
physics: NeverScrollableScrollPhysics(),
padding: EdgeInsets.all(
Dimensions.PADDING_SIZE_SMALL),
itemBuilder: (context, index) {
return ProductWidget(
product: category
.categoryProductList[index]);
},
)
: NoDataScreen()
: GridView.builder(
shrinkWrap: true,
itemCount: 10,
physics: NeverScrollableScrollPhysics(),
padding: EdgeInsets.all(
Dimensions.PADDING_SIZE_SMALL),
gridDelegate:
SliverGridDelegateWithFixedCrossAxisCount(
crossAxisSpacing: 5,
mainAxisSpacing: 5,
childAspectRatio: 4,
crossAxisCount:
ResponsiveHelper.isDesktop(context)
? 3
: ResponsiveHelper.isTab(context)
? 2
: 1,
),
itemBuilder: (context, index) {
return ProductShimmer(
isEnabled:
category.categoryProductList ==
null);
},
),
),
],
),
),
),
)
: Center(
child: CircularProgressIndicator(
valueColor: AlwaysStoppedAnimation<Color>(
Theme.of(context).primaryColor)));
},
),
);
}
List<Tab> _tabs(CategoryProvider category) {
List<Tab> tabList = [];
tabList.add(Tab(text: 'Tout'));
category.subCategoryList
.forEach((subCategory) => tabList.add(Tab(text: subCategory.name)));
return tabList;
}
}
You need to use a NestedScrollView to use a Sliver with a TabBar
import 'package:flutter/material.dart';
void main() {
runApp(
MaterialApp(
debugShowCheckedModeBanner: false,
theme: ThemeData.dark(),
home: SliverTabExample(),
),
);
}
class SliverTabExample extends StatefulWidget {
const SliverTabExample({Key? key}) : super(key: key);
#override
_SliverTabExampleState createState() => _SliverTabExampleState();
}
class _SliverTabExampleState extends State<SliverTabExample>
with SingleTickerProviderStateMixin {
final _tabs = List.generate(10, (index) => 'Tab#${index + 1}');
late final TabController _tabCont;
#override
void initState() {
_tabCont = TabController(length: 10, vsync: this);
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: NestedScrollView(
headerSliverBuilder: (_, __) {
return [
SliverAppBar(
expandedHeight: 200,
pinned: true,
floating: false,
title: Text('TabBar Example'),
centerTitle: true,
bottom: TabBar(
controller: _tabCont,
isScrollable: true,
tabs: [
..._tabs.map(
(label) => Tab(
child: Text(label),
),
),
],
),
),
];
},
body: TabBarView(
controller: _tabCont,
children: [
..._tabs.map(
(label) => SamplePage(
label: label,
),
),
],
),
),
);
}
}
class SamplePage extends StatelessWidget {
const SamplePage({Key? key, required this.label}) : super(key: key);
final String label;
#override
Widget build(BuildContext context) {
return Container(
child: Center(child: Text('Page of $label')),
);
}
}
I have a gridview.builder that fetches images from an API, images are already compressed to a max of 70kb each. I am also using pagination usin to fetch more data. When the grid crosses 30+ images the scrolling becomes choppy and when I go to a page by clicking on any image and then I come back many images load again everything again. I am maintaining the state using IndexedStack. And back animation is also stuttering. What am I doing wrong here?
Gridview Builder Code:
GridView.builder(
physics: NeverScrollableScrollPhysics(),
shrinkWrap: true,
itemCount: postsList.posts.length,
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3,
crossAxisSpacing: 3,
mainAxisSpacing: 3,
),
itemBuilder: (context, index) {
return ProfilePostImageCard(
length: postsList.posts.length,
post: postsList.posts[index],
stringOfPostID: stringOfPostID,
);
})
ProfilePostImageCard
class ProfilePostImageCard extends StatelessWidget {
final ProfilePostModel post;
final String stringOfPostID;
final int length;
ProfilePostImageCard({Key key, this.post, this.stringOfPostID, this.length}) : super(key: key);
#override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => ProfileFeedsPage(
currentMemberImage: CurrentUser().currentUser.image,
listOfPostID: stringOfPostID,
postID: post.postId,
logo: CurrentUser().currentUser.logo,
country: CurrentUser().currentUser.country,
memberID: CurrentUser().currentUser.memberID,
)));
},
child: Container(
child: Stack(
children: [
AspectRatio(
aspectRatio: 1,
child: CachedNetworkImage(
fit: BoxFit.cover,
imageUrl: post.postAllImage,
),
),
post.dataMultiImage == 1
? Positioned.fill(
child: Align(
alignment: Alignment.topRight,
child: Padding(
padding: EdgeInsets.all(6.0),
child: Image.asset(
"assets/images/multiple.png",
height: 2.5.h,
),
)),
)
: Container(),
post.postType == "Video" || post.postType == "svideo"
? Positioned.fill(
child: Align(
alignment: Alignment.topRight,
child: Padding(
padding: EdgeInsets.all(6.0),
child: Icon(
Icons.video_collection,
color: Colors.white,
size: 2.5.h,
))),
)
: Container(),
],
),
),
);
}
}
Full Code
SmartRefresher(
enablePullDown: true,
enablePullUp: selectedIndex == 1 ? false : true,
header: CustomHeader(
builder: (context, mode) {
return Container(
child: Center(child: loadingAnimation()),
);
},
),
footer: CustomFooter(
builder: (BuildContext context, LoadStatus mode) {
Widget body;
if (mode == LoadStatus.idle) {
body = Text("");
} else if (mode == LoadStatus.loading) {
body = loadingAnimation();
} else if (mode == LoadStatus.failed) {
body = Container(
decoration: new BoxDecoration(
shape: BoxShape.circle,
border: new Border.all(color: Colors.black, width: 0.7),
),
child: Padding(
padding: EdgeInsets.all(12.0),
child: Icon(CustomIcons.reload),
));
} else if (mode == LoadStatus.canLoading) {
body = Text("");
} else {
body = Text("No more Data");
}
return Container(
height: 55.0,
child: Center(child: body),
);
},
),
controller: _postRefreshController,
onRefresh: _onRefresh,
onLoading: () {
if (selectedIndex == 0) {
_onLoading();
} else {
print("blog");
}
},
child: ListView(
physics: AlwaysScrollableScrollPhysics(),
children: [
profileLoaded == true
? ProfileCard(
userImage: userImage,
totalPosts: totalPosts,
followers: followers,
following: following,
bio: bio,
name: name,
shortcode: shortcode,
list: list,
)
: Container(),
TabBar(
indicatorColor: Colors.black,
tabs: <Tab>[
Tab(
child: Text(
"Posts",
style: blackBold.copyWith(color: Colors.black, fontSize: 10.0.sp),
),
),
Tab(
child: Text(
"Blogs",
style: blackBold.copyWith(color: Colors.black, fontSize: 10.0.sp),
),
),
Tab(
child: Text(
"Channel",
style: blackBold.copyWith(color: Colors.black, fontSize: 10.0.sp),
),
),
],
controller: _tabController,
onTap: (int index) {
setState(() {
selectedIndex = index;
_tabController.animateTo(index);
});
},
),
IndexedStack(
children: <Widget>[
GestureDetector(
onHorizontalDragUpdate: (details) {
if (details.delta.dx < 0) {
setState(() {
_tabController.animateTo(1);
selectedIndex = 1;
});
} else if (details.delta.dx > 0) {
setState(() {
_tabController.animateTo(2);
selectedIndex = 2;
});
}
},
child: Visibility(
child: Container(
child: hasPosts == true
? GridView.builder(
physics: NeverScrollableScrollPhysics(),
shrinkWrap: true,
itemCount: postsList.posts.length,
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3,
crossAxisSpacing: 3,
mainAxisSpacing: 3,
),
itemBuilder: (context, index) {
return ProfilePostImageCard(
length: postsList.posts.length,
post: postsList.posts[index],
stringOfPostID: stringOfPostID,
);
})
: Container(),
),
maintainState: true,
visible: selectedIndex == 0,
),
),
GestureDetector(
onHorizontalDragUpdate: (details) {
if (details.delta.dx < 0) {
setState(() {
_tabController.animateTo(2);
selectedIndex = 2;
});
} else if (details.delta.dx > 0) {
setState(() {
_tabController.animateTo(0);
selectedIndex = 0;
});
}
},
child: Visibility(
child: Container(
child: hasPosts == true
? Column(
children: [
ListView.builder(
controller: widget.scrollController,
shrinkWrap: true,
//physics: NeverScrollableScrollPhysics(),
itemCount: blogsList.blogs.length,
itemBuilder: (context, index) {
var blog = blogsList.blogs[index];
return PersonalBlogCard(
blog: blog,
index: index,
lastIndex: blogsList.blogs.length - 1,
);
},
),
Padding(
padding: EdgeInsets.symmetric(vertical: 2.0.h),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
GestureDetector(
onTap: () {
if (currentPage > 1) {
setState(() {
hasBlogs = false;
currentPage = --currentPage;
});
getBlogs();
}
},
child: CircleAvatar(
radius: 3.0.h,
backgroundColor: primaryBlueColor,
child: Icon(
Icons.arrow_back_ios_outlined,
color: Colors.white,
)),
),
Text(
"Page " + currentPage.toString() + "/" + totalPages.toString(),
style: TextStyle(fontSize: 11.0.sp),
),
GestureDetector(
onTap: () {
if (currentPage < totalPages) {
setState(() {
hasBlogs = false;
currentPage = ++currentPage;
});
getBlogs();
}
},
child: CircleAvatar(
radius: 3.0.h,
backgroundColor: primaryBlueColor,
child: Icon(
Icons.arrow_forward_ios_outlined,
color: Colors.white,
)),
)
],
),
)
],
)
: Container(),
),
maintainState: true,
visible: selectedIndex == 1,
),
),
GestureDetector(
onHorizontalDragUpdate: (details) {
if (details.delta.dx < 0) {
setState(() {
_tabController.animateTo(0);
selectedIndex = 0;
});
} else if (details.delta.dx > 0) {
setState(() {
_tabController.animateTo(1);
selectedIndex = 1;
});
}
},
child: Visibility(
child: Container(
child: hasPosts == true
? StaggeredGridView.countBuilder(
addAutomaticKeepAlives: true,
physics: NeverScrollableScrollPhysics(),
shrinkWrap: true,
crossAxisCount: 3,
itemCount: postsList.posts.length,
mainAxisSpacing: 3,
crossAxisSpacing: 3,
itemBuilder: (context, index) {
return ProfilePostImageCard(
length: postsList.posts.length,
post: postsList.posts[index],
stringOfPostID: stringOfPostID,
);
},
staggeredTileBuilder: (index) {
return StaggeredTile.fit(1);
},
)
: Container(),
),
maintainState: true,
visible: selectedIndex == 2,
),
),
],
index: selectedIndex,
),
],
),
)
This is the solution. Evict the image from cache on dispose method and no more lag on screen transition.
class ProfilePostImageCard extends StatefulWidget {
const ProfilePostImageCard({Key key, this.url}) : super(key: key);
#override
State createState() => new _ProfilePostImageCardState();
}
class _ProfilePostImageCardState extends State<ProfilePostImageCard> {
#override
void dispose() {
// needs to match the url and scale from below
CachedNetworkImage.evictFromCache(widget.url);
}
#override
Widget build(BuildContext context) {
return AspectRatio(
aspectRatio: 1,
child: CachedNetworkImage(
fit: BoxFit.cover,
imageUrl: post.postAllImage,
),
),;
}
}