How to Implement a manual carousel slider in Flutter? - flutter

I am creating a product image carousel which contains pictures of shoes where the user can change the image to be viewed by selecting a different color.
The user can manually scroll through the images without an issue,however when I try to manually change the displayed carousel image, only the indicator changes, but the image remains on the first image.
class DetailsPage extends StatefulWidget {
final String url;
final String title;
final int index;
DetailsPage({this.url, this.title, this.index});
#override
_DetailsPageState createState() => _DetailsPageState();
}
class _DetailsPageState extends State<DetailsPage> {
List imgList = [
'https://i.dlpng.com/static/png/6838599_preview.png',
'https://www.manelsanchez.pt/uploads/media/images/nike-air-force-max-ii-blue-fury-18.jpg',
'https://www.vippng.com/png/detail/30-302339_nike-women-running-shoes-png-image-transparent-background.png',
];
int _current = 0;
String selected = "grey";
List<T> map<T>(List list, Function handler) {
List<T> result = [];
for (var i = 0; i < list.length; i++) {
result.add(handler(i, list[i]));
}
return result;
}
final CarouselController _buttonCarouselController = CarouselController();
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Theme.of(context).canvasColor,
appBar: AppBar(
title: Center(
child: Text(
'Details',
style: TextStyle(
fontFamily: 'OpenSansLight',
fontSize: 26,
color: Theme.of(context).textTheme.headline1.color),
),
),
body: ListView(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
//Carousel Slider
CarouselSlider.builder(
options: CarouselOptions(
carouselController: _buttonCarouselController,
height: 200.0,
enlargeCenterPage: true,
enlargeStrategy: CenterPageEnlargeStrategy.height,
initialPage: 0,
reverse: false,
autoPlay: false,
enableInfiniteScroll: false,
scrollDirection: Axis.horizontal,
onPageChanged: (index, fn) {
setState(() {
_current = index;
});
}),
itemCount: imgList.length,
itemBuilder: (BuildContext context, int index) =>
Builder(builder: (BuildContext context) {
return Image.network(
imgList[index],
fit: BoxFit.contain,
);
}),
),
SizedBox(height: 10),
//Indicator to show current index of images
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: map<Widget>(imgList, (index, url) {
return Container(
width: 30.0,
height: 2.0,
margin: EdgeInsets.symmetric(
vertical: 10.0, horizontal: 4.0),
decoration: BoxDecoration(
shape: BoxShape.rectangle,
borderRadius: BorderRadius.circular(10.0),
color: _current == index
? Colors.deepPurple
: Colors.grey,
),
);
}),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
height: 30,
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text('Color',
style: TextStyle(
fontFamily: 'OpenSansLight',
fontSize: 24)),
],
),
),
),
Flexible(
fit: FlexFit.loose,
child: Container(
width: width,
height: 120,
child: ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: imgList.length,
itemBuilder: (BuildContext context, int index) {
//Color selector from images to manually control the carousel
return GestureDetector(
onTap: () {
setState(() {
selected = imgList[index];
_current = index;
_buttonCarouselController
.animateToPage(_current);
print('I HAVE SELECTED $selected');
});
},
child: ColorTicker(
image: imgList[index],
selected: selected == imgList[index],
),
);
},
),
),
),
],
),
);
Color Ticker Widget
class ColorTicker extends StatelessWidget {
final image;
final bool selected;
ColorTicker({this.image, this.selected});
#override
Widget build(BuildContext context) {
print(selected);
return Container(
margin: EdgeInsets.all(5),
width: 100,
height: 100,
decoration: BoxDecoration(
image: DecorationImage(
fit: BoxFit.scaleDown, image: NetworkImage(image)),
shape: BoxShape.circle,
border: selected
? Border.all(color: Colors.deepPurple, width: 3)
: Border.all(color: Colors.grey[500])),
// color: color.withOpacity(0.7)),
child: selected
? Center(child: Icon(Icons.check, size: 40, color: Colors.deepPurple))
: Container(),
);
}
}
I've tried all I could from the documentation : https://pub.dev/packages/carousel_slider/example
But I kept getting an error
Unhandled Exception: NoSuchMethodError: The getter 'options' was called on null

I am almost embarassed at my mistake.
In the configuration of the slider, I placed the controller in the wrong place.
I put the controller inside the Carousel options instead of under CarouselSlider
CarouselSlider(
carouselController: _buttonCarouselController,
options: CarouselOptions(
... ))
It now works :)

Related

Find the width of every single item in list in flutter

I need to develope feature which paint the text by syllables (like screenshot shows). Bows and dots represent syllables (dot - 1 letter syllable, bow - 2 letter syllable). The painting is provided by dragging of green slider.
There is a variant of getting syllable position with the help of GlobalKey. I use the method List.generate for creating numerous GlobalKeys but get the exception Multiple widgets used the same GlobalKey. How can help me to resolve this task?
There is method for creating Row of Columns which include letter and bow or dot.
List<Widget> createDotAndBows(String sentence, List<GlobalKey> keys) {
DetailedScreenBloc _bloc = DetailedScreenBloc();
List<String> syllablesRow = [];
List<Widget> dotAndBows = [];
List<String> splittedText = sentence.split(' ');
for (int i = 0; i < splittedText.length; i++) {
syllablesRow.addAll(_bloc.syllables(splittedText[i]));
}
_syllablesTotal.add(syllablesRow.length);
for (int index = 0; index < syllablesRow.length; index++) {
dotAndBows.add(
(syllablesRow[index] != ' ')
? IntrinsicWidth(
key: keys[index],
child: Center(
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Padding(
padding: const EdgeInsets.only(
bottom: FairyTaleSizes.tinyPadding4,
),
child: Text(
syllablesRow[index],
style: FairyTaleStyle(
fontWeight: FontWeight.w800,
fontSize: getProportionateScreenWidth(22),
color: FairyTaleColors.fullBlack,
),
textAlign: TextAlign.center,
maxLines: 1,
),
),
(_bloc.getSyllableType(syllablesRow[index]) == 2)
? Padding(
padding: const EdgeInsets.symmetric(
horizontal: FairyTaleSizes.theMostTinyPadding2,
),
child: CustomPaint(
painter: BowPainter(),
child: Center(
child: Container(
height: getProportionateScreenHeight(20),
),
),
),
)
: (_bloc.getSyllableType(syllablesRow[index]) == 1)
? Center(
child: Container(
height: getProportionateScreenHeight(23),
width: getProportionateScreenHeight(23),
decoration:
const BoxDecoration(shape: BoxShape.circle, color: FairyTaleColors.fullBlack),
),
)
: Container(),
],
),
),
)
: Text(
' ',
key: keys[index],
),
);
}
return dotAndBows;
}
This is the implementation of the method above in UI
class DetailedScreen extends StatefulWidget {
final String? detailedBanner;
final List<String>? fullText;
const DetailedScreen({this.detailedBanner, this.fullText});
#override
State<DetailedScreen> createState() => _DetailedScreenState();
}
class _DetailedScreenState extends State<DetailedScreen> {
final ItemScrollController _itemScrollController = ItemScrollController();
final ItemPositionsListener _itemPositionsListener = ItemPositionsListener.create();
int currentIndex = 1;
final _bloc = DetailedScreenBloc();
List<GlobalKey> keysList = [];
final GlobalKey _sliderKey = GlobalKey();
#override
void initState() {
super.initState();
}
#override
void dispose() {
super.dispose();
_bloc.dispose();
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: SizedBox(
height: MediaQuery.of(context).size.height,
child: SingleChildScrollView(
physics: const NeverScrollableScrollPhysics(),
child: Stack(
children: <Widget>[
Container(
width: SizeConfig.screenWidth,
height: SizeConfig.screenHeight,
decoration: const BoxDecoration(
color: FairyTaleColors.lightGold,
),
),
Column(
children: [
Align(
alignment: Alignment.topCenter,
child: Container(
height: SizeConfig.screenHeight / 2,
width: SizeConfig.screenWidth,
decoration: BoxDecoration(
image: DecorationImage(
image: Image.asset(widget.detailedBanner ?? '').image,
fit: BoxFit.fitWidth,
),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Align(
alignment: Alignment.topLeft,
child: ArrowWidget(
height: getProportionateScreenHeight(84),
width: getProportionateScreenWidth(36),
isForward: false,
onTap: () => Navigator.of(context).pop(),
),
),
StreamBuilder<bool>(
stream: _bloc.isVoiceOnStream,
builder: (context, snapshot) {
bool? _isVoiceOn = snapshot.data;
return Padding(
padding: const EdgeInsets.only(
right: FairyTaleSizes.bigHorizontalPadding36,
),
child: Align(
alignment: Alignment.topRight,
child: VoiceSwitcher(
isVoiceOn: _isVoiceOn,
onPressed: () {
if (_isVoiceOn != null && _isVoiceOn) {
_bloc.switchVoice(false);
} else {
_bloc.switchVoice(true);
}
}),
),
);
}),
],
),
),
),
Padding(
padding: const EdgeInsets.only(
top: FairyTaleSizes.middleHorizontalPadding22,
),
child: Stack(
children: [
StreamBuilder<int>(
stream: _bloc.syllablesTotalStream,
builder: (context, snapshot) {
return SizedBox(
height: MediaQuery.of(context).size.height,
child: ScrollablePositionedList.builder(
shrinkWrap: true,
padding: const EdgeInsets.only(
bottom: FairyTaleSizes.twoHundredPadding216,
),
physics: const NeverScrollableScrollPhysics(),
itemScrollController: _itemScrollController,
itemPositionsListener: _itemPositionsListener,
itemCount: widget.fullText!.length,
itemBuilder: (_, index) {
int total = snapshot.data ?? 0;
keysList.addAll(
List.generate(
total,
(index) => GlobalKey(),
),
);
print('$index - $keysList');
return Container(
padding: const EdgeInsets.only(
bottom: FairyTaleSizes.itemsMassivePadding140,
),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: _bloc.createDotAndBows(
widget.fullText![index],
keysList,
),
),
);
},
),
);
}),
StreamBuilder<double>(
initialData: 0.0,
stream: _bloc.shadowPositionStream,
builder: (context, snapshot) {
double _position = snapshot.data ?? 0.0;
return Positioned(
left: _position,
child: Container(
color: FairyTaleColors.lightGold.withOpacity(0.9),
height: getProportionateScreenWidth(23),
width: MediaQuery.of(context).size.width,
),
);
}),
StreamBuilder<List>(
stream: CombineLatestStream.list([
_bloc.sliderValueStream,
_bloc.shadowPositionStream,
]),
builder: (context, snapshot) {
double _sliderValue = snapshot.data?[0] ?? 0.0;
double _shadowPosition = snapshot.data?[1] ?? 0.0;
return Padding(
padding: const EdgeInsets.symmetric(
vertical: FairyTaleSizes.hundredPadding100,
horizontal: FairyTaleSizes.massivePadding64,
),
child: SliderTheme(
data: const SliderThemeData(
trackShape: GradientRectSliderTrackShape(),
trackHeight: 14.0,
thumbShape: GradientSliderThumbShape(
enabledThumbRadius: 16,
pressedElevation: 5.1,
),
),
child: Slider(
key: _sliderKey,
min: 0.0,
max: 200.0,
value: _sliderValue,
inactiveColor: FairyTaleColors.inactiveGrey,
onChanged: (value) {
_sliderValue = value;
_shadowPosition = value * 4.5;
_bloc.changeSliderValue(_sliderValue);
_bloc.stepBySyllable(keysList);
// _bloc.changeShadowPosition(_shadowPosition);
},
onChangeEnd: (value) {
if (value == 200) {
keysList.clear();
_bloc.changeSliderValue(0.0);
_shadowPosition = 0;
_bloc.scrollString(_itemScrollController, currentIndex);
_bloc.changeShadowPosition(0.0);
currentIndex++;
}
},
),
),
);
}),
],
),
),
],
),
],
),
),
),
);
}
}

How to scroll with NestedScrollView to use stack Circle Avatar over SliverAppBar?

I am dealing with a Flutter project recently and I have such a problem.
See photo 1: here's my code: the photo and text should be between the TabBar widget and the red background like in design (blue).
Here you can see my actual code:
class Main
body: NestedScrollView(
headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) {
return <Widget>[
PortfolioSliverAppBar(_pages[_tabController.index].item1),
SliverPersistentHeader(
delegate: SliverPersistentHeaderDelegateImpl(
tabBar: TabBar(
padding: EdgeInsets.only(top: 15.0),
labelColor: Colors.black,
indicatorColor: Colors.black,
indicator: BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(18)),
color: Colors.blue),
controller: _tabController,
tabs: _pages
.map<Tab>((Tuple3 page) => Tab(text: page.item1))
.toList(),
),
),
),
];
},
body: Container(
margin: EdgeInsets.only(top: 20.0),
child: TabBarView(
controller: _tabController,
children: _pages.map<Widget>((Tuple3 page) => page.item2).toList(),
),
),
class Silver
class SliverPersistentHeaderDelegateImpl extends SliverPersistentHeaderDelegate {
final TabBar tabBar;
final Color color;
const SliverPersistentHeaderDelegateImpl({
Color color = Colors.transparent,
#required this.tabBar,
}) : this.color = color;
#override
Widget build(BuildContext context, double shrinkOffset, bool overlapsContent) {
return Container(
color: color,
child: tabBar,
);
}
See photo 2: here's the given design:
my view
the actual UI
Thanks a lot!
Please refer to below code
class NestedScrollWithTabs extends StatefulWidget {
const NestedScrollWithTabs({Key key}) : super(key: key);
#override
_NestedScrollWithTabsState createState() => _NestedScrollWithTabsState();
}
class _NestedScrollWithTabsState extends State<NestedScrollWithTabs>
with TickerProviderStateMixin {
var animation;
var controller;
#override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
body: DefaultTabController(
length: 2,
child: NestedScrollView(
physics: NeverScrollableScrollPhysics(),
headerSliverBuilder: (headerCtx, innnerBoxIsScrolled) {
if (innnerBoxIsScrolled) {
/* Animation */
controller = AnimationController(
vsync: this,
duration: Duration(
seconds: 1,
),
);
animation = Tween(
begin: 0.0,
end: 1.0,
).animate(controller);
/* Animation */
controller.forward();
}
return <Widget>[
SliverAppBar(
expandedHeight: ScreenUtil().setHeight(185.0),
floating: false,
pinned: true,
backgroundColor: Colors.white,
automaticallyImplyLeading: false,
titleSpacing: 0.0,
centerTitle: true,
elevation: 0.0,
leadingWidth: 0.0,
title: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
if (innnerBoxIsScrolled != null &&
innnerBoxIsScrolled == true)
FadeTransition(
opacity: animation,
child: Text(
"Title",
style: TextStyle(
color: Colors.black,
fontSize: 22,
fontWeight: FontWeight.bold,
),
),
),
],
),
flexibleSpace: FlexibleSpaceBar(
background: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Stack(
alignment: Alignment.center,
clipBehavior: Clip.none,
children: [
Image.network(
"https://images.pexels.com/photos/10181294/pexels-photo-10181294.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500" ??
"",
fit: BoxFit.fitWidth,
height: ScreenUtil().setHeight(126.0),
width: ScreenUtil().screenWidth,
filterQuality: FilterQuality.low,
loadingBuilder: (BuildContext context,
Widget child,
ImageChunkEvent loadingProgress) {
if (loadingProgress == null) return child;
return Container(
height: ScreenUtil().setHeight(126.0),
width: ScreenUtil().screenWidth,
color: Colors.grey,
);
},
errorBuilder: (context, error, stackTrace) {
return SizedBox(
height: ScreenUtil().setHeight(126.0),
width: ScreenUtil().screenWidth,
child: Container(
width: ScreenUtil().screenWidth,
),
);
},
),
Positioned(
top: ScreenUtil().setHeight(92.0),
// left: ScreenUtil().setWidth(20.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
CircleAvatar(
backgroundColor: Colors.transparent,
radius: 30.0,
child: ClipRRect(
borderRadius: BorderRadius.circular(
45.0,
),
child: Image.network(
"https://images.pexels.com/photos/10181294/pexels-photo-10181294.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500" ??
"",
fit: BoxFit.fill,
height: ScreenUtil().setHeight(72.0),
width: ScreenUtil().screenWidth,
filterQuality: FilterQuality.low,
loadingBuilder: (BuildContext context,
Widget child,
ImageChunkEvent loadingProgress) {
if (loadingProgress == null)
return child;
return Container(
height:
ScreenUtil().setHeight(72.0),
width: ScreenUtil().screenWidth,
color: Colors.grey,
);
},
errorBuilder:
(context, error, stackTrace) {
return SizedBox(
height:
ScreenUtil().setHeight(72.0),
width: ScreenUtil().screenWidth,
child: Container(
width: ScreenUtil().screenWidth,
),
);
},
),
),
),
Text("Name"),
Text("Place"),
],
),
),
],
),
],
),
),
),
SliverOverlapAbsorber(
handle: NestedScrollView.sliverOverlapAbsorberHandleFor(
headerCtx),
sliver: SliverPersistentHeader(
delegate: SliverAppBarDelegate(TabBar(
labelColor: Colors.blue,
unselectedLabelColor: Colors.black,
labelStyle: TextStyle(
fontSize: 15.0,
),
unselectedLabelStyle: TextStyle(
fontSize: 15.0,
),
labelPadding: EdgeInsets.zero,
indicatorColor: Colors.blue,
indicatorPadding: EdgeInsets.zero,
physics: NeverScrollableScrollPhysics(),
tabs: [
Tab(
text: "Tab 1",
),
Tab(
text: "Tab 2",
),
],
)),
pinned: false,
),
),
];
},
body: TabBarView(
children: [
/* Tab 1 */
Container(
color: Colors.white,
child: ListView.builder(
itemCount: 100,
physics: NeverScrollableScrollPhysics(),
shrinkWrap: true,
itemBuilder: (BuildContext context, int index) {
return Padding(
padding: const EdgeInsets.all(4.0),
child: Text("Index value: $index"),
);
},
),
),
/* Tab 2 */
Container(
color: Colors.white,
child: ListView.builder(
itemCount: 10,
physics: NeverScrollableScrollPhysics(),
shrinkWrap: true,
itemBuilder: (BuildContext context, int index) {
return Padding(
padding: const EdgeInsets.all(4.0),
child: Text("Index value of Tab 2: $index"),
);
},
),
),
],
),
),
),
),
);
}
}
class SliverAppBarDelegate extends SliverPersistentHeaderDelegate {
SliverAppBarDelegate(this.tabBars);
final TabBar tabBars;
#override
double get minExtent => 60.0;
#override
double get maxExtent => 60.0;
#override
Widget build(
BuildContext context, double shrinkOffset, bool overlapsContent) {
// shinkOffsetPerValue.value = shrinkOffset;
return new Container(
color: Colors.white,
child: Column(
children: [
tabBars,
],
),
);
}
#override
bool shouldRebuild(SliverAppBarDelegate oldDelegate) {
return false;
}
}

thrown during paint(): 'package:flutter/src/rendering/sliver_multi_box_adaptor.dart': Failed assertion: line 544 pos 12: 'child.hasSize': is not true

I want to build a Carousel Slider that shows Product Images of a List I've made earlier, with an onPressed function that Navigates to another Route that shows the details of the tapped product, My product list is of name List< Productz >.
When I call the Carousel Slider method in my Home_Page Route I need "itemBuilder: (context, index)", so I wrapped it in a ListView.builder and wrapped that into a Container with defined height and width to avoid the error above, but on running the app nothing shows in the place where the Carousel Slider is supposed to be.. Am I doing this right?
My Carousel Slider code:
class CustomCarouselHomePage extends StatefulWidget {
final List<String> Productzz;
final Function press;
final Productz productz;
CustomCarouselHomePage(
{required this.Productzz, required this.press, required this.productz});
#override
_CustomCarouselHomePageState createState() => _CustomCarouselHomePageState();
}
class _CustomCarouselHomePageState extends State<CustomCarouselHomePage> {
int activeIndex = 0;
late final Function press;
late final Productz productz;
setActiveDot(index) {
setState(() {
activeIndex = index;
});
}
#override
Widget build(BuildContext context) {
return Stack(
clipBehavior: Clip.none,
children: <Widget>[
Container(
width: MediaQuery.of(context).size.width,
child: CarouselSlider(
options: CarouselOptions(
autoPlayInterval: Duration(seconds: 4),
autoPlayCurve: Curves.fastLinearToSlowEaseIn,
autoPlayAnimationDuration: Duration(seconds: 2),
viewportFraction: 1.0,
onPageChanged: (index,reason) {
setActiveDot(index);
},
),
items: widget.Productzz.map((productzz) {
return Builder(
builder: (BuildContext context) {
return GestureDetector(
onTap: () => press (),
child: Stack(
// crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Container(
width: MediaQuery.of(context).size.width,
child: Hero(
tag: "${productz.id}",
child: Image.asset(productz.item_image),
),
),
Container(
width: MediaQuery.of(context).size.width,
color: Colors.black.withOpacity(0.2),
),
],
), );
},
);
}).toList(),
),
),
Positioned(
left: 0,
right: 0,
bottom: 10,
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: List.generate(widget.Productzz.length, (idx) {
return activeIndex == idx ? ActiveDot() : InactiveDot();
})),
)
],
);
}
}
class ActiveDot extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.only(right: 8.0),
child: Container(
width: 25,
height: 8,
decoration: BoxDecoration(
color: white,
borderRadius: BorderRadius.circular(5),
),
),
);
}
}
class InactiveDot extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.only(right: 8.0),
child: Container(
width: 8,
height: 8,
decoration: BoxDecoration(
color: grey,
borderRadius: BorderRadius.circular(5),
),
),
);
}
}
My code for when I call the Carousel Slider method in Home_Page Route:
Container(
height:MediaQuery.of(context).size.height,
child: ListView.builder(
itemBuilder: (context, index) => CustomCarouselHomePage(
Productzz: [],
productz: productz[index],
press: () => Navigator.push(
context,
MaterialPageRoute(
builder: (context) => DetailsScreen(
productz: productz[index],
),
)),
),
),),

Preserve Selected item in Listview, Flutter

I have a Listview with 3 List Items, I need to select an item then it should be stays as selected,if click on another the previous selected item should be unselcted, and also change the Container color,but the problem is it's throws errror like this
Error:
The getter 'isSelected' isn't defined for the class 'String'.
Try correcting the name to the name of an existing getter, or defining a getter or field named 'isSelected'.
color: physical_status[index].isSelected ? Colors.red[100] : Colors.white,
Code For Listview
final List<String> physical_status = <String>['0', '1', '2'];
bool isSelected = false;
#override
Widget build(BuildContext context) {
Size size = MediaQuery.of(context).size;
SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Container(
height: 110,
width: size.width,
child: ListView.builder(
shrinkWrap: true,
scrollDirection: Axis.horizontal,
itemBuilder: (BuildContext context, int index) {
return Padding(
padding: const EdgeInsets.all(10.0),
child: GestureDetector(
onTap: () {
print("clicked");
setState(() {
physical_status[index].isSelected = true;
});
},
child: Container(
width: 100,
height: 100,
color: physical_status[index].isSelected ? Colors.red[100] : Colors.white,
decoration: new BoxDecoration(
shape: BoxShape.circle,
image: new DecorationImage(
fit: BoxFit.cover,
image: AssetImage(
"assets/images/user_avatar.png")),
),
),
),
);
},
),
),
],
),
),
}
You're trying to access isSelectable property from physical_status list element. But elements are strings, and String doesn't have such property.
You need to either store selectedItems separately, or convert physical_status list to a list of objects instead.
I would take the first approach:
final List<String> physical_status = <String>['0', '1', '2'];
Set<String> physical_status_selected = Set();
bool isSelected = false;
#override
Widget build(BuildContext context) {
Size size = MediaQuery.of(context).size;
SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Container(
height: 110,
width: size.width,
child: ListView.builder(
shrinkWrap: true,
scrollDirection: Axis.horizontal,
itemBuilder: (BuildContext context, int index) {
return Padding(
padding: const EdgeInsets.all(10.0),
child: GestureDetector(
onTap: () {
print("clicked");
setState(() {
physical_status_selected.add(physical_status[index]);
});
},
child: Container(
width: 100,
height: 100,
decoration: new BoxDecoration(
color: physical_status_selected.contains(physical_status[index]) ? Colors.red[100] : Colors.white,
shape: BoxShape.circle,
image: new DecorationImage(
fit: BoxFit.cover,
image: AssetImage(
"assets/images/user_avatar.png")),
),
),
),
);
},
),
),
],
),
),
You can use list of bool instead of String and also manage which item is currently selected using another variable.
Following code will help you more.
final List<bool> physical_status = <bool>[false, false, false];
int currentSelectedIndex = 0;
#override
Widget build(BuildContext context) {
Size size = MediaQuery.of(context).size;
return Scaffold(
body: SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Container(
height: 110,
width: size.width,
child: ListView.builder(
shrinkWrap: true,
scrollDirection: Axis.horizontal,
itemCount: physical_status.length,
itemBuilder: (BuildContext context, int index) {
return Padding(
padding: const EdgeInsets.all(10.0),
child: GestureDetector(
onTap: () {
print("clicked");
setState(() {
physical_status[currentSelectedIndex] = false;
currentSelectedIndex = index;
physical_status[index] = true;
});
},
child: Container(
width: 100,
height: 100,
decoration: new BoxDecoration(
color: physical_status[index]
? Colors.red[100]
: Colors.white,
shape: BoxShape.circle,
image: new DecorationImage(
fit: BoxFit.cover,
image: AssetImage("assets/images/user_avatar.png")),
),
),
),
);
},
),
),
],
),
),
);
}
Change physical_status[index].isSelected to isSelected
Also put color: isSelected ? Colors.red[100] : Colors.white, inside BoxDecoration
SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Container(
height: 110,
width: size.width,
child: ListView.builder(
shrinkWrap: true,
scrollDirection: Axis.horizontal,
itemBuilder: (BuildContext context, int index) {
return Padding(
padding: const EdgeInsets.all(10.0),
child: GestureDetector(
onTap: () {
print("clicked");
setState(() {
isSelected = true;
});
},
child: Container(
width: 100,
height: 100,
decoration: new BoxDecoration(
color:
isSelected ? Colors.red[100] : Colors.white,
shape: BoxShape.circle,
image: new DecorationImage(
fit: BoxFit.cover,
image: AssetImage(
"assets/images/user_avatar.png")),
),
),
),
);
},
),
),
],
),
),
You may also create a class like this.
class Item {
final String physical_status;
final bool isSelected;
Item({this.physical_status, this.isSelected});
}
List<Item> itemList = <Item>[
Item(
physical_status: '1',
isSelected: true),
Item(
physical_status: '2',
isSelected: false),
Item(
physical_status: '3',
isSelected: false),
];

How to set image size in carousel slider flutter

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(),
),
),
],
);