I have a carousel, two iconButtons in a Positioned Layout, gridView and 2 other positioned layouts All Inside A Stack Layout.
The onPressed() functions on the iconButtons specifically or on any of the elements general do not get triggered. I figured out that the issue is because of the Parent Stack Layout because when place them outside of it the onPressed works.
I need the Stack Layout for the design so im wondering if there is an alternative for it.
Here's an example of the code:
child: Stack(
children: <Widget>[
Container(
child: Column(
children: <Widget>[
carouselSlider = CarouselSlider(
height: 270.0,
initialPage: 0,
viewportFraction: 1.0,
aspectRatio: 1.0,
enlargeCenterPage: false,
autoPlay: true,
reverse: false,
enableInfiniteScroll: true,
autoPlayInterval: Duration(seconds: 2),
autoPlayAnimationDuration:
Duration(milliseconds: 2000),
pauseAutoPlayOnTouch: Duration(seconds: 10),
scrollDirection: Axis.horizontal,
onPageChanged: (index) {
setState(() {
current = index;
});
},
items: carouselImages.map((i) {
return Builder(
builder: (BuildContext context) {
return Container(
child: GestureDetector(
// behavior:
// HitTestBehavior.translucent,
child: Image.asset(
i,
fit: BoxFit.cover,
),
onTap: () {
// Navigator.push<Widget>(
// context,
// MaterialPageRoute(
// builder: (context) => ImageScreen(i),
// ),
// );
}));
},
);
}).toList(),
),
SizedBox(
height: 20,
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children:
map<Widget>(carouselImages, (index, url) {
return Container(
width: 10.0,
height: 10.0,
margin: EdgeInsets.symmetric(
vertical: 10.0, horizontal: 2.0),
decoration: BoxDecoration(
shape: BoxShape.circle,
color: current == index
? Color.fromRGBO(221, 40, 42, 0.7)
: Colors.white,
),
);
}),
),
],
),
),
Positioned(
right: 5,
top: 10,
child: IconButton(
icon: Icon(Icons.menu),
color: Color.fromRGBO(221, 40, 42, 0.7),
iconSize: 20.0,
onPressed: () {
print('Clicked');
scaffolddKey.currentState.openDrawer();
},
),
),
The solution is to wrap all of your widgets that are not supposed to receive tap events in IgnorePointer widget.
If your CarouselSlider is not supposed to receive tap events then wrap it and all other widgets that are not supposed to receive tap events in IgnorePointer widget.
Related
i created a carousel containing three different images. the problem is these images are not taking the full length of my current screen. i have tried setting the width in the image and even setting the aspect ratio and viewport in carousel options but the outcome is still the same. help would be very much appreciated. here is the code.
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: 400.0),
child: Center(
child:SvgPicture.asset('assets/iconImages/Button.svg'),
),
),
],
),
Image.asset('assets/images/leeloo.jpeg', width: double.infinity,),
Image.asset('assets/images/ayaka.jpeg', width: double.infinity,),
];
#override
Widget build(BuildContext context) {
return DefaultTabController(
length: 5,
child: Column(
children: [
Stack(
children: [
CarouselSlider.builder(
options: CarouselOptions(
viewportFraction: 1,
aspectRatio: 16/9,
height: MediaQuery.of(context).size.height*0.78,
autoPlay: false,
initialPage: 0,
enableInfiniteScroll: false,
enlargeCenterPage: true,
onPageChanged: (index, reason){
setState(() {
_activeIndex = index;
});
}
),
itemCount: _images.length,
itemBuilder: (BuildContext context, int index, int realIndex) {
return GestureDetector(
onTap: (){
Navigator.of(context).pushNamedAndRemoveUntil(BlackScreen.routeName, (route) => false);
},
child: Align(
alignment: Alignment.bottomCenter,
child:Container(
child: _images[index]
),
),
);
},
),
Set fit to your image like this:
Image.asset('assets/images/leeloo.jpeg', width: double.infinity,fit: BoxFit.cover),
Please try this
FittedBox(
child: Image.asset('foo.png'),
fit: BoxFit.fill,
)
I am trying to achieve something like this in the video https://youtu.be/tpfP7wlHCxw , when the slider image will change the below text will also change like fat in the video example, and also one container box on the front image only
I tried the carousel_slider and use the stack for box frame that is in the video but frame size and image sizes not adjustable
and the important thing is how can I change the below text on change image and slider should not rotate it will stop if the last image comes
here is my code
import 'package:carousel_slider/carousel_slider.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:trainer_app/color.dart';
class FatGet extends StatefulWidget {
#override
_GetAgeState createState() => _GetAgeState();
}
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',
'https://images.unsplash.com/photo-1523205771623-e0faa4d2813d?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjEyMDd9&s=89719a0d55dd05e2deae4120227e6efc&auto=format&fit=crop&w=1953&q=80',
'https://images.unsplash.com/photo-1508704019882-f9cf40e475b4?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjEyMDd9&s=8c6e5e3aba713b17aa1fe71ab4f0ae5b&auto=format&fit=crop&w=1352&q=80',
'https://images.unsplash.com/photo-1519985176271-adb1088fa94c?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjEyMDd9&s=a0c8d632e977f94e5d312d9893258f59&auto=format&fit=crop&w=1355&q=80'
];
class _GetAgeState extends State<FatGet> {
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: background,
body: SafeArea(
child: Column(
children: [
SizedBox(height: 50,),
Center(
child: Stack(
children: [
Container(
height: 5,
width: MediaQuery.of(context).size.height/2,
color: backcolor,
),
Container(
height: 5,
width: MediaQuery.of(context).size.height/2.5,
color: textcolor,
),
],
),
),
SizedBox(height: 50,),
Text('Estimated your current',style: TextStyle(fontFamily: font1,fontSize: 30,fontWeight: FontWeight.w300),),
Text('body Fat Percentage?',style: TextStyle(fontFamily: font1,fontSize: 30,fontWeight: FontWeight.w300),),
SizedBox(height: 100,),
// Image.asset('assets/fat2.png'),
Stack(
children: [
Center(
child: Container(
margin: EdgeInsets.only(bottom: 15),
width: 350,
height: 260,
decoration: BoxDecoration(
border: Border.all(color: textcolor,width: 3, )
),
),
),
Column(
children: [
SizedBox(height: 7,),
CarouselSlider(
options: CarouselOptions(),
items: imgList.map((item) => Container(
child: Padding(
padding: const EdgeInsets.only(left: 5,right: 5),
child: Image.network(item, fit: BoxFit.cover,height: 20,),
),
)).toList(),
),
],
),
],
),
Spacer(),
Container(
margin: EdgeInsets.only(bottom: 30),
width: MediaQuery.of(context).size.width/1.2,
height: 50,
child: ClipRRect(
borderRadius: BorderRadius.circular(50),
child: RaisedButton(
child: Text('Next',style: TextStyle(color: Colors.white,fontFamily: font1,fontWeight: FontWeight.w400,fontSize: 20),),
onPressed: (){
Navigator.pushNamed(context, "Exercise");
},
color: textcolor,
),
),
)
],
),
),
);
}
}
With onPageChange, you can take the value of a variable and return it from a function you send. I think it will work.
Define each text as companent.
Check the index of images with a variable
Write the function that returns value according to the parameter sent.
Call the function and give the control variable
for slider should not rotate.. see comment 1 in the code
for change the below text on change.. see comment 2
CarouselSlider(
items: items,
options: CarouselOptions(
height: 400,
aspectRatio: 16/9,
viewportFraction: 0.8,
initialPage: 0,
enableInfiniteScroll: false, // (1) Set to false
reverse: false,
autoPlay: true,
autoPlayInterval: Duration(seconds: 3),
autoPlayAnimationDuration: Duration(milliseconds: 800),
autoPlayCurve: Curves.fastOutSlowIn,
enlargeCenterPage: true,
onPageChanged: changeActiveImageText(), // (2) Set up your function here
scrollDirection: Axis.horizontal,
)
)
Function will look something like this
changeActiveImageText(){
// your method of changing the text
setState((){})
}
I really need your help.
I'm pretty sure that using CustomPaint would be the solution here. but I can't find the source code of Flutter's CustomPaint video.
I'm also aware that I must use drawPath to achieve this. but I can't find any resources on how to convert my SVG to path.
my scenario is this:
I have an image, and I also have my SVG wrapped in Draggable so I can place it anywhere on the image.
I tried using RepaintBoundaries but it doesn't include the SVG even if I try to place it as a parent widget.
I'd appreciate any help.
EDIT :
I am converting specifically, A pdf file to images.
Stack(
children: <Widget>[
Positioned(
child: Text(
imageList.length == 0
? "$currentPage / --"
: "$currentPage / ${imageList.length}",
style: TextStyle(color: Colors.white),
),
top: 10,
right: 10,
),
FutureBuilder(
future: getDocument,
builder: (context, snapshot) {
if (!snapshot.hasData) {
return Center(
child: FadingText(
'Rendering File ...',
style: TextStyle(color: Colors.black, fontSize: 20),
),
);
}
return CarouselSlider.builder(
itemCount: snapshot.data.length,
options: CarouselOptions(
viewportFraction: 1,
autoPlay: false,
aspectRatio: 0.5,
enableInfiniteScroll: false,
onPageChanged: (index, reason) {
setState(() {
currentPage = index + 1;
print(currentPage);
});
}),
itemBuilder: (context, index) {
return Container(
child: Image.memory(snapshot.data[index]),
);
},
);
}),
Positioned(
top: position.dy,
left: position.dx,
child: Center(
child: Container(
padding: EdgeInsets.all(10),
child: Draggable(
child: Container(
width: 120,
height: 70,
child: Center(
child: SvgPicture.asset("assets/signature.svg"),
),
),
childWhenDragging: Container(
width: 120,
height: 70,
child: Center(
child: Opacity(
opacity: 0.2,
child: SvgPicture.asset("assets/signature.svg"),
),
),
),
feedback: Container(
child: Center(
child: SvgPicture.asset("assets/signature.svg"),
),
width: 120,
height: 70,
),
onDraggableCanceled:
(Velocity velocity, Offset offset) {
setState(() => position = offset);
print(
"X Position : ${position.dx} | Y Position : ${position.dy}");
//_capturePng();
showDialog(
barrierDismissible: true,
context: context,
builder: (_) => ViewDocumentDialog(
x: double.parse((position.dx).toStringAsFixed(2)),
y: double.parse((position.dy).toStringAsFixed(2)),
images: encodeImageList,
page: currentPage,
),
);
},
),
),
),
)
],
)),
How can I achieve such behavior in Flutter? any widget or plugins example?
See this gif
I tried carousels plugins and viewPagers widgets but couldn't make it work.
here is the sample code I started with.
CarouselSlider(
items: [
Container(child: Text("Complimentary"), width: double.infinity),
Container(child: Text("Complimentary"), width: double.infinity),
Container(child: Text("Complimentary"), width: double.infinity),
Container(child: Text("Complimentary"), width: double.infinity),
Container(child: Text("Complimentary"), width: double.infinity),
],
options: CarouselOptions(
height: 39 * resizeFactor,
autoPlay: false,
enlargeCenterPage: true,
autoPlayInterval: Duration(seconds: 10),
),
),
I made it work by using both Swiper and Row of arrows, with the following code:
Stack(
children: [
Container(
height: 39 * resizeFactor,
child: Swiper(
itemCount: 4,
itemBuilder: (context, index) => getIndexWidget(index), // -> Text widget.
viewportFraction: 0.4,
onIndexChanged: (value) {
setState(() => carouselIndex = value);
},
loop: false,
controller: swiperController,
),
),
Container(
padding: EdgeInsets.symmetric(horizontal: 30 * resizeFactor),
height: 39 * resizeFactor,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
getIndicatorWidget(false), // back arrow icon.
getIndicatorWidget(true), // forward arrow icon.
],
),
),
],
),
Thank you for your contributions.
I have a ListView where I want to implement a nice way to delete list items using a bottom sheet with actions on. Initially I went down the path of simply calling showBottomSheet() in the onLongPress event handler for my list items, which would successfully open a bottom sheet with my action buttons on. However, this would automatically add a back button to the AppBar which is not what I want.
I then went down the route of trying out animations, such as SlideTransition and AnimatedPositioned:
class FoldersListWidget extends StatefulWidget {
#override
_FoldersListWidgetState createState() => _FoldersListWidgetState();
}
class _FoldersListWidgetState extends State<FoldersListWidget>
with SingleTickerProviderStateMixin {
double _bottomPosition = -70;
#override
Widget build(BuildContext context) {
return Stack(
children: [
FutureBuilder<List<FolderModel>>(
future: Provider.of<FoldersProvider>(context).getFolders(),
builder: (context, snapshot) {
if (!snapshot.hasData) {
return Center(
child: CircularProgressIndicator(),
);
}
return ListView.builder(
itemCount: snapshot.data.length,
itemBuilder: (context, i) {
final folder = snapshot.data[i];
return Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(15),
),
margin: EdgeInsets.symmetric(vertical: 5, horizontal: 10),
elevation: 1,
child: ListTile(
title: Text(folder.folderName),
leading: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Container(
width: 50,
child: Consumer<FoldersProvider>(
builder:
(BuildContext context, value, Widget child) {
return value.deleteFolderMode
? CircularCheckBox(
value: false,
onChanged: (value) {},
)
: Icon(
Icons.folder,
color: Theme.of(context).accentColor,
);
},
),
),
],
),
subtitle: folder.numberOfLists != 1
? Text('${folder.numberOfLists} items')
: Text('${folder.numberOfLists} item'),
onTap: () {},
onLongPress: () {
Provider.of<FoldersProvider>(context, listen: false)
.toggleDeleteFolderMode(true); // removes fab from screen
setState(() {
_bottomPosition = 0;
});
},
),
);
},
);
},
),
AnimatedPositioned(
bottom: _bottomPosition,
duration: Duration(milliseconds: 100),
child: ClipRRect(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(25),
topRight: Radius.circular(25),
),
child: Container(
height: 70,
width: MediaQuery.of(context).size.width,
color: Theme.of(context).colorScheme.surface,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
Expanded(
child: IconAboveTextButton(
icon: Icon(Icons.cancel),
text: 'Cancel',
textColour: Colors.black,
opacity: 0.65,
onTap: () => setState(() {
_bottomPosition = -70;
}),
),
),
VerticalDivider(
color: Colors.black26,
),
Expanded(
child: IconAboveTextButton(
icon: Icon(Icons.delete),
text: 'Delete',
textColour: Colors.black,
opacity: 0.65,
),
),
],
),
),
),
),
],
);
}
}
This slides the bottom Container on and off the screen but my issue is that it covers the last list item:
Could anyone suggest a better way of doing this or simply a way to adjust the height of the ListView so that when the Container slides up, the ListView also slides up.
Wrap ListView.builder inside a container and set its bottom padding as (70+16)
70 (height of bottom sheet), 16 (some default padding to make it look better if you like).
return Container(
padding: EdgetInset.ony(bottom: (70+16)),
child:ListView.builder(
itemCount: snapshot.data.length,
itemBuilder: (context, i) {
.....
.....