I have an app that has pageView.builder and it contains 5 stack widget
how can I scale up the widget that user-selected, for example:
if the user scrolls to widget 3, widgets 1 & 2 become smaller than widget 3, and the same if he scrolls to widget 5 or 2
( the middle will become bigger than the widget on both sides)
my code :
Widget build(BuildContext context) {
// ignore: sized_box_for_whitespace
return Container(
height: 320,
child: PageView.builder(
controller: pageController,
itemCount: 5,
itemBuilder: (context, position) {
return _bulidPageItem(position);
}),
);
}
Widget _bulidPageItem(int index) {
//------------------------------------------------------------------------------
// Slide image 🚩
return Stack(
alignment: Alignment.topCenter,
children: [
Container(
margin: const EdgeInsets.only(left: 5, right: 5),
height: 220,
width: 350,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20),
color: index.isEven
? const Color(0xFFffd28d)
: const Color(0xFF89dad0),
image: const DecorationImage(
image: AssetImage('images/chineseFood.jpg'), fit: BoxFit.cover),
),
),
//------------------------------------------------------------------------------
// Slide Information 🚩
Align(
alignment: Alignment.bottomCenter,
child: Container(
margin: const EdgeInsets.only(left: 30, right: 30, bottom: 15),
height: 130,
decoration: BoxDecoration(
boxShadow: [
BoxShadow(
color: Colors.grey.withOpacity(0.3),
blurRadius: 6,
spreadRadius: 0.7,
offset: const Offset(1, 4))
],
borderRadius: BorderRadius.circular(25),
color: Colors.white,
),
//------------------------------------------------
// Slider title
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const BigText(
text: 'Chinese side',
),
//----------------------------------------------
// Slider Rating
const SizedBox(height: 10),
Row(
children: [
Wrap(
children: List.generate(
5,
(index) => const Icon(Icons.star,
color: AppColor.mainColor, size: 12),
),
),
const SizedBox(width: 10),
SmallText(text: 4.5.toString()),
const SizedBox(width: 10),
const SmallText(text: '1287 comments'),
],
),
const SizedBox(height: 20),
//----------------------------------------------
// Slider Icons
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: const [
SliderIcons(
color: AppColor.iconColor1,
text: 'Normal',
icon: Icons.circle),
SliderIcons(
color: AppColor.mainColor,
text: '1.7km',
icon: Icons.location_pin),
SliderIcons(
color: AppColor.iconColor2,
text: '32min',
icon: FontAwesomeIcons.clock),
],
),
],
),
),
),
),
],
);
}
}
I think the carousel slider package provides the functionality you need. The package has an example, which exactly describes your issue.
you should try out https://api.flutter.dev/flutter/widgets/ListWheelScrollView-class.html
and for your layout, you can use rotate widget for the horizontal view and of course
you to use rotate widget on the child of the list too.
Save the current page and adjust the content based on that. Like below the current page, _currentPage == index, has smaller margins.
final _pageController = PageController(viewportFraction: 0.8);
int _currentPage = 0;
...
PageView.builder(
controller: _pageController,
itemCount: 5,
itemBuilder: (_, index) =>
Container(
margin: _currentPage == index
? const EdgeInsets.symmetric(vertical: 16)
: const EdgeInsets.symmetric(vertical: 64),
child: Image.network(
'https://picsum.photos/1080/1920?index=$index',
fit: BoxFit.cover,
loadingBuilder: (_, child, loadingProgress) {
if (loadingProgress == null) return child;
return const Center(child: CircularProgressIndicator());
}
)
),
onPageChanged: (page){
setState(() {
_currentPage = page;
});
},
)
)
Related
I'm building an app with a PageView Widget and I wanted to add AnimatedSmoothIndicator.
I added a CarouseLslider to the pageView to make it auto run
but it never changes .. I tried a lot of methods but none of them work
can anyone help..
class FoodPageBody extends StatefulWidget {
const FoodPageBody({Key? key}) : super(key: key);
#override
State<FoodPageBody> createState() => _FoodPageBodyState();
}
class _FoodPageBodyState extends State<FoodPageBody> {
PageController pageController = PageController(viewportFraction: 1);
int activeIndex = 0;
//------------------------------------------------------------------------------
#override
Widget build(BuildContext context) {
return SizedBox(
height: 340,
child: PageView.builder(
controller: pageController,
itemCount: 5,
itemBuilder: (context, position) {
return _bulidPageItem(position);
}),
);
}
Widget _bulidPageItem(int index) {
//------------------------------------------------------------------------------
// Slide image 🚩
return Column(
children: [
CarouselSlider(
options: CarouselOptions(
onPageChanged: (index, reason) {
setState(() {
activeIndex = index;
});
},
enlargeStrategy: CenterPageEnlargeStrategy.height,
enableInfiniteScroll: true,
enlargeCenterPage: true,
autoPlayCurve: Curves.ease,
autoPlay: true,
autoPlayInterval: const Duration(seconds: 5),
height: 320,
),
items: [
Stack(
alignment: Alignment.topCenter,
children: [
Container(
margin: const EdgeInsets.only(left: 5, right: 5),
height: 220,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20),
color: index.isEven
? const Color(0xFFffd28d)
: const Color(0xFF89dad0),
image: const DecorationImage(
image: AssetImage('images/chineseFood.jpg'),
fit: BoxFit.cover),
),
),
//------------------------------------------------------------------------------
// Slide Information 🚩
Align(
alignment: Alignment.bottomCenter,
child: Container(
margin:
const EdgeInsets.only(left: 20, right: 20, bottom: 15),
height: 130,
decoration: BoxDecoration(
boxShadow: [
BoxShadow(
color: Colors.grey.withOpacity(0.3),
blurRadius: 6,
spreadRadius: 0.7,
offset: const Offset(1, 4))
],
borderRadius: BorderRadius.circular(25),
color: Colors.white,
),
//------------------------------------------------
// Slider title
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const BigText(
text: 'Chinese side',
),
//----------------------------------------------
// Slider Rating
const SizedBox(height: 10),
Row(
children: [
Wrap(
children: List.generate(
5,
(index) => const Icon(Icons.star,
color: AppColor.mainColor, size: 12),
),
),
const SizedBox(width: 10),
SmallText(text: 4.5.toString()),
const SizedBox(width: 10),
const SmallText(text: '1287 comments'),
],
),
const SizedBox(height: 20),
//----------------------------------------------
// Slider Icons
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: const [
SliderIcons(
color: AppColor.iconColor1,
text: 'Normal',
icon: Icons.circle),
SliderIcons(
color: AppColor.mainColor,
text: '1.7km',
icon: Icons.location_pin),
SliderIcons(
color: AppColor.iconColor2,
text: '32min',
icon: FontAwesomeIcons.clock),
],
),
],
),
),
),
),
],
),
],
),
//------------------------------------------------------------------------------
// Slider Dots 🚩
AnimatedSmoothIndicator(
activeIndex: activeIndex,
count: 5,
effect: const WormEffect(),
)
],
);
}
}
The issue is here, the CarouselSlider's items is just one of this snippet. Therefore, onPageChanged active index is always getting 0.
To have five items, we need to generate item here.
I think pageView is not necessary for this case.
#override
Widget build(BuildContext context) {
return SizedBox(height: 340, child: _bulidPageItem());
}
Widget _bulidPageItem() {
//------------------------------------------------------------------------------
// Slide image 🚩
return Column(
children: [
CarouselSlider(
carouselController: carouselController,
options: CarouselOptions(
onPageChanged: (index1, reason) {
debugPrint("on Page changed $index1");
setState(() {
activeIndex = index1;
});
},
),
items: List.generate(
5,
(index) => Stack(
I have a ListViewBuilder inside a container in my UI when I scroll the list tiles get out of the container like so :
This my code :
return Padding(
padding: const EdgeInsets.symmetric(vertical: 10.0, horizontal: 5.0),
child: Container(
margin: const EdgeInsets.only(
left: 30, right: 30, bottom: 20),
width: getProportionateScreenWidth(600),
height: getProportionateScreenHeight(300),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: const BorderRadius.only(
topLeft: Radius.circular(17),
topRight: Radius.circular(17),
bottomLeft: Radius.circular(17),
bottomRight: Radius.circular(17)),
boxShadow: [
BoxShadow(
color: Colors.grey.withOpacity(0.5),
spreadRadius: 5,
blurRadius: 7,
offset: Offset(0, 3), // changes position of shadow
),
],
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Expanded(child: ListView.builder(
shrinkWrap: true,
physics: const ScrollPhysics(),
itemCount: snapshot.data!.perimeters.length,
itemBuilder: (context,index){
return PerimListTile(
perimID: snapshot.data!.perimeters[index].perimeterId.toString(),
perimLabel: snapshot.data!.perimeters[index].label,
);
})),
],
),
),
)
I want the list tiles to stay inside the container even while scrolling , if anyone knows how to solve the issue I'd be grateful , thank you in advance.
Problem
I do not know the details about getProportionateScreenHeight you used but I assume that it returns a double value.
The ListView inside the Column is constrained by the height of the container through that.
Solution
Remove the height of the container and try mainAxisSize: MainAxisSize.min on Column.
Solve
[1] Use the clip behavior parameter in container Widget. And set it to hardEdge
clipBehavior: Clip.hardEdge,
[2] Wrap the ListTile Widget with Card widget to make the cards inside the Container.
Card(child: ListTile());
Demo
import 'package:flutter/material.dart';
void main(List<String> args) {
runApp(MyHome());
}
class MyHome extends StatelessWidget {
const MyHome({super.key});
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Ans(),
);
}
}
class Ans extends StatefulWidget {
const Ans({super.key});
#override
State<Ans> createState() => _AnsState();
}
class _AnsState extends State<Ans> {
List<String> charName = [
'Rio',
'Tokyo',
'Berlin',
'Stockhome',
'Lisbon',
'Sergio',
'Martin'
];
List<String> charGender = [
'male',
'female',
'male',
'female',
'female',
'male',
'male'
];
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text("Tile Wrapper"),
),
body: SizedBox(
height: double.infinity,
width: double.infinity,
child: Column(
children: [
Padding(
padding: const EdgeInsets.only(top: 100.0),
child: Container(
height: 400,
width: 300,
/// Clipping the inner View Condition
clipBehavior: Clip.hardEdge,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20.2),
border: Border.all(color: Colors.black),
color: Colors.amberAccent,
),
child: ListView.builder(
itemCount: charGender.length,
itemBuilder: ((BuildContext context, int index) {
return Padding(
padding: EdgeInsets.only(top: 20.0),
//// Wrap the ListTile with Card Widget...
child: Card(
child: ListTile(
title: Text(
charName[index],
style: TextStyle(fontSize: 18.0),
),
subtitle: Text(
charGender[index],
style: TextStyle(fontSize: 18.0),
),
tileColor: Colors.brown,
leading: CircleAvatar(
radius: 20, child: Icon(Icons.person_rounded)),
),
),
);
})),
),
),
],
),
),
);
}
}
Sample
List fu = [
'Packing & Unpacking',
'Cleaning',
'Painting',
'Heavy Lifting',
'Shopping',
'Watching Netflix',
'sadfdsfe eaf',
'ewfsfeagga,' 'gegea',
'gaegaewgv ewaggaa aweegaage',
'safa asdfesadfv esfsdf',
'sadfdsfe eaf',
'ewfsfeagga,' 'gegea',
'awfgraga wsg sfage aegea',
'gaegaewgv ewaggaa aweegaage',
'asdfehtrbfawefa garevaa aewf a'
];
Widget build(BuildContext context) {
return Container(
height: 120,
margin: EdgeInsets.symmetric(horizontal: 3.5.w, vertical: 0.8.h),
child: StaggeredGridView.countBuilder(
crossAxisCount: 2,
staggeredTileBuilder: (index) => const StaggeredTile.fit(1),
shrinkWrap: true,
controller: _controller,
scrollDirection: Axis.horizontal,
// crossAxisSpacing: 0,
mainAxisSpacing: 8,
itemBuilder: (ctx, index) {
return Container(
padding: const EdgeInsets.all(15),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(15)),
child: Text(
fu[index],
maxLines: 1,
),
);
},
itemCount: fu.length,
),
);
}
StaggeredTile.fit(1) didn't work when staggeredGridiew is horizontal.
I also tried using Wrap but I didn't get expected outcome.
Wrap( direction: Axis.vertical, children: fu .map((title) => Container( decoration: BoxDecoration( color: ConstColors.kWhite, borderRadius: BorderRadius.circular(15)), margin: EdgeInsets.all(8), padding: const EdgeInsets.all(8), child: Row( children: [ Text(title), ], ), )) .toList(), )
The result has extra space between containers. It would be great id there was a way to get horizontal container back to back
Try Wrap
Like so:
Wrap(
children: List.generate(
fu.length,
(context){
return Container(
padding: const EdgeInsets.all(15),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(15)),
child: Text(
fu[index],
maxLines: 1,
),
);
})
),
You can use Warp widget to solve this
final items = <String>[
'Packing & Unpacking',
'Cleaning',
'Painting',
'Heavy Lifting',
'Shopping',
'Watching Netflix',
'sadfdsfe eaf',
'ewfsfeagga,' 'gegea',
'gaegaewgv ewaggaa aweegaage',
'safa asdfesadfv esfsdf',
'sadfdsfe eaf',
'ewfsfeagga,' 'gegea',
'awfgraga wsg sfage aegea',
'gaegaewgv ewaggaa aweegaage',
'asdfehtrbfawefa garevaa aewf a'
];
class Screen extends StatelessWidget {
const Screen({
Key? key,
}) : super(key: key);
#override
Widget build(BuildContext context) {
return Scaffold(
body: Wrap(
children: [
for (var item in items)
Container(
decoration: BoxDecoration(
color: Colors.white10,
border: Border.all(color: Colors.green),
borderRadius: const BorderRadius.all(Radius.circular(5)),
),
// you can change margin to increase spacing between containers
margin: const EdgeInsets.all(3),
padding: const EdgeInsets.all(5),
child: Text(item),
),
],
),
);
}
}
I'm making a Flutter Web App and I have something like this
class _HomeViewState extends State<HomeView> {
#override
Widget build(BuildContext context) {
var posts = Provider.of<List<Post>>(context);
List<int> l =[1,2,3,4];
return Scaffold(
backgroundColor: Colors.white,
appBar: TheAppBaar,
body: SingleChildScrollView(
scrollDirection: Axis.vertical,
child: Container(child: Padding(
padding: EdgeInsets.all(20.0),
child: Column(
children: [
CreatePost(connUserUid: widget.user.uid, connUserImage:
userFetched.get('profileImage').toString(),
connUserFullname: userFetched.get('fullName').toString(),),
SizedBox(height: 10,),
ListView.separated(itemBuilder: (BuildContext context, int
index) {
return Container(
height: 150,
child: Text('${l[index]}'),
);
},
separatorBuilder:
(BuildContext context, int index) => Divider(),
itemCount: l.length)
],
),
),
),
),
);
}
}
Every time I want to display a ListView with those posts fetched or anything, the method Create Post and that Sized Box disappear and the list is not displayed either.
#override
Widget build(BuildContext context) {
return Align(
alignment: Alignment.center,
child: Container(
width: 400,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.all(Radius.circular(10)),
boxShadow: [BoxShadow(
color:kPrimaryColor.withOpacity(0.2),
spreadRadius: 2,
blurRadius: 3,
offset: Offset(0,3)
)]
),
child: Padding(
padding: EdgeInsets.all(20),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Align(
alignment: Alignment.center,
child: Container(
height: 50,
child: Image.network(widget.connUserImage),
),
),
Align(
alignment: Alignment.center,
child: Container(width: 30,child: Divider(
color: kPrimaryColor,
thickness: 2,
),),
),
SizedBox(height: 8,),
TextField(
maxLines: 5,
decoration: InputDecoration(
errorText: errorTextMessage,
border: OutlineInputBorder(
borderSide: BorderSide(color: kPrimaryColor)
),
labelText: 'Yadda, Yadda, Yadda...'
),
onChanged: (String value) {
setState(() {
postDescription = value;
errorTextMessage = null;
spinner = false;
});
},
),
SizedBox(height: 12,),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Row(
children: [
IconButton(
icon: Icon(Icons.add_a_photo_rounded, color: Color
(0xFFE53E00),
size:
25,),
onPressed: () {
imagePicker();
},
),
SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: imageInfo == null ? Container() : Text(imageInfo.fileName),
)
],
),
Icon(Icons.pin_drop_rounded, color: Color(0xFF0077e5),
size:
25,),
Icon(Icons.map_rounded, color: Color(0xFF26c118),
size: 25,),
spinner? Padding(
padding: EdgeInsets.all(15.0),
child: CircularProgressIndicator(backgroundColor: kPrimaryColor,),
) :
IconButton(icon:
Icon(Icons
.arrow_forward_ios_outlined,
color:
kPrimaryColor,size: 25,), onPressed: () {
},),
],
)
],
),
),
),
);
}
This is the CreatePost method, just a " card ",
If I make a ListView all disappear, but if in my Column from the first code, I add 1 PostView by 1, they are displayed. I don't understand what's wrong. Should I remove those Align or I don't know. In my console I do not have any errors.
Thank you in advance!
I'm not sure if I'll be able to implement what I want with the way the code is set up.
I have a home screen where at the top I declared a ListView, taking information from a list.dart file.
This horizontal scrolling screen brings me 5 images and a text in each of them.
I would like to insert an onPressed directing to other screens according to the information passed in this list.
Example: Chat, direct to chat screen.
class HomePage extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
body: Stack(children: <Widget>[
Container(
width: double.infinity,
height: MediaQuery.of(context).size.height * 4 / 7,
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: [Color(0xff40dedf), Color(0xff0fb2ea)],
),
),
),
Positioned(
top: 100,
left: 20,
child: Container(
height: 100,
width: MediaQuery.of(context).size.width,
child: ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: categoryData.length,
itemBuilder: (context, index) {
bool isSelected = true;
if (index == 0) {
isSelected = true;
}
return Row(
children: <Widget>[
Column(
children: <Widget>[
Container(
width: 65,
height: 65,
decoration: BoxDecoration(
color: isSelected
? Colors.transparent
: Colors.transparent,
borderRadius: BorderRadius.circular(16),
border: Border.all(
color: Colors.white,
width: 1,
),
boxShadow: isSelected
? [
BoxShadow(
color: Color(0x14000000),
blurRadius: 10)
]
: null),
child: Center(
child: Image.asset(categoryData[index].imageUrl),
),
),
SizedBox(
height: 10,
),
Text(
categoryData[index].name,
style: TextStyle(color: Colors.white, fontSize: 15),
),
],
),
SizedBox(
width: 20,
)
],
);
},
),
),
),
]));
}
}
This is the List.dart from which you get the information:
class MyList {
final String name;
final String count;
final String imageUrl;
MyList({this.imageUrl, this.name, this.count});
}
And this is the variable used for configuration:
List<MyList> categoryData = [
new MyList(imageUrl: "assets/page1/usuario.png", name: "Perfil", count: "1"),
new MyList(
imageUrl: "assets/page1/entregas.png", name: "Entregas", count: "2"),
new MyList(imageUrl: "assets/page1/msg.png", name: "Chat", count: "3"),
new MyList(
imageUrl: "assets/page1/configurações.png",
name: "Configuração",
count: "4"),
new MyList(imageUrl: "assets/page1/sair.png", name: "Sair", count: "5"),
];
You can make use of a GestureDetector as a parent for each Container you've created to be a button. The documentation shows that the GestureDetector can have an onTap function declared, where you can define your own routing logic.
You could then have a switch case created to determine to which screen the application needs to route, or even make use of the name parameter of your categoryData variable.
ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: categoryData.length,
itemBuilder: (context, index) {
bool isSelected = true;
if (index == 0) {
isSelected = true;
}
return Row(
children: <Widget>[
Column(
children: <Widget>[
// Here you add a GestureDetector
GestureDetector(
onTap: () {
// Here you add your navigation logic
},
child: Container(
width: 65,
height: 65,
decoration: BoxDecoration(
color: isSelected
? Colors.transparent
: Colors.transparent,
borderRadius: BorderRadius.circular(16),
border: Border.all(
color: Colors.white,
width: 1,
),
boxShadow: isSelected
? [
BoxShadow(
color: Color(0x14000000),
blurRadius: 10)
]
: null),
child: Center(
child: Image.asset(categoryData[index].imageUrl),
),
),
),
SizedBox(
height: 10,
),
Text(
categoryData[index].name,
style: TextStyle(color: Colors.white, fontSize: 15),
),
],
),
SizedBox(
width: 20,
)
],
);
},
),
Note: You should always name your class variables UpperCamelCase in Flutter. Try changing the list class name to something more declarative ;)