How to add button on each slide of carousel slider - flutter

I have been using flutter and the carousel slider package to create an image slider of 3 images
https://pub.dev/packages/carousel_slider
However, i want to add a button on each of those sliders on top of the images as you would see in e-commerce apps for example to "shop now" the sale etc.
like so:
class _MainScreenState extends State<MainScreen> {
final featuredImages = [
'lib/assets/images/elitefeatured.jpg',
'lib/assets/images/guabafeatured.jpg',
'lib/assets/images/eliteclubfeatured.jpg'
];
#override
Widget build(BuildContext context) { //extra non-relevant code in here
Padding(
padding: EdgeInsets.only(
top: 85,
),
child: SizedBox(
width: 450,
height: 300,
child: CarouselSlider(
options: CarouselOptions(
autoPlay: true,
),
items: featuredImages.map((featuredImage) {
return Padding(
padding: EdgeInsets.symmetric(horizontal: 7),
child: Image.asset(featuredImage),
);
}).toList(),
),
),
),
}

There are 2 important ideas:
Use a Stack widget to display your right and left arrows
Use a CarouselController to programmatically control your carousel
In code:
import 'package:carousel_slider/carousel_slider.dart';
import 'package:flutter/material.dart';
class _MainScreenState extends State<MainScreen> {
/// Create a controller to control the carousel programmatically
CarouselController carouselController = CarouselController();
final featuredImages = [
'lib/assets/images/elitefeatured.jpg',
'lib/assets/images/guabafeatured.jpg',
'lib/assets/images/eliteclubfeatured.jpg'
];
#override
Widget build(BuildContext context) {
//extra non-relevant code in here
Padding(
padding: EdgeInsets.only(
top: 85,
),
child: SizedBox(
width: 450,
height: 300,
child: Stack(
children: [
CarouselSlider(
carouselController: carouselController, // Give the controller
options: CarouselOptions(
autoPlay: true,
),
items: featuredImages.map((featuredImage) {
return Padding(
padding: EdgeInsets.symmetric(horizontal: 7),
child: Image.asset(featuredImage),
);
}).toList(),
),
Align(
alignment: Alignment.centerLeft,
child: IconButton(
onPressed: () {
// Use the controller to change the current page
carouselController.previousPage();
},
icon: Icon(Icons.arrow_back),
),
),
Align(
alignment: Alignment.centerRight,
child: IconButton(
onPressed: () {
// Use the controller to change the current page
carouselController.nextPage();
},
icon: Icon(Icons.arrow_forward),
),
),
],
),
),
);
}
}

Related

ElevatedButton Position Changing method

I have an Elevated Button which is on of the bottom of the Page and I am a beginner sorry for this silly doubts but i can't figure out how to change the position of the button I dont know how to try positioned widget too. Kindly help me
I tried positioned widget but couldn't do well can anyone help me with this. here is my full code.
import 'package:flutter/material.dart';
void main() {
runApp(MaterialApp(
home: MyApp(),
));
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Column(
children: [
Expanded(
child: PageView.builder(
itemBuilder: (context, index)=> const OnBoardContent(
image: 'assets/splash-1.png',
description: "All under one roof with different approach"),
),
),
SizedBox(
height: 30,
width: 200,
child: ElevatedButton(
onPressed: (){},
child: const Text("Tap to get started"),
),
),
],
)
),
);
}
}
class OnBoardContent extends StatelessWidget {
const OnBoardContent({
Key? key,
required this.image,
required this.description,
}) : super(key: key);
final String image, description;
#override
Widget build(BuildContext context) {
return Column(
children: [
const SizedBox(
height: 160,
),
const Text("Naz-Kearn",
style: TextStyle(
fontSize: 30,
fontWeight: FontWeight.bold
)),
const Text("A simplify learning App",
style: TextStyle(
fontWeight: FontWeight.normal
),
),
Image.asset(image),
const SizedBox(
height: 50,
),
Text(description,
textAlign: TextAlign.center,
style: const TextStyle(fontWeight: FontWeight.normal),
),
],
);
}
}
Output of the above code
You need your widgets in a stack if you want to use Positioned widget on them :
import 'package:flutter/material.dart';
void main() {
runApp(MaterialApp(
home: MyApp(),
));
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Stack( //wrapped the whole column with a stack so that all the other widgets doesn't get disturbed
children: [
Column(
children: [
Expanded(
child: PageView.builder(
itemBuilder: (context, index)=> const OnBoardContent(
image: 'assets/splash-1.png',
description: "All under one roof with different approach"),
),
),
],
),
Positioned(
top: MediaQuery.of(context).size.height*0.7, //change the 0.7 part to any number you like
child: SizedBox(
height: 30,
width: 200,
child: ElevatedButton(
onPressed: (){},
child: const Text("Tap to get started"),
),
),
),
],
)
),
);
}
}
class OnBoardContent extends StatelessWidget {
const OnBoardContent({
Key? key,
required this.image,
required this.description,
}) : super(key: key);
final String image, description;
#override
Widget build(BuildContext context) {
return Column(
children: [
const SizedBox(
height: 160,
),
const Text("Naz-Kearn",
style: TextStyle(
fontSize: 30,
fontWeight: FontWeight.bold
)),
const Text("A simplify learning App",
style: TextStyle(
fontWeight: FontWeight.normal
),
),
Image.asset(image),
const SizedBox(
height: 50,
),
Text(description,
textAlign: TextAlign.center,
style: const TextStyle(fontWeight: FontWeight.normal),
),
],
);
}
}
try this code, you can use alignment property of the Stack widget to center everything.
SafeArea(
child: Stack(
alignment: Alignment.center, //do this
children: [
You can wrap your button with Padding widget which helps you to add padding as you like
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Column(
children: [
Expanded(
child: PageView.builder(
itemBuilder: (context, index)=> const OnBoardContent(
image: 'assets/splash-1.png',
description: "All under one roof with different approach"),
),
),
Padding(
padding: EdgeInsets.all(8),
child: SizedBox(
height: 30,
width: 200,
child: ElevatedButton(
onPressed: (){},
child: const Text("Tap to get started"),
),
),),
],
)
),
);
}
Firstly please mention what precisely the issue you are facing. If you have a problem with the get started button, what is the expected place for the get started button in the design?
Based on the code given, I'm hoping that the get started button should be at the bottom of the screen with some space below. You have already placed the button at the bottom, but you are not able to give space below.
There are some possible ways, you can use it with the get started button component.
Instead of this,
SizedBox(
height: 30,
width: 200,
child: ElevatedButton(
onPressed: (){},
child: const Text("Tap to get started"),
),
),
Option 1
Use container with margin
Container(
height: 30,
width: 200,
margin: EdgeInsets.only(
bottom: 50,
),
child: ElevatedButton(
onPressed: () {},
child: const Text("Tap to get started"),
),
),
Option 2
Wrap existing SizedBox with padding widget
Padding(
padding: EdgeInsets.only(bottom: 50.0),
child: Sizedbox(
height: 30,
width: 200,
child: ElevatedButton(
onPressed: () {},
child: const Text("Tap to get started"),
),
),
),
Even with some more ways to move the button wherever you need, you can try your own with the following widgets Expanded(), Spacer(), SizedBox(), Positioned() and etc.

How to remove padding of MaterialBanner?

I want to remove the following blue padding from MaterialBanner widget, but it doesn't seem to be customizable. I want to insert an image in the red region.
I looked into MaterialBanner for using across Scaffold widgets because ScaffoldMessenger doesn't allow me to insert widgets other than MaterialBanner.
Is there any suggestion?
dartpad.
import 'package:flutter/material.dart';
void main() {
runApp(MaterialApp(home: Scaffold(body: JustBanner())));
}
class JustBanner extends StatefulWidget {
#override
State<StatefulWidget> createState() {
return _JustBannerState();
}
}
class _JustBannerState extends State<JustBanner> {
#override
Widget build(BuildContext context) {
return Column(
children: [
ElevatedButton(
onPressed: () {
final messenger = ScaffoldMessenger.of(context);
messenger.clearMaterialBanners();
messenger.showMaterialBanner(MaterialBanner(
padding: EdgeInsets.zero,
leadingPadding: EdgeInsets.zero,
leading: const SizedBox.shrink(),
backgroundColor: Colors.blue,
content: Container(
color: Colors.red,
width: 200,
height: 50,
),
actions: const [SizedBox.shrink()]));
},
child: const Text('Banner')),
],
);
}
}
Container(
width: MediaQuery.of(context).size.width,
child: MaterialBanner(
content: Text('Hello'),
actions: [
Icon(Icons.add),
],
),
),
Its no possible without copy and re-create the class, buttonBar always appear:
final Widget buttonBar = Container( // <-- problematic widget
alignment: AlignmentDirectional.centerEnd,
constraints: const BoxConstraints(minHeight: 52.0),
padding: const EdgeInsets.symmetric(horizontal: 8),
child: OverflowBar(
overflowAlignment: widget.overflowAlignment,
spacing: 8,
children: widget.actions,
),
);
final double elevation = widget.elevation ?? bannerTheme.elevation ?? 0.0;
final Color backgroundColor = widget.backgroundColor
?? bannerTheme.backgroundColor
?? theme.colorScheme.surface;
final TextStyle? textStyle = widget.contentTextStyle
?? bannerTheme.contentTextStyle
?? theme.textTheme.bodyText2;
Widget materialBanner = Container(
margin: EdgeInsets.only(bottom: elevation > 0 ? 10.0 : 0.0),
child: Material(
elevation: elevation,
color: backgroundColor,
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Padding(
padding: padding,
child: Row(
children: <Widget>[
if (widget.leading != null)
Padding(
padding: leadingPadding,
child: widget.leading,
),
Expanded(
child: DefaultTextStyle(
style: textStyle!,
child: widget.content,
),
),
if (isSingleRow)
buttonBar, // <----- here
],
),
),
if (!isSingleRow)
buttonBar, // <----- here
if (elevation == 0)
const Divider(height: 0),
],
),
),
);

onTap function not working for Align widgets in Flutter

I have a widget with a GestureDetector inside of Stack having Align as a child(where onTap is registered)
The layout code is,
body: Stack(
children: [
Padding(
padding: EdgeInsets.only(top: 28.0.vs),
child: PageView.builder(
controller: _pageController,
onPageChanged: _changeCurrentSlide,
itemCount: 2,
itemBuilder: (context, index) => Align(
alignment: Alignment.topCenter,
child: Container(
height: 700.h,
child: Card(
elevation: 20,
color: AppColors.black,
child: Container(
width: 350.w,
child: Stack(
overflow: Overflow.visible,
children: [
Text('Hai'),
GestureDetector(
behavior: HitTestBehavior.opaque,
onTap: () { print('hello'); },
child: Align(
alignment: Alignment(0, 1.1),
child: Material(
elevation: 20,
color: AppColors.transparent,
child: Container(
width: 70,
height: 40,
color: AppColors.goldenYellow,
child: Center(
child: Text(
'Next'
),
),
),
),
),
),
],
),
),
),
),
),
),
),
],
),
I need to call a function on tap of Align widget but only half the area of GestureDetector is working and on other half, onTap is not detected
Image for GestureDector, not working
This behavior occurs because the stack checks whether the pointer is inside its bounds before checking whether a child got hit:
If you notice the part of the button which is overflowing or not within the constraints of the Stack does not receive the tap. This is because the Stack widgets first checks whether the hit was inside its bounds before checking whether its child got tapped.
As a workaround you may wrap the parent widget of the Stack with Gesture detector and then check if the hit was within the bounds of your button or the intended widget. Please check the code below, I had to make some changes to your code in order to make my code work. Note if 'clipBehavior: Clip.none,' in my code gives you an error then you may comment it out and use 'overflow: Overflow.visible,' instead. Please check if this code works for you.
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
final Color darkBlue = const Color.fromARGB(255, 18, 32, 47);
void main() {
runApp(
MaterialApp(
theme: ThemeData.dark().copyWith(scaffoldBackgroundColor: darkBlue),
debugShowCheckedModeBanner: false,
home: MyApp(),
),
);
}
class MyApp extends StatefulWidget {
#override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
final List<GlobalKey> _key = <GlobalKey>[];
final PageController _controller = PageController();
int _currentPage = 0;
void onTapDown(
BuildContext context,
TapDownDetails details,
) {
final RenderBox box = context.findRenderObject();
final Offset localOffset = box.globalToLocal(details.globalPosition);
final RenderBox containerBox =
_key[_currentPage].currentContext.findRenderObject();
final Offset containerOffset = containerBox.globalToLocal(localOffset);
final onTap = containerBox.paintBounds.contains(containerOffset);
if (onTap) {
print("hello");
}
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: GestureDetector(
onTapDown: (TapDownDetails details) {
onTapDown(context, details);
},
child: Container(
width: 500,
height: MediaQuery.of(context).size.height,
color: Colors.white,
child: Stack(
children: [
Padding(
padding: EdgeInsets.only(
top: 28.0), // EdgeInsets.only(top: 28.0.vs),
child: PageView.builder(
controller: _controller, //_pageController,
onPageChanged: (val) {
_currentPage = val;
//_changeCurrentSlide();
},
itemCount: 2,
itemBuilder: (context, index) {
_key.add(GlobalKey());
return Align(
alignment: Alignment.topCenter,
child: Container(
height: 600, //700.h,
child: Card(
elevation: 20,
color: Colors.white, // AppColors.black,
child: Container(
width: 350, //350.w,
child: Stack(
//overflow: Overflow.visible,
clipBehavior: Clip.none,
children: [
Text('Hai'),
//GestureDetector(
// behavior: HitTestBehavior.opaque,
// onTap: () { print('hello'); },
// child:
Align(
alignment: Alignment(0, 1.1),
child: Material(
elevation: 20,
color: Colors
.transparent, // AppColors.transparent,
child: Container(
key: _key[index],
width: 70,
height: 40,
color: Colors
.black, //AppColors.goldenYellow,
child: Center(
child: Text('Next'),
),
),
),
),
//),
],
),
),
),
),
);
},
),
),
],
),
),
),
);
}
}

Fade Image.asset when SingleChildScrollView scrolls

I have an image.asset at the top of a Column inside a SingleChildScrollView
I'm trying to achieve that when the users scrolls the scrollView, the image will fade out.
I've tried to to it using the controller property of the scrollView, but I couldn't achieve the opacity change.
Does anyone has an idea what is the most efficient way to do that?
Thank you!
Current Code:
Scaffold(
backgroundColor: Colors.white,
body: SingleChildScrollView(
child: Column(
children: [
Stack(
children: [
Container(
height: _imageTopPosition + _imageHeight,
color: Colors.blue[100],
),
Positioned(
top: _customShapeTopPosition,
child: MyCustomShape(
size: Size(_screenSize.width, _customShapeHeight),
),
),
Positioned(
top: _imageTopPosition,
right: _imageRightPosition,
child: Image.asset( //The image I would like to fade on scroll
'assets/images/image.png',
width: _imageWidth,
height: _imageHeight,
),
),
],
),
Padding(
padding: EdgeInsets.only(top: _screenSize.height * 0.05),
),
Text('Some Text'),
],
),
),
);
Just create an animation controller and update its value according to the scroll controller
full working example:
import 'package:flutter/material.dart';
class MyPage extends StatefulWidget {
#override
_MyPageState createState() => _MyPageState();
}
class _MyPageState extends State<MyPage> with SingleTickerProviderStateMixin{
var _controller=ScrollController();
AnimationController animation;
#override
void initState() {
super.initState();
animation=AnimationController(vsync:this);
_controller.addListener(() {
animation.value=1-_controller.offset/_controller.position.maxScrollExtent;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
body:Center(
child:Container(
width: 300,
height: 300,
child: SingleChildScrollView(
controller: _controller,
child:FadeTransition(
opacity: animation,
child:Container(
width: 300,
height: 600,
color: Colors.red,
)
)
),
),
)
);
}
}

Add New Widget on button click with a finction that returns a widget

Hello i am new to Flutter and I want to know if there is a way to add new Widgets with a button click.
I looked into many stack overflow similar Questions. but due to my poor knowledge most of them seems complex to me and hard to grasp. All i need to do is add some containers below old build containers
class MedPreC extends StatefulWidget {
#override
_MedPreCState createState() => _MedPreCState();
}
Widget returnWidget() {
return Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
width: double.infinity,
height: 40,
color: Colors.red,
),
);
}
class _MedPreCState extends State<MedPreC> {
var child2 = Column(
children: [
returnWidget(),
],
);
#override
Widget build(BuildContext context) {
return Container(
child: Column(
children: [
Expanded(
child: Container(
color: Colors.yellow,
height: 400,
width: double.infinity,
child: child2,
),
),
RaisedButton(
child: Text("Add"),
onPressed: () {
setState(() {
//
child2.children.add(returnWidget());
//
});
},
)
],
),
);
}
}
This is the code i have made so far. This whole code will be called inside another class with scafold and stuffs
returnWidget() Returns a red container
child2 is a Column called inside a yellow Container with one red container as one of its children
i need to add more redcontainers on button press
Thank you thats all
Try this
class AddWidget extends StatefulWidget {
#override
_AddWidgetState createState() => _AddWidgetState();
}
class _AddWidgetState extends State<AddWidget> {
List<Widget> containerList = [];
Widget returnWidget() {
return Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
width: double.infinity,
height: 40,
color: Colors.red,
),
);
}
#override
Widget build(BuildContext context) {
return Container(
child: Column(
children: [
Expanded(
child: Container(
color: Colors.yellow,
height: 400,
width: double.infinity,
child: Column(children: containerList),
),
),
RaisedButton(
child: Text("Add"),
onPressed: () {
setState(() {
containerList.add(returnWidget());
});
},
)
],
),
);
}
}
For this you need also check the overflow of widget. So you can check the below code.
import 'package:flutter/material.dart';
class MedPreC extends StatefulWidget {
#override
_MedPreCState createState() => _MedPreCState ();
}
class _MedPreCState extends State<MedPreC > {
List<Widget> data = [];
Widget CustomWidget() {
return Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
width: double.infinity,
height: 40,
color: Colors.red,
),
);
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
children: [
Container(
color: Colors.yellow,
height: MediaQuery.of(context).size.height - 60,
width: double.infinity,
child: SingleChildScrollView(child: Column(children: data)),
),
],
),
bottomNavigationBar: Container(
height: 60,
width: MediaQuery.of(context).size.width,
color: Colors.white,
child: InkWell(
child: Center(
child: Container(
color: Colors.red,
width: 100,
height: 40,
child: Center(child: Text("Add"))),
),
onTap: () {
setState(() {
data.add(CustomWidget());
});
},
),
),
);
}
}