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(() {});
}),
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,
),
],
);
}
}
This question already has answers here:
Flutter: "RenderFlex children have non-zero flex but incoming height constraints are unbounded"
(8 answers)
Closed 23 days ago.
I want to have a GridView.builder inside another TabBar Widget of SingleChildScrollView and I got this error.
======== Exception caught by rendering library =====================================================
The following assertion was thrown during performLayout():
RenderFlex children have non-zero flex but incoming height constraints are unbounded.
I tried to put the GridView in a Container and give a specific height, it doesn't make an error but the Grid was cut off.
This is my SingleChildScrollView Widget code
import ...
class CommunityPage extends StatefulWidget {...}
class _CommunityPageState extends State<CommunityPage> {
ScrollController? sc;
bool check = false;
Future<void> _copyToClipboard() async {...}
#override
void initState() {...}
#override
void dispose() {...}
#override
Widget build(BuildContext context) {
return DefaultTabController(
length: 2,
child: Scaffold(
appBar: AppBar(
elevation: 0.0,
),
drawer: const SideBar(),
floatingActionButton: check
? FloatingActionButton.small(...)
: null,
floatingActionButtonAnimator: FloatingActionButtonAnimator.scaling,
floatingActionButtonLocation: FloatingActionButtonLocation.endFloat,
body: SafeArea(
child: ((this.sc == null) && !this.sc!.hasClients)
? const Center(...)
: SingleChildScrollView(
controller: this.sc!,
child: Container(
width: MediaQuery.of(context).size.width,
child: Column(
children: [
Container(...),
const SizedBox(height: largeSpace * 0.8),
Row(...),
const SizedBox(height: 20),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 65.0),
child: Container(
height: 43,
decoration: BoxDecoration(...),
child: Padding(
padding: const EdgeInsets.all(2.0),
child: TabBar(
indicator: BoxDecoration(),
labelColor: Colors.white,
unselectedLabelColor: Colors.black,
tabs: const [
Tab(
child: Text(
'EVENTS',
style: TextStyle(
fontSize: 15,
fontFamily: 'assets/fonts/LeferiBase',
),
),
),
Tab(
child: Text(
'MEMBERS',
style: TextStyle(
fontSize: 15,
fontFamily: 'assets/fonts/LeferiBase',
),
),
),
],
),
),
),
),
const SizedBox(height: 20),
const Expanded(
child: TabBarView(children: [
EventsScreen(),
MembersScreen(),
]),
),
],
),
),
),
),
),
);
}
}
And this is my GridView code
import ...
class EventsScreen extends StatefulWidget {
const EventsScreen({super.key});
#override
_EventsScreenState createState() {
return _EventsScreenState();
}
}
class _EventsScreenState extends State<EventsScreen> {
List<Nfts> nfts = [];
bool isLoading = true;
NftsProviders nftsProvider = NftsProviders();
Future initNfts() async {
nfts = await nftsProvider.getNfts();
}
#override
void initState() {
super.initState();
initNfts().then((_) {
setState(() {
isLoading = false;
});
});
}
#override
Widget build(BuildContext context) {
return isLoading
? const Center(
child: CircularProgressIndicator(),
)
: Padding(
padding: const EdgeInsets.symmetric(horizontal: 40),
child: GridView.builder(
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
itemCount: nfts.length,
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3),
itemBuilder: (context, index) {
return Padding(
padding: const EdgeInsets.all(5.0),
child: GestureDetector(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => const NFTDetailPage()),
);
},
child: CircleAvatar(
radius: 30,
backgroundImage: NetworkImage(nfts[index].meta_image),
),
),
);
},
),
);
}
}
You are using expanded inside SingleChildScrollView which is giving you error.
Try removing the expanded widget wrap from tabView.
Change this
Expanded(
child: TabBarView(children: [
EventsScreen(),
MembersScreen(),
]),
to
TabBarView(children: [
EventsScreen(),
MembersScreen(),
]
I am using AutoRoute with AutoTabsRouter for navigation in my web app. I have a custom Drawer used for navigation. I want my current tab icon and text to be the primary color when on the selected index.
For mobile and tablet view, the drawer pops with every selection and when I open it again the current tab has the primary color as it should. On desktop view this works if I open the app in desktop view and do not resize the screen at all. If I do resize the screen at all, even if I'm still in desktop view after resizing, the selected does not work as expected and the current tab does not have the primary color.
Here is my code for the Drawer :
class CustomDrawer extends StatefulWidget {
final double width;
const CustomDrawer({
required this.width,
Key? key,
}) : super(key: key);
#override
State<CustomDrawer> createState() => _CustomDrawerState();
}
class _CustomDrawerState extends State<CustomDrawer> {
ScrollController scrollController = ScrollController();
#override
void dispose() {
scrollController.dispose();
super.dispose();
}
#override
Widget build(context) {
final tabsRouter = context.tabsRouter;
return Drawer(
elevation: 0,
backgroundColor: lightThemeCardColor,
child: SingleChildScrollView(
controller: scrollController,
child: Column(
children: [
DrawerHeader(
child: Column(
children: const [
SizedBox(
height: defaultMargin,
),
Icon(
Icons.architecture,
color: lightPrimaryColor,
size: 50,
),
Text(
'Drawer Header',
style: TextStyle(
fontSize: mobileTitleTextSize,
fontWeight: FontWeight.bold,
),
),
],
),
),
ListTile(
leading: const Icon(Icons.home),
title: const Text('H O M E'),
selected: tabsRouter.activeIndex == 0,
selectedColor: lightPrimaryColor,
onTap: () {
// Push to screen
tabsRouter.setActiveIndex(0);
if (widget.width < 1100) {
Navigator.pop(context);
}
},
),
ListTile(
leading: const Icon(Icons.edit),
title: const Text('S E C O N D'),
selected: tabsRouter.activeIndex == 1,
selectedColor: lightPrimaryColor,
onTap: () {
// Push to screen
tabsRouter.setActiveIndex(1);
if (widget.width < 1100) {
Navigator.pop(context);
}
},
),
ListTile(
leading: const Icon(Icons.check),
title: const Text('T H I R D'),
selected: tabsRouter.activeIndex == 2,
selectedColor: lightPrimaryColor,
onTap: () {
// Push to screen
tabsRouter.setActiveIndex(2);
if (widget.width < 1100) {
Navigator.pop(context);
}
},
),
ListTile(
leading: const Icon(Icons.settings),
title: const Text('F O U R T H'),
selected: tabsRouter.activeIndex == 3,
selectedColor: lightPrimaryColor,
onTap: () {
//Push to screen
tabsRouter.setActiveIndex(3);
if (widget.width < 1100) {
Navigator.pop(context);
}
},
),
],
),
),
);
}
}
Here is my code for the desktop home page where CustomDrawer is the first item in body row:
class DesktopHomePage extends StatelessWidget {
const DesktopHomePage({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
final width = MediaQuery.of(context).size.width;
return Scaffold(
backgroundColor: lightThemeScaffoldColor,
body: Row(
children: [
// Always open drawer
CustomDrawer(width: width),
// Body contents
Expanded(
child: Container(
margin: const EdgeInsets.all(largeMargin),
child: SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const MobileTabletTextHeadline(
text: 'Some widget',
),
SizedBox(
height: 300,
child: AspectRatio(
aspectRatio: 4,
child: SizedBox(
width: double.infinity,
child: GridView.builder(
physics: const NeverScrollableScrollPhysics(),
itemCount: 4,
gridDelegate:
const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 4,
),
itemBuilder: ((context, index) {
return Padding(
padding: const EdgeInsets.all(defaultPadding),
child: Container(color: lightThemeCardColor),
);
}),
),
),
),
),
// Some other widget
const MobileTabletTextHeadline(
text: 'Other Widget',
),
SizedBox(
height: 300,
child: AspectRatio(
aspectRatio: 4,
child: SizedBox(
width: double.infinity,
child: GridView.builder(
physics: const NeverScrollableScrollPhysics(),
itemCount: 4,
gridDelegate:
const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 4,
),
itemBuilder: ((context, index) {
return Padding(
padding: const EdgeInsets.all(defaultPadding),
child: Container(color: lightThemeCardColor),
);
}),
),
),
),
),
],
),
),
),
),
],
),
);
}
}
(All desktop views have the same layout)
And here is my code where I set up AutoTabsRouter:
class NavPage extends StatelessWidget {
const NavPage({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
final width = MediaQuery.of(context).size.width;
return AutoTabsRouter(
routes: const [
HomeRouter(),
SecondRouter(),
ThirdRouter(),
FourthRouter(),
],
builder: (context, child, animation) {
return Scaffold(
appBar:
MediaQuery.of(context).size.width < 1100 ? mobileAppBar : null,
backgroundColor: lightThemeScaffoldColor,
body: child,
drawer: CustomDrawer(width: width),
);
},
);
}
}
I've tried using using setState after setting the current index but that does not help. What can I change the Drawer in a way that reflects the changes in desktop view after window resize?
How to create this kind of UI in flutter. with expanded pageview??
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:movie_app/components/bottom_tabs.dart';
import 'package:movie_app/components/card_image.dart';
import 'package:movie_app/components/expandable_text.dart';
import 'package:movie_app/components/heading.dart';
import 'package:movie_app/constants.dart';
import 'package:movie_app/screens/card_details/components/card_details_cast.dart';
import 'package:movie_app/screens/card_details/components/card_details_photos.dart';
import 'package:movie_app/screens/card_details/components/card_details_reviews.dart';
import 'package:movie_app/screens/card_details/components/card_details_tabs.dart';
import '../../../components/my_text.dart';
import '../card_details.dart';
class Body extends StatefulWidget {
const Body({Key key}) : super(key: key);
#override
State<Body> createState() => _BodyState();
}
class _BodyState extends State<Body> {
PageController _tabsPageController;
int _selectedTab = 0;
#override
void initState() {
_tabsPageController = PageController();
super.initState();
}
#override
void dispose() {
_tabsPageController.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return SingleChildScrollView(
child: Stack(
clipBehavior: Clip.none,
children: [
Image.network(
"https://static.wikia.nocookie.net/film-vault/images/c/c8/Furypost.jpg/revision/latest?cb=20171202094520",
height: 260,
fit: BoxFit.cover,
),
Positioned(
top: 100,
left: 180,
child: SvgPicture.asset(
"assets/icons/play icon.svg",
color: kwhitecolor,
height: 50,
),
),
Container(
margin: EdgeInsets.only(top: 200, left: 15, right: 15, bottom: 20),
child: Column(
children: [
Row(
crossAxisAlignment: CrossAxisAlignment.end,
children: [
const CardImage(
image:
"https://m.media-amazon.com/images/M/MV5BMjA4MDU0NTUyN15BMl5BanBnXkFtZTgwMzQxMzY4MjE#._V1_.jpg",
width: 120,
),
const SizedBox(width: 15),
// Text("data"),
Column(
// mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: const [
MyText(
"FURY",
fontSize: 22,
isBold: true,
color: Colors.black,
),
SizedBox(width: 2),
MyText(
"(2014)",
fontSize: 14,
isBold: true,
color: Colors.black,
),
],
),
const MyText(
"Action/Drama/War",
fontWeight: FontWeight.w600,
),
const SizedBox(height: 40),
Row(
children: [
const Icon(Icons.remove_red_eye_outlined,
color: klightgreyColor),
const SizedBox(width: 2),
const MyText("1.5M", isBold: true),
const SizedBox(width: 10),
SvgPicture.asset(
"assets/icons/comment.svg",
height: 21,
color: klightgreyColor,
),
const SizedBox(width: 4),
const MyText("1K", isBold: true),
const SizedBox(width: 10),
SvgPicture.asset(
"assets/icons/clock.svg",
height: 18,
color: klightgreyColor,
),
const SizedBox(width: 4),
const MyText("2h 30min", isBold: true),
],
),
],
),
],
),
const SizedBox(height: 30),
const Heading(
"STORYLINE",
fontSize: 18,
padding: 0,
lineColor: Color.fromARGB(255, 255, 68, 68),
// fontWeight: FontWeight.w800,
),
const SizedBox(height: 10),
const ExpandableText(
text:
"1945, the Allies are making their final push in the European theater. A battle-hardened Army sergeant nallier (Brad Pitt), leading a Sherman tank and a five-man crew, undertakes a deadly mission behind enemy lines. Hopelessly outnumbered, outgunned and saddled with an inexperienced soldier (Logan Lerman) in their midst, Wardaddy and his men face overwhelming odds as they move to strike at the heart of Nazi Germany.",
max: 4,
),
SizedBox(height: 10),
CardDetailsBottomTabs(
selectedTab: _selectedTab,
tabPressed: (num) {
_tabsPageController.animateToPage(num,
duration: const Duration(milliseconds: 300),
curve: Curves.easeOutCubic);
},
),
// HERE I WANT TO USE EXPANDED WIDGET INSTEAD OF SIZEDBOX, BUT IT GIVES ME ERROR
SizedBox(
height: 300,
child: PageView(
controller: _tabsPageController,
onPageChanged: (num) {
setState(() {
_selectedTab = num;
});
},
children: const [
CardDetailsCast(),
CardDetailsPhoto(),
CardDetailsReview(),
],
),
),
],
),
),
],
),
);
}
}
this is all what I did so far, when I wrap pageview inside expanded widget it gives me error,
So is there any one who could find a way to wrap the pageview with expanded widget???
this is all what I did so far, when I wrap pageview inside expanded widget it gives me error,
So is there any one who could find a way to wrap the pageview with expanded widget???
this is all what I did so far, when I wrap pageview inside expanded widget it gives me error,
So is there any one who could find a way to wrap the pageview with expanded widget???
You can follow CustomScrollView with SliverAppBar. Example from SliverAppBar
class MyStatefulWidget extends StatefulWidget {
const MyStatefulWidget({Key? key}) : super(key: key);
#override
State<MyStatefulWidget> createState() => _MyStatefulWidgetState();
}
class _MyStatefulWidgetState extends State<MyStatefulWidget> {
bool _pinned = true;
bool _snap = false;
bool _floating = false;
// [SliverAppBar]s are typically used in [CustomScrollView.slivers], which in
// turn can be placed in a [Scaffold.body].
#override
Widget build(BuildContext context) {
return Scaffold(
body: CustomScrollView(
slivers: <Widget>[
SliverAppBar(
pinned: _pinned,
snap: _snap,
floating: _floating,
expandedHeight: 160.0,
flexibleSpace: const FlexibleSpaceBar(
title: Text('SliverAppBar'),
background: FlutterLogo(),
),
),
const SliverToBoxAdapter(
child: SizedBox(
height: 20,
child: Center(
child: Text('Scroll to see the SliverAppBar in effect.'),
),
),
),
SliverList(
delegate: SliverChildBuilderDelegate(
(BuildContext context, int index) {
return Container(
color: index.isOdd ? Colors.white : Colors.black12,
height: 100.0,
child: Center(
child: Text('$index', textScaleFactor: 5),
),
);
},
childCount: 20,
),
),
],
),
bottomNavigationBar: BottomAppBar(
child: Padding(
padding: const EdgeInsets.all(8),
child: OverflowBar(
overflowAlignment: OverflowBarAlignment.center,
children: <Widget>[
Row(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
const Text('pinned'),
Switch(
onChanged: (bool val) {
setState(() {
_pinned = val;
});
},
value: _pinned,
),
],
),
Row(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
const Text('snap'),
Switch(
onChanged: (bool val) {
setState(() {
_snap = val;
// Snapping only applies when the app bar is floating.
_floating = _floating || _snap;
});
},
value: _snap,
),
],
),
Row(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
const Text('floating'),
Switch(
onChanged: (bool val) {
setState(() {
_floating = val;
_snap = _snap && _floating;
});
},
value: _floating,
),
],
),
],
),
),
),
);
}
}
I have to return the number of pages in the PageView so that the value of 'count' in DotsAnimatedWidget->AnimatedSmoothIndicator automatically updates if the number of banners are increased or decreased. Is there any way to count the number of pages in the PageView or count the number of children? Should I approach a different way?
Link for the package used:
https://pub.dev/packages/smooth_page_indicator
class _BannerWidgetState extends State<BannerWidget> {
int _pages = 0;
final _controller = PageController();
#override
Widget build(BuildContext context) {
return Stack(
children: [
Padding(
padding: const EdgeInsets.fromLTRB(10, 0, 10, 10),
child: ClipRRect(
borderRadius: BorderRadius.circular(5),
child: Container(
height: 140,
width: MediaQuery.of(context).size.width,
color: Colors.white,
child: PageView(
controller: _controller,
onPageChanged: ((val) {
setState(() {
_pages = val.toInt();
});
}),
children: const [
Center(
child: Text(
'Banner 1',
style: TextStyle(fontSize: 20),
),
),
Center(
child: Text(
'Banner 2',
style: TextStyle(fontSize: 20),
),
),
Center(
child: Text(
'Banner 3',
style: TextStyle(fontSize: 20),
),
),
],
),
),
),
),
DotsIndicatorWidget(pages: _pages),
],
);
}
}
class DotsIndicatorWidget extends StatelessWidget {
const DotsIndicatorWidget({
Key? key,
required int pages,
}) : _pages = pages,
super(key: key);
final int _pages;
#override
Widget build(BuildContext context) {
return Positioned.fill(
bottom: 18,
child: Align(
alignment: Alignment.bottomCenter,
child: Row(
//mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
children: [
AnimatedSmoothIndicator(
activeIndex: _pages,
count: 3,
effect: const WormEffect(
spacing: 4.0,
activeDotColor: Colors.green,
dotColor: Colors.grey,
dotHeight: 8.0,
dotWidth: 8.0,
radius: 3,
type: WormType.normal),
),
],
),
),
);
}
}
Create a variable for children of PageView
List<Widget> _pages = [some Container]
int _currentIndex = 0;
And update it on onPageChanged()
onPageChanged: ((page) {
setState(() {
_currentIndex = page.toInt();
});
}),
Count the number of pages in the PageView used: _pages.length
But I think, used package smooth_page_indicator is best way