Flutter How to show container expand and collapse element's? - flutter

I would like to shows a container elements with expansion and collapse effect.
It is not combined with AppBar.
Here is my container code:
InkWell(
onTap: () {
if (_height == 200) {
setState(() {
_height = 100.0;
});
} else {
_updateState();
}
},
child: AnimatedContainer(
duration: const Duration(milliseconds: 550),
height: _height,
width: Get.width,
decoration: BoxDecoration(
color: Colors.white,
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.2),
spreadRadius: 2,
blurRadius: 10,
offset: const Offset(0, 3),
),
],
borderRadius: const BorderRadius.only(
bottomLeft: Radius.circular(20),
bottomRight: Radius.circular(20),
),
),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Text("0.0"),
Text("0.0"),
//Widget1(),
//Widget2(),
//Widget3(),
],
),
),
);
I want it to show my other Widgets when I click it.
Also I tried ExpansionPanelList and ExpansionTile but they are not working like what I exactly want. Also I don't want to use SliverAppBar .

This example might help you:
class _MyHomePageState extends State<MyHomePage> {
double _height = 100;
void onClick() {
if (_height == 300) {
setState(() {
_height = 100.0;
});
} else {
setState(() {
_height = 300;
});
}
}
#override
Widget build(BuildContext context) {
final List<Widget> _widgets = [
Container(
width: MediaQuery.of(context).size.width,
height: 100,
decoration: BoxDecoration(
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.2),
spreadRadius: 2,
blurRadius: 10,
offset: const Offset(0, 3),
),
],
borderRadius: const BorderRadius.only(
bottomLeft: Radius.circular(20),
bottomRight: Radius.circular(20),
),
),
),
Container(
width: MediaQuery.of(context).size.width,
height: 100,
color: Colors.grey,
),
Container(
width: MediaQuery.of(context).size.width,
height: 100,
decoration: const BoxDecoration(
boxShadow: [
BoxShadow(
color: Colors.red,
),
],
borderRadius: BorderRadius.only(
bottomLeft: Radius.circular(20),
bottomRight: Radius.circular(20),
),
),
)
];
return Scaffold(
backgroundColor: Colors.blueAccent,
body: Column(
children: [
InkWell(
onTap: () {
onClick();
},
child: AnimatedContainer(
duration: const Duration(milliseconds: 550),
height: _height,
width: MediaQuery.of(context).size.width,
decoration: BoxDecoration(
color: Colors.white,
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.2),
spreadRadius: 2,
blurRadius: 10,
offset: const Offset(0, 3),
),
],
borderRadius: const BorderRadius.only(
bottomLeft: Radius.circular(20),
bottomRight: Radius.circular(20),
),
),
child: SingleChildScrollView(
physics: const NeverScrollableScrollPhysics(),
child: Column(
children: _widgets,
),
),
),
),
],
),
);
}
}
result:

you can add condition in you column like this
children: [
Text("0.0"),
Text("0.0"),
if(_height == 200)
Widget1(),
if(_height == 200)
Widget2(),
if(_height == 200)
Widget3(),
],
also you can use AnimatedSwitcher
https://api.flutter.dev/flutter/widgets/AnimatedSwitcher-class.html

Related

Flutter: How can I add a box shadow to this widget?

I am trying to add a box shadow over a widget that displays an image. Whenever I include the box-shadow within the parent container, the shadow is only shown on the container which is stacked behind the child image. How can I have the shadow be displayed for the child image?
import 'package:flutter/material.dart';
import 'package:flutter_course_app_4/pages/nft_post.dart';
class NFTIconTemplate extends StatelessWidget {
final String NFTImg;
NFTIconTemplate({required this.NFTImg});
#override
Widget build(BuildContext context) {
return ClipRRect(
borderRadius: BorderRadius.circular(10),
child: Container(
child: InkWell(
child: Container(
decoration: BoxDecoration(
boxShadow: [
BoxShadow(
color: Colors.black54,
offset: Offset(4.0, 4.0),
blurRadius: 15.0,
spreadRadius: 1.0),
],
color: Colors.grey[800],
),
child: Column(
children: [
Image.network(
NFTImg,
width: 120,
height: 160,
fit: BoxFit.cover,
),
],
),
),
onTap: () {
print('Clicked NFT Icon');
Navigator.push(
context, MaterialPageRoute(builder: (context) => nftPost()));
},
),
),
);
}
}
Try this code to get extra shade to your code,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(12),
topRight: Radius.circular(12),
bottomLeft: Radius.circular(12),
bottomRight: Radius.circular(12)),
boxShadow: [
BoxShadow(
color: Colors.grey.withOpacity(0.6),
spreadRadius: 8,
blurRadius: 6,
offset: Offset(0, 4),
),
],
),

Stack with custom shadow and positioned widget outside the bounderies

I'm trying to achieve something like this in flutter:
This is my attempt to do that
class ContainerWidget extends StatelessWidget {
final Widget child;
final double width, height;
late List<Color>? gradiantColors;
ContainerWidget({
Key? key,
required this.child,
required this.height,
required this.width,
this.gradiantColors,
}) : super(key: key);
#override
Widget build(BuildContext context) {
var border = BorderRadius.only(
topRight: Radius.circular(70),
topLeft: Radius.circular(8),
bottomLeft: Radius.circular(8),
bottomRight: Radius.circular(8),
);
return Container(
decoration: BoxDecoration(
color: gradiantColors == null ? Colors.white : null,
borderRadius: border,
boxShadow: [
BoxShadow(
color: Colors.grey.shade300,
offset: Offset(0, 1),
blurRadius: 30,
spreadRadius: 5,
),
],
gradient: gradiantColors != null
? LinearGradient(
colors: gradiantColors!,
begin: Alignment.topLeft,
end: Alignment.bottomRight,
)
: null,
),
width: width,
height: height,
child: Stack(
children: [
Positioned(
top: -40,
left: -20,
child: Container(
decoration: BoxDecoration(
color: Colors.red.shade100.withOpacity(0.2),
shape: BoxShape.circle,
),
width: 100,
height: 100,
),
),
Positioned(
child: Icon(
Icons.abc_rounded,
size: 40,
),
),
child
],
),
);
}
}
this is the output
However, I've two problems:
The circle on top leak out over the rounded corner, I tried to solve that with the ClipRRect, but it clipped also the shadow of the container.
Icon (or the image) cannot be placed above the top portion of the container.
Any ideas ?
Like this (put this inside your widget class):
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Stack(
clipBehavior: Clip.none,
children: [
Container(
decoration: BoxDecoration(
boxShadow: [
BoxShadow(blurRadius: 20,
color: Colors.orange.withOpacity(0.5),
offset: const Offset(0.0, 8.0)
)
],
borderRadius: const BorderRadius.only(
topLeft: Radius.circular(20),
topRight: Radius.circular(100),
bottomLeft: Radius.circular(20),
bottomRight: Radius.circular(20)
)
),
child: ClipRRect(
borderRadius: const BorderRadius.only(
topLeft: Radius.circular(20),
topRight: Radius.circular(100),
bottomLeft: Radius.circular(20),
bottomRight: Radius.circular(20)
),
child: Stack(
children: [
Container(
width: 200,
height: 300,
color: Colors.orange
),
Positioned(
top: -50,
left: -40,
child: ClipOval(
child: Container(
width: 150,
height: 150,
color: Colors.white.withOpacity(0.25)
)
)
)
]
)
)
),
Positioned(
top: -40,
left: 20,
child: Container(
width: 80,
height: 80,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(25),
boxShadow: [
BoxShadow(blurRadius: 10, color: Colors.black.withOpacity(0.2), offset: const Offset(0.0, 5.0))
]
)
)
)
]
)
)
);
}
which then ends up looking like this:
The top white Container is just a placeholder for what your image could look like. I'd suggest then using a PNG already with the shadow integrated if you'll be using pictures like that.
Let me know if that's what you're trying to accomplish and adjust to your needs.

Flutter place an object from a stack on top of container outside that stack

Long story short I have a stack, in which I have an image that is position out of the stack.
body: Column(
children: [
Stack(
clipBehavior: Clip.none,
alignment: Alignment.center,
children: [
_positionedImage(),
],
),
_bodyContainer(),
],
container:
Widget _bodyContainer() {
return Container(
width: MediaQuery.of(context).size.width,
height: 200,
decoration: BoxDecoration(
color: itsyBackground,
borderRadius: BorderRadius.only(topLeft: Radius.circular(20), topRight: Radius.circular(20)),
boxShadow: [BoxShadow(offset: Offset(0, 0), color: Colors.green, spreadRadius: 1, blurRadius: 1),],
),
);
}
How can I make so that picture is on top of the container?
the approach that you used is wrong here.. You don't need a column here. You can simply render a stack an the bottom most widget should be placed first in the stack children.
https://medium.com/flutter-community/a-deep-dive-into-stack-in-flutter-3264619b3a77
An Example:
Stack(
clipBehavior: Clip.none,
alignment: Alignment.center,
children: [
Container(
width: MediaQuery.of(context).size.width,
height: 200,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(20),
topRight: Radius.circular(20)),
boxShadow: [
BoxShadow(
offset: Offset(0, 0),
color: Colors.green,
spreadRadius: 1,
blurRadius: 1),
],
),
),
Positioned(
top: -10,
child: Image.network(
'https://static.toiimg.com/thumb/msid-31346158,width-748,height-
499,resizemode=4,imgsize-114461/.jpg',
width: 100,
),
),
],
),

How do I automatically scale images in flutter to fit every resolution without overflow and scrolling?

I'm new and my English is pretty bad. Please answer easy to understand...
I already tried using the AspectRatio Widget but it, combined with a Center widget, moved my buttons in the center. Apart from that it worked but the buttons really need to stick to the side. This is my code so far:
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'main.dart';
import 'contentData.dart';
import 'package:swipedetector/swipedetector.dart';
AppBrain contentData = AppBrain();
class SwipePage extends StatefulWidget {
SwipePage({Key key, this.title}) : super(key: key);
final String title;
#override
_SwipePage createState() => _SwipePage();
}
class _SwipePage extends State<SwipePage> {
#override
Widget build(BuildContext context) {
return SwipeDetector(
swipeConfiguration: SwipeConfiguration(
horizontalSwipeMaxHeightThreshold: 80.0,
horizontalSwipeMinDisplacement: 30.0,
horizontalSwipeMinVelocity: 150.0),
onSwipeLeft: () {
Navigator.of(context).push(
toInformationPage(),
);
},
child: Scaffold(
backgroundColor: Colors.white,
body: SafeArea(
child: Padding(
padding: const EdgeInsets.only(top: 20, bottom: 20),
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Container(
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(20),
topRight: Radius.circular(20),
bottomLeft: Radius.circular(20),
bottomRight: Radius.circular(20)),
boxShadow: [
BoxShadow(
color: Colors.grey.withOpacity(0.5),
spreadRadius: 5,
blurRadius: 7,
offset: Offset(0, 3), // changes position of shadow
),
],
),
child: ClipRRect(
borderRadius: BorderRadius.circular(20),
child: Image.asset(
AppBrain().getImageAdress(),
),
),
),
Padding(
padding: const EdgeInsets.only(top: 20.0, bottom: 20),
child: Divider(
color: Colors.grey,
height: 20,
thickness: 2,
indent: 120,
endIndent: 120,
),
),
Padding(
padding: const EdgeInsets.only(bottom: 20),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.end,
children: <Widget>[
Container(
decoration: BoxDecoration(
color: buttonColor,
borderRadius: BorderRadius.only(
topRight: Radius.circular(50),
bottomRight: Radius.circular(50),
),
),
child: MaterialButton(
height: 60,
onPressed: () {},
textColor: red,
child: Icon(
Icons.close,
size: 45,
),
),
),
Container(
width: 120,
),
Container(
decoration: BoxDecoration(
color: buttonColor,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(50),
bottomLeft: Radius.circular(50),
),
),
child: MaterialButton(
height: 60,
onPressed: () {
Navigator.of(context).push(
toInformationPage(),
);
},
textColor: green,
child: Icon(
Icons.check,
size: 45,
),
),
),
],
),
)
],
),
),
),
),
);
}
}
This is what it looks like now:
https://imgur.com/a/2kgpJ6A
This is what it should look like across all aspect-ratios and resolutions (the image should just scale down..):
https://imgur.com/FBNlpDa
Looking at your code you have at least two different problems.
Setting the correct image fit - You can use BoxFit.contain in Image.asset(fit: boxFit.contain, .... ) to make sure it is resized to be contained inside it's parent.
You have a Column and want the first child to take all the available width. Hence you should nest it inside Expanded widget.
ie. structurally something like:
Column(
children: [
Expanded(
// your image goes here which will take as much height as possible.
child: Image.asset('asset', fit: BoxFit.contain),
),
Container(
// your button bar which takes up the rest of the height
child: MaterialButton( ... ),
),
],
);
I left out quite a bit, but i hope you get the gist.
I think I fixed it myself with the help of Herbert, thanks :). I wrapped the Container containing my image in an Expanded widget and set a flex value of 3.
This is my new code:
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'main.dart';
import 'contentData.dart';
import 'package:swipedetector/swipedetector.dart';
AppBrain contentData = AppBrain();
class SwipePage extends StatefulWidget {
SwipePage({Key key, this.title}) : super(key: key);
final String title;
#override
_SwipePage createState() => _SwipePage();
}
class _SwipePage extends State<SwipePage> {
#override
Widget build(BuildContext context) {
return SwipeDetector(
swipeConfiguration: SwipeConfiguration(
horizontalSwipeMaxHeightThreshold: 80.0,
horizontalSwipeMinDisplacement: 30.0,
horizontalSwipeMinVelocity: 150.0),
onSwipeLeft: () {
Navigator.of(context).push(
toInformationPage(),
);
},
child: Scaffold(
backgroundColor: Colors.white,
body: SafeArea(
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Expanded(
flex: 4,
child: Container(
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(20),
topRight: Radius.circular(20),
bottomLeft: Radius.circular(20),
bottomRight: Radius.circular(20)),
boxShadow: [
BoxShadow(
color: Colors.grey.withOpacity(0.5),
spreadRadius: 5,
blurRadius: 7,
offset: Offset(0, 3), // changes position of shadow
),
],
),
child: ClipRRect(
borderRadius: BorderRadius.circular(20),
child: Image.asset(
AppBrain().getImageAdress(),
fit: BoxFit.contain,
),
),
margin: EdgeInsets.fromLTRB(25, 25, 25, 0),
),
),
Padding(
padding: const EdgeInsets.only(
top: 20.0,
),
child: Divider(
color: Colors.grey,
height: 20,
thickness: 2,
indent: 120,
endIndent: 120,
),
),
Padding(
padding: const EdgeInsets.only(bottom: 25),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.end,
children: <Widget>[
Container(
decoration: BoxDecoration(
color: buttonColor,
borderRadius: BorderRadius.only(
topRight: Radius.circular(50),
bottomRight: Radius.circular(50),
),
),
child: MaterialButton(
height: 60,
onPressed: () {},
textColor: red,
child: Icon(
Icons.close,
size: 45,
),
),
),
Container(
width: 120,
),
Container(
decoration: BoxDecoration(
color: buttonColor,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(50),
bottomLeft: Radius.circular(50),
),
),
child: MaterialButton(
height: 60,
onPressed: () {
Navigator.of(context).push(
toInformationPage(),
);
},
textColor: green,
child: Icon(
Icons.check,
size: 45,
),
),
),
],
),
)
],
),
),
),
);
}
}
You can try using FittedBox widget too.

How to display a text at the bottom left of the Image

I want to display a text at the bottom left if the image to be like as the below figure:
and this the below code is related:
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import '../providers/city.dart';
class ProvinceItem extends StatelessWidget {
#override
Widget build(BuildContext context) {
final city = Provider.of<City>(context, listen: false);
// final cart = Provider.of<Cart>(context, listen: false);
return Padding(
padding: const EdgeInsets.all(8.0),
child: InkWell(
splashColor: Colors.transparent,
onTap: () => {},
child: Container(
decoration: BoxDecoration(
borderRadius: const BorderRadius.all(Radius.circular(16.0)),
boxShadow: <BoxShadow>[
BoxShadow(
color: Colors.grey.withOpacity(0.6),
offset: const Offset(2.5, 2.5),
blurRadius: 16,
),
],
),
margin: EdgeInsets.all(2),
child: ClipRRect(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(15),
topRight: Radius.circular(15),
bottomLeft: Radius.circular(15),
bottomRight: Radius.circular(15),
),
child: Image.asset(
city.cityImage,
fit: BoxFit.cover,
),
),
),
),
);
}
}
I have just create a list of Grid widget and as every list of grid item have a grid item just shown like the previous code...
as I need the best suggestion for this Grid item as it only contains just an image and a text with some of shadows..
Stack widget will do the trick for you.
Stack(
children: <Widget>[
InkWell(
splashColor: Colors.transparent,
onTap: () => {},
child: Container(
decoration: BoxDecoration(
borderRadius: const BorderRadius.all(Radius.circular(16.0)),
boxShadow: <BoxShadow>[
BoxShadow(
color: Colors.grey.withOpacity(0.6),
offset: const Offset(2.5, 2.5),
blurRadius: 16,
),
],
),
margin: EdgeInsets.all(2),
child: ClipRRect(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(15),
topRight: Radius.circular(15),
bottomLeft: Radius.circular(15),
bottomRight: Radius.circular(15),
),
child: Image.asset(
city.cityImage,
fit: BoxFit.cover,
),
),
),
),
Container(
margin: EdgeInsets.only(left: 20, bottom: 20),
child: Align(
alignment: Alignment.bottomLeft,
child: Text(
'Text',,
style: TextStyle(color: Colors.white, fontSize: 20),
)),
),
],
),