Good afternoon! I am new to Flutter. Faced such a problem
There is a scooter card. I need it to be able to move vertically across the screen between three positions - initial, top and bottom (as planned, in the bottom position, part of the card goes off the screen). I tried to solve it through AnimatedPositioned and child GestureDetector. But I managed to do it well for only two positions. When I tried to do this for three positions, the movements did not work out quite correctly. Because of what it is difficult to install the card in its original position. How can this be done for three positions? Maybe not through AnimatedPositioned? Thanks a lot!
starting positionbottom positiontop position
this is how i did for 2 positions
class CardBeforeRent extends StatefulWidget {
const CardBeforeRent({super.key});
#override
State<CardBeforeRent> createState() => _CardBeforeRentState();
}
class _CardBeforeRentState extends State<CardBeforeRent> {
bool isHiden = false;
num hidenV = 0;
hide(details) {
if (details.delta.dy < 0) {
setState(() {
hidenV = 0;
isHiden = false;
});
} else if (details.delta.dy > 0) {
setState(() {
hidenV = -265;
isHiden = true;
});
}
}
#override
Widget build(BuildContext context) {
return AnimatedPositioned(
width: MediaQuery.of(context).size.width,
duration: const Duration(milliseconds: 600),
bottom: isHiden ? hidenV.toDouble() : 0,
child: GestureDetector(
onVerticalDragUpdate: (details) => hide(details),
child: Column(
mainAxisAlignment: MainAxisAlignment.end,
children: [
SizedBox(
height: 360,
child: StatefulBuilder(
builder: (context, setState) => FractionallySizedBox(
heightFactor: 1.1,
child: Container(
padding: const EdgeInsets.symmetric(horizontal: 10),
decoration: BoxDecoration(
color: Theme.of(context).dialogBackgroundColor,
borderRadius: const BorderRadius.only(
topLeft: Radius.circular(15),
topRight: Radius.circular(15),
),
),
child: Column(
children[...],
),
),
),
),
),
Column(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Container(
decoration:
BoxDecoration(color: Theme.of(context).bottomAppBarColor),
height: 100,
child: BookButton(...),
],
),
],
),
),
);
}
}
this is what i tried to do for 3 positions
class _CardBeforeRentState extends State<CardBeforeRent> {
double cardPadding = 0;
#override
Widget build(BuildContext context) {
return AnimatedPositioned(
width: MediaQuery.of(context).size.width,
duration: const Duration(milliseconds: 600),
bottom: cardPadding,
child: GestureDetector(
onVerticalDragUpdate: (details) {
if (details.delta.dy == 0) {
setState(() {
cardPadding = 0;
});
} else if (details.delta.dy < 0) {
setState(() {
cardPadding = -265;
});
} else if (details.delta.dy > 0) {
setState(() {
cardPadding = 140;
});
}
},
child: Column(
mainAxisAlignment: MainAxisAlignment.end,
children: [
SizedBox(
height: 360,
child: StatefulBuilder(
builder: (context, setState) => FractionallySizedBox(
heightFactor: 1.1,
child: Container(
padding: const EdgeInsets.symmetric(horizontal: 10),
decoration: BoxDecoration(
color: Theme.of(context).dialogBackgroundColor,
borderRadius: const BorderRadius.only(
topLeft: Radius.circular(15),
topRight: Radius.circular(15),
),
),
child: Column(
children[...],
),
),
),
),
),
Column(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Container(
decoration:
BoxDecoration(color: Theme.of(context).bottomAppBarColor),
height: 100,
child: BookButton(...),
],
),
],
),
),
);
}
}
Related
my video call output
when logged another person to this video call then shows like this.But I want when someone logged to video call then my video should be small.
like this.
and also when click my video then my video should be big and another person's video should be small. how to do that ? I couldn't find the any documentation how to do that
Code video call ui
// video view
Widget _viewRows() {
final views = _getRenderViews();
switch (views.length) {
case 1:
return Column(
children: <Widget>[_videoView(views[0])],
);
case 2:
return Column(
children: <Widget>[
_expandedVideoRow([views[0]]),
_expandedVideoRow([views[1]])
],
);
case 3:
return Column(
children: <Widget>[
_expandedVideoRow(views.sublist(0, 2)),
_expandedVideoRow(views.sublist(2, 3))
],
);
case 4:
return Column(
children: <Widget>[
_expandedVideoRow(views.sublist(0, 2)),
_expandedVideoRow(views.sublist(2, 4))
],
);
default:
}
return Container();
}
How customize the video UI like as I mentioned?
error
To create the layout which you want, edit _viewRow(CallNotifier notifier) and _expandedVideoRow(List views) function with following code : -
Widget _viewRows(CallNotifier notifier) : -
case 2:
return Container(
margin: EdgeInsets.only(top: 100, bottom: 100),
child: Stack(
children: [
_expandedVideoRow([views[secondScreen]]),
Align(
alignment: Alignment.bottomRight,
child: Padding(
padding: const EdgeInsets.only(right: 10, bottom: 10),
child: GestureDetector(
onTap: () {
tempSwap = firstScreen;
firstScreen = secondScreen;
secondScreen = tempSwap;
setState(() {});
},
child: SizedBox(
height: 200,
width: 100,
child: _expandedVideoRow([views[firstScreen]])),
),
),
),
],
));
Above code contains _expandedVideoRow([views[secondScreen]]), which is just a simple Expandable Container and we are passing the index of the screen as a parameter. In our case, there are 2 screens hence 2 index that is 0 and 1. I have declared three integer variables here, int firstScreen = 0, int secondScreen = 1 and int tempSwap = 0. The second _expandedVideoRow([views[firstScreen]]) is wrapped by GesutreDector, so when the user taps on that screen the indexes of the variable are swapped which results in swapping the screens, SizedBox to reduce its width and height and Align widget to give the desired position to the second screen.
Widget _expandedVideoRow(List views) : -
Widget _expandedVideoRow(List<Widget> views) {
final wrappedViews = views.map<Widget>(_videoView).toList();
return Row(
children: wrappedViews,
);
}
Remove the Expanded widget that wraps the row like the above code because we can't use the Expanded under the Stack widget.
If you wish to change the bottom icons, then change _toolbar(CallNotifier notifier) function according to your need.
Widget _toolbar(CallNotifier notifier) {
return Container(
alignment: Alignment.bottomCenter,
padding: const EdgeInsets.symmetric(vertical: 20),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
RawMaterialButton(
onPressed: () {
_onToggleMute(notifier);
setState(() {
isMute = !isMute;
});
},
child: Icon(
isMute ? Icons.mic_off : Icons.mic,
color: isMute ? Colors.white : Colors.teal,
size: 20.0,
),
shape: CircleBorder(),
elevation: 2.0,
fillColor: isMute ? Colors.teal : Colors.white,
padding: const EdgeInsets.all(12.0),
),
RawMaterialButton(
onPressed: () => _onCallEnd(context),
child: Icon(
Icons.call_end,
color: Colors.white,
size: 20.0,
),
shape: CircleBorder(),
elevation: 2.0,
fillColor: Colors.redAccent,
padding: const EdgeInsets.all(15.0),
),
],
),
);
}
Code which I use in my app, full code : -
class _CallScreenState extends State<CallScreen> {
double globalHeight;
int firstScreen = 0;
int secondScreen = 1;
int tempSwap = 0;
bool isMute = false;
void initState() {
super.initState();
}
List<Widget> _getRenderViews(CallNotifier model) {
final List<StatefulWidget> list = [];
list.add(RtcLocalView.SurfaceView());
model.users
.forEach((int uid) => list.add(RtcRemoteView.SurfaceView(uid: uid)));
return list;
}
Widget _videoView(view) {
return Expanded(child: Container(child: view));
}
Widget _expandedVideoRow(List<Widget> views) {
final wrappedViews = views.map<Widget>(_videoView).toList();
return Row(
children: wrappedViews,
);
}
Widget _viewRows(CallNotifier notifier) {
final views = _getRenderViews(notifier);
switch (views.length) {
case 1:
return Container(
margin: EdgeInsets.only(top: 100, bottom: 100),
child: Column(
children: <Widget>[_videoView(views[0])],
));
case 2:
return Container(
margin: EdgeInsets.only(top: 100, bottom: 100),
child: Stack(
children: [
_expandedVideoRow([views[secondScreen]]),
Align(
alignment: Alignment.bottomRight,
child: Padding(
padding: const EdgeInsets.only(right: 10, bottom: 10),
child: GestureDetector(
onTap: () {
tempSwap = firstScreen;
firstScreen = secondScreen;
secondScreen = tempSwap;
setState(() {});
},
child: SizedBox(
height: 200,
width: 100,
child: _expandedVideoRow([views[firstScreen]])),
),
),
),
],
));
default:
}
return Container();
}
Widget _toolbar(CallNotifier notifier) {
return Container(
alignment: Alignment.bottomCenter,
padding: const EdgeInsets.symmetric(vertical: 20),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
RawMaterialButton(
onPressed: () {
_onToggleMute(notifier);
setState(() {
isMute = !isMute;
});
},
child: Icon(
isMute ? Icons.mic_off : Icons.mic,
color: isMute ? Colors.white : Colors.teal,
size: 20.0,
),
shape: CircleBorder(),
elevation: 2.0,
fillColor: isMute ? Colors.teal : Colors.white,
padding: const EdgeInsets.all(12.0),
),
RawMaterialButton(
onPressed: () => _onCallEnd(context),
child: Icon(
Icons.call_end,
color: Colors.white,
size: 20.0,
),
shape: CircleBorder(),
elevation: 2.0,
fillColor: Colors.redAccent,
padding: const EdgeInsets.all(15.0),
),
],
),
);
}
void _onCallEnd(BuildContext context) {
Navigator.pop(context);
}
void _onToggleMute(CallNotifier notifier) {
notifier.isMuted = notifier.isMuted;
notifier.engine.muteLocalAudioStream(notifier.isMuted);
}
#override
Widget build(BuildContext context) {
return BaseWidget<CallNotifier>(
model: CallNotifier(),
onModelReady: (model) => model.init(widget.channelName, widget.token),
builder: (context, notifier, child) {
return Scaffold(
backgroundColor: Colors.black,
body: SafeArea(
child: Stack(
children: <Widget>[
_viewRows(notifier),
Align(
alignment: Alignment.bottomCenter,
child: _toolbar(notifier)),
],
),
),
);
});
}
}
i have a list view that shows images, every time i navigate to another screen and come back its reload the images.
i tried AutomaticKeepAliveClientMixin but didn’t work.
this is the list
ListView.builder(
addAutomaticKeepAlives: true,
physics: const NeverScrollableScrollPhysics(),
shrinkWrap: true,
itemCount: allproducts.length,
itemBuilder: (context, index) {
return ChangeNotifierProvider.value(
value: allproducts[index],
child: const FeedsWidget(),
);
},
),
this is the screen that i call inside it
class FeedsWidget extends StatefulWidget {
const FeedsWidget({
Key? key,
}) : super(key: key);
#override
State<FeedsWidget> createState() => _FeedsWidgetState();
}
class _FeedsWidgetState extends State<FeedsWidget>with AutomaticKeepAliveClientMixin {
final qantityController = TextEditingController();
#override
Widget build(BuildContext context) {
super.build(context);
final themeState = Provider.of<DarkThemeProvider>(context);
final ProductModelsvar = Provider.of<ProductModels>(context);
final cartProvider = Provider.of<CartProvider>(context);
bool? _isInCart =
cartProvider.getCartItems.containsKey(ProductModelsvar.id);
final wishListProvider = Provider.of<WishListProvider>(context);
bool? _isInWishlist =
wishListProvider.getwishListItems.containsKey(ProductModelsvar.id);
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Container(
height: 230,
width: double.maxFinite,
margin: const EdgeInsets.all(10),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20),
),
child: Stack(alignment: Alignment.centerRight, children: [
Container(
width: double.maxFinite,
child: ClipRRect(
borderRadius: BorderRadius.circular(20),
child:CachedNetworkImage(
imageUrl:ProductModelsvar.imageUrl,
imageBuilder: (context,imageProvider)=>Container(
decoration: BoxDecoration(
image: DecorationImage(
image: imageProvider,
fit: BoxFit.cover,
),
),
),
placeholder: (context,url)=>Container(
alignment: Alignment.center,
child: LoadingManegar(isLoading: true),
),
),
// Image.network(
// ProductModelsvar.imageUrl,
// fit: BoxFit.cover,
// loadingBuilder: (BuildContext context, Widget child,
// ImageChunkEvent? loadingProgress) {
// if (loadingProgress == null) return child;
// return Center(
// child: LoadingManegar(
// isLoading: true,
// ),
// );
// },
// ),
),
),
Container(
width: 80,
decoration: BoxDecoration(
color: Colors.black.withOpacity(0.3),
borderRadius: const BorderRadius.only(
topRight: Radius.circular(
20,
),
bottomRight: Radius.circular(
20,
)),
),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Padding(
padding: const EdgeInsets.all(5),
child: ReusibleText(
text: ProductModelsvar.title,
size: 15,
textfontWeight: FontWeight.w500,
color: Colors.white,
),
),
PriceWidget(
price: double.parse(ProductModelsvar.price),
textprice: '1',
),
Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [
IconButton(
onPressed: _isInCart
? null
: ()async {
await CartProvider.addToCart(
productid: ProductModelsvar.id,
quantity: 1, context: context);
await cartProvider.fetchCart();
// cartProvider.addProductToCart(
// productid: ProductModelsvar.id,
// quantity: 1);
},
icon: Icon(_isInCart ? Icons.check : IconlyLight.bag,
color: Colors.white,size: 20,),
),
HeartWidget(
productId: ProductModelsvar.id,
isInwishList: _isInWishlist,
),
IconButton(
onPressed: () {
Navigator.pushNamed(context, "ProductDetScreen",
arguments: ProductModelsvar.id);
},
icon: const Icon(IconlyLight.arrowRightCircle,
color: Colors.white,size: 20),
),
],
)
],
),
),
]),
),
],
);
}
#override
bool get wantKeepAlive => true;
}
I wanted to create a Container which looks like a Card with a small icon, when this icon is clicked the container height changed and show different component inside.
here is the expected result
Here is the working example,
double _height = 50.0;
bool _isExpanded = false;
Future<bool> _showList() async {
await Future.delayed(Duration(milliseconds: 300));
return true;
}
AnimatedContainer
AnimatedContainer(
duration: Duration(milliseconds: 300),
height: _height,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(5),
color: Colors.grey,
),
width: MediaQuery.of(context).size.width - 100,
padding: EdgeInsets.only(left: 15, right: 15),
child: Column(
children: [
Padding(
padding: const EdgeInsets.only(top: 10),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text('Title'),
InkWell(
onTap: () {
if (!_isExpanded) {
setState(() {
_height = 300;
_isExpanded = true;
});
} else {
setState(() {
_height = 50;
_isExpanded = false;
});
}
},
child: Container(
height: 30,
width: 40,
color: Colors.red,
child: !_isExpanded ? Icon(Icons.add) : Icon(Icons.remove),
),
),
],
),
),
_isExpanded
? FutureBuilder(
future: _showList(), /// will wait untill box animation completed
builder: (context, snapshot) {
if (!snapshot.hasData) {
return SizedBox();
}
return ListView.builder(
itemCount: 10,
shrinkWrap: true,
itemBuilder: (context, index) {
return Text('data'); // your custom UI
},
);
})
: SizedBox.shrink(),
],
),
);
I have a List of BoardingPage widgets that I build a pageview with. I have some navigation buttons on the bottom of the Pageview that the user can use to go to the next or previous page.
However, these buttons need to be tapped twice in order to do something and I don't know how to fix this behaviour.
Codesnippet:
https://pastebin.com/kuZ8Hhvf
class _BoardingState extends State<Boarding> {
int currentPage = 0;
#override
void initState() {
super.initState();
}
#override
Widget build(BuildContext context) {
MyLocalization localization = MyLocalization.of(context);
String title = "notitle";
Widget circleBar(bool isActive) {
return AnimatedContainer(
duration: Duration(milliseconds: 150),
margin: EdgeInsets.symmetric(horizontal: 8),
height: isActive ? 12 : 8,
width: isActive ? 12 : 8,
decoration: BoxDecoration(
color: isActive ? myDarkGreen : myDefaultBackgroundColor,
borderRadius: BorderRadius.all(Radius.circular(15)),
),
);
}
void setPage(int pageID) {
setState(() {
currentPage = pageID;
});
}
return Consumer<Settings>(builder: (context, settings, _) {
PageController pageController = PageController(initialPage: 0);
if (settings.isFirstStartDone()) {
return widget.child;
}
return Stack(
children: [
PageView.builder(
controller: pageController,
physics: new NeverScrollableScrollPhysics(),
onPageChanged: (page) {
setState(() {
currentPage = page;
});
},
itemCount: boardingList.length,
itemBuilder: (context, index) {
BoardingPage boardingSite = boardingList[index];
//widget.title = boardingSite.title;
return boardingSite.body;
}),
Align(
alignment: Alignment.bottomCenter,
child: Container(
margin: EdgeInsets.only(bottom: 30),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
mainAxisSize: MainAxisSize.min,
children: [
for (int i = 0; i < boardingList.length; i++)
if (i == currentPage) ...[circleBar(true)] else ...[circleBar(false)],
],
),
),
),
//Boarding finished Button
Visibility(
visible: currentPage == boardingList.length - 1,
child: Container(
padding: EdgeInsets.only(bottom: 20, right: 30),
child: Align(
alignment: Alignment.bottomRight,
child: FloatingActionButton(
backgroundColor: myDarkGreen,
onPressed: () {
//Saving Town
settings.setProfilesetting(0, 0, "townname", boardingTownName);
settings.setProfilesetting(0, 0, "dreamaddress", boardingDreamAddress);
settings.setSouthernRegion(0, boardingTownRegion == "south");
settings.setProfilesetting(0, 0, "townfruit", boardingTownFruit);
settings.setTownExisting(0, true);
settings.setActiveTownID(0);
//Saving Character
settings.setProfilesetting(0, 0, "charactername", boardingCharacterName);
settings.setProfilesetting(0, 0, "friendcode", boardingCharacterFriendcode);
settings.setProfilesetting(0, 0, "gender", boardingCharacterGender);
settings.setProfilesetting(0, 0, "creatorid", boardingCharacterCreatorID);
settings.setProfilesetting(0, 0, "joindate", boardingCharacterJoinDate);
settings.setProfilesetting(0, 0, "birthday", boardingCharacterBirthday);
settings.setProfilesetting(0, 0, "townleader", true.toString());
settings.setCharacterExisting(0, 0, true);
//Saving Characterlook
settings.setCharacterRenderValues(0, 0, boardingActiveItems);
settings.setActiveCharacterID(0);
settings.setFirstStartDone(true);
Navigator.push(context, MaterialPageRoute(builder: (context) {
return widget.child;
}));
},
child: Icon(Icons.arrow_forward),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(10)),
))),
)),
//Page forward Button
Visibility(
visible: currentPage != boardingList.length - 1 && currentPage != 0,
child: Container(
padding: EdgeInsets.all(10),
child: Align(
alignment: Alignment.bottomRight,
child: FlatButton(
color: myDarkGreen,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(10))),
child: currentPage != 4
? Icon(
Icons.arrow_forward,
color: myWhite,
)
: Text(localization.no, style: TextStyle(color: myWhite)),
onPressed: () {
if (currentPage == 4) {
settings.setSpoilerfilter(false);
settings.setSpoilerFilterSeen(true);
}
pageController.animateToPage(currentPage++, duration: Duration(milliseconds: 250), curve: Curves.bounceInOut);
}),
),
)),
//Page back Button
Visibility(
visible: currentPage != boardingList.length - 1 && currentPage != 0,
child: Align(
alignment: Alignment.bottomLeft,
child: Container(
padding: EdgeInsets.all(10),
child: FlatButton(
color: myDarkGreen,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(10))),
child: currentPage != 4
? Icon(
Icons.arrow_back,
color: myWhite,
)
: Text(localization.yes, style: TextStyle(color: myWhite)),
onPressed: () {
if (currentPage == 4) {
settings.setSpoilerfilter(true);
settings.setSpoilerFilterSeen(true);
}
pageController.animateToPage(currentPage--, duration: Duration(milliseconds: 250), curve: Curves.bounceInOut);
})))),
//First screen create button
Visibility(
visible: currentPage == 0,
child: Padding(
padding: const EdgeInsets.only(bottom: 100.0),
child: Align(
alignment: Alignment.bottomCenter,
child: Row(
children: [
Expanded(
child: Container(
padding: EdgeInsets.all(10),
child: FlatButton(
color: myDarkGreen,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(10))),
child: Text(
"Create",
style: TextStyle(color: myWhite),
),
onPressed: () => pageController.animateToPage(currentPage++, duration: Duration(milliseconds: 250), curve: Curves.bounceInOut))),
),
],
),
),
),
),
//first screen skip button
Visibility(
visible: currentPage == 0,
child: Padding(
padding: const EdgeInsets.only(bottom: 40.0),
child: Align(
alignment: Alignment.bottomCenter,
child: Row(
children: [
Expanded(
child: Container(
padding: EdgeInsets.all(10),
child: FlatButton(
color: myDarkGreen,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(10))),
child: Text(
"Skip",
style: TextStyle(color: myWhite),
),
onPressed: () {
pageController.animateToPage(4, duration: Duration(milliseconds: 250), curve: Curves.bounceInOut);
currentPage = 5;
})),
),
],
),
),
),
),
],
),
),
),
)
],
);
});
}
Future<void> _migrateSettings() async {
setState(() {});
}
}
I solved my problem by replacing currentPage++ with ++currentPage (currentPage-- as well) so the page will get counted up before the navigation will be executed
I am new in flutter. I am using carousel slider package to show image. I want to set my image size. Now I faced the problem with my vertical image have been crop and show part center only. Here is my code:
final List<String> imgList = [
'https://images.unsplash.com/photo-1520342868574-5fa3804e551c?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjEyMDd9&s=6ff92caffcdd63681a35134a6770ed3b&auto=format&fit=crop&w=1951&q=80',
'https://images.unsplash.com/photo-1522205408450-add114ad53fe?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjEyMDd9&s=368f45b0888aeb0b7b08e3a1084d3ede&auto=format&fit=crop&w=1950&q=80',
'https://images.unsplash.com/photo-1519125323398-675f0ddb6308?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjEyMDd9&s=94a1e718d89ca60a6337a6008341ca50&auto=format&fit=crop&w=1950&q=80',
];
final List<Widget> imageSliders = imgList.map((item) => Container(
child: Container(
margin: EdgeInsets.all(5.0),
child: ClipRRect(
borderRadius: BorderRadius.all(Radius.circular(5.0)),
child: Stack(
children: <Widget>[
Image.network(item, fit: BoxFit.cover, width: 1000.0),],
)),),
)).toList();
class CarouselWithIndicatorDemo extends StatefulWidget {
#override
State<StatefulWidget> createState() {
return _CarouselWithIndicatorState();
}
}
class _CarouselWithIndicatorState extends State<CarouselWithIndicatorDemo> {
int _current = 0;
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Carousel with indicator demo')),
body: Column(
children: [
CarouselSlider(
items: imageSliders,
options: CarouselOptions(
enlargeCenterPage: true,
aspectRatio: 2.0,
onPageChanged: (index, reason) {
setState(() {
_current = index;
});}), ),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: imgList.map((url) {
int index = imgList.indexOf(url);
return Container(
width: 8.0,height: 8.0,
margin: EdgeInsets.symmetric(vertical: 10.0, horizontal: 2.0),
decoration: BoxDecoration(
shape: BoxShape.circle,color: _current == index ? Color.fromRGBO(0, 0, 0, 0.9): Color.fromRGBO(0, 0, 0, 0.4),
), );
}).toList(),
), ]
),
);
}
}
Anyone can help me? Thanks in advance
This function can help you while scrolling left to right carousel images
Column(
children: <Widget>[
Padding(
padding: EdgeInsets.only(top: parentHeight * .025),
child: CarouselSlider(
height: parentHeight * .45,
enlargeCenterPage: true,
reverse: false,
autoPlay: true,
autoPlayInterval: Duration(seconds: 4),
autoPlayAnimationDuration: Duration(milliseconds: 800),
autoPlayCurve: Curves.fastOutSlowIn,
enableInfiniteScroll: true,
scrollDirection: Axis.horizontal,
onPageChanged: (index) {
setState(() {
_current = index;
});
},
items: imageTextList.map((data) {
return Builder(
builder: (BuildContext context) {
return Wrap(
children: <Widget>[
Container(
width: MediaQuery.of(context).size.width,
margin: EdgeInsets.symmetric(
horizontal: 8.0, /*vertical: 10.0 */
),
decoration: BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(10.0)),
),
child: ClipRRect(
borderRadius: BorderRadius.all(Radius.circular(10.0)),
child: Image(
image: new AssetImage(data.imageUrl),
fit: BoxFit.cover,
),
),
),
getNewTextLayout(data, parentHeight, parentWidth),
],
);
},
);
}).toList(),
),
),
],
);