List Tiles out of container when scrolling - flutter

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

Related

how to make widget scale up when it selected in Flutter

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;
});
},
)
)

How to create horizontal scrollable GridView as shown below and change Container(GridTile)'s size dynamically based on Text?

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

Designing a Flutter button with image and text

If I just throw together an image and some text in a rounded-corner rectangle, the user will not know that they can "click here". But I don't have to bake my own solution. InkWell covers this scenario, complete with a nice shadow.
I am positioning
a custom clickable icon using the
InkWell
class, itself requiring to be inside an
Ink
instance.
import 'package:flutter/material.dart';
const boat_url = ('https://upload.wikimedia.org/wikipedia/commons/thumb/0/05/'
'Segelboot_Bodensee_Mainau_%28Foto_Hilarmont%29.JPG/'
'182px-Segelboot_Bodensee_Mainau_%28Foto_Hilarmont%29.JPG');
void main() {
runApp(MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Image',
home: Scaffold(
backgroundColor: Colors.grey,
body: MyImage(),
)));
}
class MyImage extends StatelessWidget {
MyImage({Key key,});
#override
Widget build(BuildContext context) {
Size sz = MediaQuery.of(context).size * 0.4;
double border = 4;
return Stack(children: [
Positioned(
top: 100,
left: 100,
width: sz.width,
height: sz.height,
child: Material(
child: Ink(
decoration: BoxDecoration(
boxShadow: <BoxShadow>[
new BoxShadow(
color: Colors.red,
blurRadius: 10.0,
offset: new Offset(30.0, 20.0),
),
],
border: Border.all(
color: Colors.blue,
width: border,
),
borderRadius: BorderRadius.circular(40),
),
child: InkWell(
onTap: (){/*..*/},
child: Column(
children: [
Container(
height: 4 * (sz.height - 2 * border) / 5,
alignment: Alignment.center,
child: Image.network(boat_url),
),
Container(
height: (sz.height - 2 * border) / 5,
child: FittedBox(
clipBehavior: Clip.antiAlias,
alignment: Alignment.centerLeft,
fit: BoxFit.fitHeight,
child: Text('A long descriptive sentence')),
)
],
)),
),
)),
]);
}
}
1- I'm not actually using Colors.white, and the Scaffold itself has
backgroundColor: Colors.grey. Where is the white background coming from?
2- When we talk of a "shadow", I'm expecting the shadow to be behind
the ink/inkwell object. Why does the shadow appear in front?
Related: 1
That white color is from the Material widget, to remove that you can use type param.
Material(
type: MaterialType.transparency,
child: Container(),
);
Here is code to achieve the custom button
Video link
Scaffold(
backgroundColor: Colors.blueGrey,
body: SafeArea(
child: Container(
decoration: BoxDecoration(
color: Colors.green.shade200,
border: Border.all(color: Colors.green),
borderRadius: BorderRadius.circular(5),
boxShadow: [
BoxShadow(
blurRadius: 5,
spreadRadius: 2,
color: Colors.black26,
)
]),
margin: const EdgeInsets.all(20),
child: Material(
type: MaterialType.transparency,
child: InkWell(
onTap: () {},
splashColor: Colors.black26,
child: IntrinsicHeight(
child: Padding(
padding: const EdgeInsets.all(12.0),
child: Column(mainAxisSize: MainAxisSize.min, children: [
Image.asset(
'assets/images/marked_tyre_base.png',
fit: BoxFit.cover,
width: 80,
height: 80,
),
const SizedBox(
height: 10,
),
Text(
'Tyre 1',
style: TextStyle(color: Colors.white),
)
]),
),
),
),
),
),
),
);
Screenshot:
Create a class, ImageTextButton:
class ImageTextButton extends StatelessWidget {
final VoidCallback onPressed;
final ImageProvider image;
final double imageHeight;
final double radius;
final Widget text;
ImageTextButton({
#required this.onPressed,
#required this.image,
this.imageHeight = 200,
this.radius = 28,
#required this.text,
});
#override
Widget build(BuildContext context) {
return Card(
elevation: 8,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(radius)),
clipBehavior: Clip.hardEdge,
child: InkWell(
onTap: onPressed,
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Ink.image(
image: image,
height: imageHeight,
fit: BoxFit.cover,
),
SizedBox(height: 6),
text,
SizedBox(height: 6),
],
),
),
);
}
}
Usage:
ImageTextButton(
onPressed: () {},
image: AssetImage('chocolate_image'),
text: Text('Chocolate'),
)

how to Make whole page scrollable instead to GridView Builder in flutter?

I am new to flutter and creating a screen with following code:-
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:wallpaper/ui/widgets/card_wallpaper.dart';
import '../../providers/anime_provider.dart';
import '../../models/wallpaper.dart';
import '../../providers/wallpaper_provider.dart';
class AnimeDetail extends StatelessWidget {
#override
Widget build(BuildContext context) {
final String id = ModalRoute.of(context).settings.arguments;
final selectedAnime = Provider.of<AnimeProvider>(context).findById(id);
final selectedWallPaper =Provider.of<WallpaperProvider>(context).getByAnime(id);
final appBar = AppBar(
leading: BackButton(
color: Theme.of(context).primaryColor,
),
elevation: 0,
backgroundColor: Colors.transparent,
title: Text(
selectedAnime.title,
style: TextStyle(
color: Theme.of(context).primaryColor,
fontFamily: 'Righteous',
),
),
);
final mediaQuery = MediaQuery.of(context);
final double totalHeight = mediaQuery.size.height -appBar.preferredSize.height -mediaQuery.padding.top -335;
return Scaffold(
appBar: appBar,
body: SingleChildScrollView(
child: Column(
children: [
Container(
width: double.infinity,
height: 300,
child: Card(
elevation: 3.1,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20),
),
child: Stack(
children: [
Container(
height: 300,
width: double.infinity,
child: ClipRRect(
child: Image.asset(
selectedAnime.imageUrl,
fit: BoxFit.cover,
),
borderRadius: BorderRadius.only(
bottomLeft: Radius.circular(20),
bottomRight: Radius.circular(20),
),
),
),
],
),
),
),
SizedBox(height: 10),
Row(
children: [
Container(
height: 25,
child: Padding(
padding: const EdgeInsets.symmetric(
horizontal: 15, vertical: 0),
child: Text(
'WallPapers from ${selectedAnime.title}',
style: TextStyle(
fontFamily: 'Righteous',
fontSize: 16,
color: Theme.of(context).primaryColor,
),
),
),
),
],
),
Container(
width: double.infinity,
height: totalHeight,
child: GridView.builder(
shrinkWrap: true,
physics: const ClampingScrollPhysics(),
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
childAspectRatio: 0.5,
crossAxisSpacing: 10,
mainAxisSpacing: 10,
),
itemBuilder: (ctx, i) => ChangeNotifierProvider.value(
value: selectedWallPaper[i],
child: CardWallpaper(),
),
padding: const EdgeInsets.all(8.0),
itemCount: selectedWallPaper.length,
),
),
],
),
));
}
}
When I run this app, the gridview is scrollable but the image at the top of it does not scroll,but, I want to scroll whole page but only the grid scrolls even though I am using singlechildscrollview. I tried using expanded on gridview builder but it produces error.How can I make whole page scroll instead of just gridview.builder.
![See the screen here]:https://i.stack.imgur.com/ClDZy.jpg
As you can see when you scroll the page only gridview gets scrolled while top image remains there. I want to scroll the page as whole. Is there any way to determine the height of gridtile?
In your gridview, set the parameter scrollable: NeverScrollablePhysics().

How can I change a container color on tap with Provider?

I am trying to create a custom style checkbox that is a container with rounded edges. It should show a different color icon when tapped. I am not sure how to do this can anyone help? Here is the code: (Edit I updated the code to show the gridview builder that the checkbox is placed in. The gridviewbuilder builds a card based on the length of a list in the provider class. I am trying to get the checkbox to work independently of the other gridview cards.
//this is the function in the provider class
toggleCheckbox(bool checkboxStatus){
if (checkboxStatus = false){
return checkboxStatus = true;
} else if (checkboxStatus = true){
return checkboxStatus = false;
}
notifyListeners();
}
GridView.builder(
itemCount: bloc.readingList.length,
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
childAspectRatio: 12/16, crossAxisCount: 2, crossAxisSpacing: 20.0, mainAxisSpacing: 20),
itemBuilder: (BuildContext context, int index) {
return ClipRRect(
borderRadius: BorderRadius.circular(16.0),
child: Container(
decoration: BoxDecoration(
color: Colors.white,
boxShadow: [
BoxShadow(
color: Colors.black12,
offset: Offset(3.0, 6.0),
blurRadius: 10.0)
],
borderRadius: BorderRadius.circular(20),
image: DecorationImage(
image: NetworkImage('${bloc.readingList[index].storyImage}'),
fit: BoxFit.cover,
),
),
child: Padding(
padding: const EdgeInsets.only(
top: 8.0, bottom: 0.0, left: 0.0, right: 0),
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.end,
children: <Widget>[
TopicTag(index: index,),
CardContents(),
],
),
),
),
);
},
),
class CardContents extends StatefulWidget {
const CardContents({
Key key,
}) : super(key: key);
#override
_CardContentsState createState() => _CardContentsState();
}
class _CardContentsState extends State<CardContents> {
bool checkboxStatus = false;
#override
Widget build(BuildContext context) {
final bloc = Provider.of<ReadingListBloc>(context);
return ClipRRect(
child: BackdropFilter(
filter: ImageFilter.blur(sigmaX: 10.0, sigmaY: 10.0),
child: Container(
color: Colors.blueGrey.withOpacity(.5),
child: Column(
children: <Widget>[
Text('Title Here (color change with topic)',
style: TextStyle(
color: Colors.white,
fontSize: 18.0,
fontFamily: "Calibre-Semibold",
letterSpacing: 1.0,
)),
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
Padding(
padding: const EdgeInsets.only(right: 8.0, bottom: 8),
child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20),
color: Colors.white),
child: GestureDetector(
onTap:(){},
// bloc.toggleCheckbox(checkboxStatus),
child: checkboxStatus
? Icon(Icons.check_circle, color: Colors.green)
: Icon(Icons.check_circle, color: Colors.white)),
),
),
],
),
],
),
),
),
);
}
}
Considering that you have setup your provider correctly, you could do something like below.
// add the property below to your provider
bool checkboxStatus = false;
void toggleCheckbox(){
checkboxStatus = !checkboxStatus;
notifyListeners();
}
Now for the listeners, you can just check this new property, considering that bloc is your provider.
GestureDetector(
onTap: () {
bloc.toggleCheckbox(checkboxStatus);
},
child: bloc.checkboxStatus ? Icon(Icons.check_box, color: Colors.green)
: Icon(Icons.check_circle, color: Colors.white)),
I'm assuming that for some reason you want to use a provider. Of course you could also use a StatefulWidget if you only need the status in this widget.