I was trying to make this page but this design in last is not shifting to the last bottom, I've tried padding but this doesn't look good and also I've tried positioned widget but it is showing some error please someone tell how I can shift that design to bottom last
this is my git repo: https://github.com/cryptic-exe/Otp_verfication
this is my code:
import 'package:flutter/material.dart';
import 'package:flutter/painting.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(),
debugShowCheckedModeBanner: false,
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key}) : super(key: key);
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
String dropdownValue = 'English';
#override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Center(
child: Column(
children: [
Icon(
Icons.photo_outlined,
size: 100.0,
),
Padding(
padding: const EdgeInsets.only(top: 40.0),
child: Text(
'Please Select Your Language',
style: TextStyle(
fontWeight: FontWeight.bold, fontSize: 20.0),
),
),
Padding(
padding: const EdgeInsets.symmetric(vertical: 20),
child: Text(
'You can change the language \n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t at any time',
style: TextStyle(
fontWeight: FontWeight.w300, fontSize: 15.0),
),
),
Padding(
padding: const EdgeInsets.only(top: 9.0),
child: Container(
width: 200,
padding: const EdgeInsets.only(left: 10.0, right: 10.0),
decoration: BoxDecoration(
border: Border.all(),
),
child: DropdownButton<String>(
value: dropdownValue,
icon: const Icon(Icons.arrow_drop_down_outlined),
isExpanded: true,
iconSize: 30,
elevation: 16,
style: const TextStyle(color: Colors.black),
onChanged: (String? newValue) {
setState(() {
dropdownValue = newValue!;
});
},
items: <String>[
'English',
'Hindi',
'French',
'Spanish',
'Russian',
'Arabic'
].map<DropdownMenuItem<String>>((String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(
value,
style: TextStyle(
fontSize: 20,
letterSpacing: 0.9,
fontWeight: FontWeight.w300),
),
);
}).toList(),
),
),
),
Padding(
padding: const EdgeInsets.all(20.0),
child: Container(
width: 200,
padding: const EdgeInsets.only(left: 10.0, right: 10.0),
decoration: BoxDecoration(
color: Colors.deepPurple,
border: Border.all(),
),
child: TextButton(
onPressed: () {},
child: Text(
'NEXT',
style: TextStyle(
color: Colors.white,
fontSize: 20.0,
fontWeight: FontWeight.w400,
letterSpacing: 0.9),
),
),
),
),
],
),
),
Stack(
children: [
Positioned.fill(
child: Container(
width: 393,
child: Image(
image: AssetImage('Images/design2.png'),
fit: BoxFit.fill,
),
),
),
Positioned(
child: Container(
width: 393,
child: Image(
image: AssetImage('Images/design1.png'),
colorBlendMode: BlendMode.overlay,
fit: BoxFit.fill,
),
),
),
],
),
],
),
);
}
}
you can use bottomSheet to place your image.
Add the below code inside your Scaffold
bottomSheet: Container(
width: double.infinity,
child: Image(
image: AssetImage('Images/design1.png'),
colorBlendMode: BlendMode.overlay,
fit: BoxFit.fill,
),
),
You can also use a spacer to push the content down
https://api.flutter.dev/flutter/widgets/Spacer-class.html
On mobile so I cannot give snippet
Related
First time using flutter: I'm trying to populate this column with a StatelessWidget but when I run the app, List is completely blank, even though List length is corretly displaying space for the amount of items I'm trying to display. When I debug the app there are no errors, so I can't understand if I'm submitting a completely blank widget or if I'm not inserting into the list the right way.
What I'm trying to achieve is displaying a placeholder card: once clicked it should follow the route and link to another page.
Here is my widget:
import 'package:progetto_esame_febbraio/utils/config.dart';
import 'package:flutter/material.dart';
class DoctorCard extends StatelessWidget {
const DoctorCard({Key? key, required this.route}) : super(key: key);
final String route;
#override
Widget build(BuildContext context) {
Config().init(context);
return Container(
padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 100),
height: 150,
child: GestureDetector(
child: Card(
elevation: 5,
color: Colors.black,
child: Row(
children: [
SizedBox(
width: Config.widthSize * 0.33,
child: Image.asset(
'assets/facebook.png',
fit: BoxFit.fill,
),
),
Flexible(
child: Padding(
padding:
const EdgeInsets.symmetric(horizontal: 10, vertical: 20),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
const Text(
'Dr Richart',
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
),
),
const Text(
'Dental',
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.normal,
),
),
const Spacer(),
Row(
mainAxisAlignment: MainAxisAlignment.start,
children: const <Widget>[
Icon(
Icons.star_border,
color: Colors.yellow,
size: 16,),
Spacer(
flex: 1,
),
Text('4.5'),
Spacer(
flex: 1,
),
Text('Reviews'),
Spacer(
flex: 1,
),
Text('(20)'),
Spacer(
flex: 7,
),
],
),
],
),
),
),
],
),
),
onTap: () {
Navigator.of(context).pushNamed(route);
}, // rinvia al dettaglio dottore
),
);
}
}
And Here is my home page:
class HomePage extends StatefulWidget {
const HomePage({Key? key}) : super(key: key);
#override
State<HomePage> createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
#override
Widget build(BuildContext context) {
return Scaffold(
body: Padding(
padding: const EdgeInsets.symmetric(
horizontal: 15,
vertical: 15,
),
child: SafeArea(
child: SingleChildScrollView(
child: Column(
children: List.generate(5, (index) {
return const DoctorCard(
route: 'doc_details',
);
}),
),
),
),
),
);
}
}
You are having too much padding.
return Container(
padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 10),//here it was 100
height: 150,
child: GestureDetector(
i am trying to update the state of the animated switcher in the middle area. i am trying to do this using a setstate in the lower area. but it does not work.
the first thing i did is to create a variable with a boolean data type in the home class.
then i passed the variable to both the middle area and the lower area
the idea was that if the same variable is passed to the class whose state i am trying to update, and the class with the set state, it would work. but it seems i am wrong. i would appreciate some assistance.
the boolean variable i am trying to make work is the _rep variable
This is the Home widget
class HomePage extends StatefulWidget {
const HomePage({Key? key}) : super(key: key);
#override
State<HomePage> createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> with TickerProviderStateMixin {
late AnimationController _animationController;
late AnimationController _controller;
late Animation<Offset> _animation;
late Animation<Offset> _anime;
bool _rep = true;
#override
void initState() {
_animationController = AnimationController(
vsync: this,
duration: Duration(seconds: 2)
);
_animation = Tween<Offset>(
begin:Offset (0.0, 0.0),
end: Offset (0.0,3.0),
).animate(CurvedAnimation(
parent: _animationController,
curve: Curves.easeIn));
_anime = Tween<Offset>(
begin:Offset (0.0, 0.0),
end: Offset (0.0,-0.55),
).animate(CurvedAnimation(
parent: _animationController,
curve: Curves.easeIn));
super.initState();
}
#override
void dispose() {
_animationController.dispose();
_controller.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: SingleChildScrollView(
scrollDirection: Axis.vertical,
physics: const NeverScrollableScrollPhysics(),
child: Padding(
padding: EdgeInsets.only(top: 3.h),
child: Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
TopIcon(icons: Icons.arrow_back, color:Colors.grey.shade300 ,),
SizedBox(
height: 13.h,
width: 13.w,
child: Image.asset('assets/images/download.png')
),
TopIcon(icons: Icons.shopping_bag_outlined, color: Colors.grey.shade300,),
],
),
SizedBox(
height: 3.h,
),
Text('Frappuccino',
style: TextStyle(
fontSize: 27.sp,
fontWeight: FontWeight.bold
),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Text('White Chocolate',
style: TextStyle(
fontWeight: FontWeight.bold,
color: Colors.grey.shade400
),
),
),
MiddleArea(
controller: _animationController,
animation: _animation,
rep: _rep,
),
LowerArea(controller: _animationController, anime: _anime, rep = _rep),
],
),
),
),
);
}
}
This is the middle area
class MiddleArea extends StatefulWidget {
MiddleArea({Key? key, required this.controller, required this.animation, required this.rep}) : super(key: key);
AnimationController controller;
Animation<Offset> animation;
final bool rep;
#override
State<MiddleArea> createState() => _MiddleAreaState();
}
class _MiddleAreaState extends State<MiddleArea> {
bool _flag = true;
bool _favourite = true;
#override
Widget build(BuildContext context) {
print(widget.rep);
return SizedBox(
height: 52.h,
child: Stack(
children: [
Column(
children: [
Padding(
padding: const EdgeInsets.only(top: 135.0),
child: Text('STARBUCKS',
style: TextStyle(
fontFamily: 'Typette',
color: Colors.brown.shade200,
fontSize: 30.sp,
fontWeight: FontWeight.w400
),
),
),
Text('STARBUCKS',
style: TextStyle(
fontFamily: 'Typette',
color: Colors.brown.shade100,
fontSize: 30.sp,
fontWeight: FontWeight.w400
),
),
Text('STARBUCKS',
style: TextStyle(
fontFamily: 'Typette',
color: Colors.brown.shade50,
fontSize: 30.sp,
fontWeight: FontWeight.w400
),
),
],
),
Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: const [
SizeAndFave(text: 'Preference'),
SizeAndFave(text: 'Fave!')
],
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
GestureDetector(
onTap: (){
setState(() {
_flag = !_flag;
});
},
child: AnimatedSwitcher(
duration: const Duration(milliseconds: 500),
transitionBuilder: (Widget child, Animation<double> animation){
return FadeTransition(opacity: animation, child: child,);
},
child: widget.rep == true?Padding(
padding: const EdgeInsets.all(14.0),
key: const Key('1'),
child: Container(
height: 40,
width: 40,
decoration: BoxDecoration(
border: Border.all(
color: Colors.brown.shade300,
width: 3
),
borderRadius: BorderRadius.circular(10)
),
child: const Center(
child: Icon(
Icons.coffee_outlined,
size: 20,
),
)
),
):null,
)
),
GestureDetector(
onTap: (){
setState(() {
_favourite = !_favourite;
});
},
child: _favourite? TopIcon(icons: Icons.favorite_border, color: Colors.brown.shade300)
:TopIcon(
icons: Icons.favorite, color: Colors.brown.shade300)
)
],
)
],
),
AnimatedSwitcher(
duration: Duration(seconds: 1),
transitionBuilder: (Widget child, Animation<double> animation) {
return FadeTransition( opacity: animation,
child: child);
},
child: _flag == true ? Center(
key: const Key('1'),
child: SlideTransition(
position: widget.animation,
child: SizedBox(
height: 80.h,
width: 80.w,
child: Image.asset('assets/images/starcup.png'),
),
),
):Center(
key: const Key('2'),
child: SlideTransition(
position: widget.animation,
child: SizedBox(
height: 80.h,
width: 80.w,
child: Image.asset('assets/images/greeen.png'),
),
),
),
),
Positioned(
child:
Align(
alignment: Alignment.bottomRight,
child: Padding(
padding: EdgeInsets.only(top: 30.h),
child: TopIcon(
icons: Icons.car_crash_outlined, color: Colors.brown.shade300),
),
)),
const Positioned(
child:
Align(
alignment: Alignment.bottomLeft,
child: Padding(
padding: EdgeInsets.only(top: 330.0, left: 14),
child: Text('\$ 5.99',
style: TextStyle(
fontSize: 27,
fontWeight: FontWeight.bold
),
),
),
))
],
),
);
}
}
and lastly, the lower area
class LowerArea extends StatefulWidget {
final AnimationController controller;
final Animation<Offset> anime;
bool rep;
LowerArea({Key? key, required this.controller, required this.anime, required this.rep}) : super(key: key);
#override
State<LowerArea> createState() => _LowerAreaState();
}
class _LowerAreaState extends State<LowerArea> {
bool _bigger = true;
bool _fade = true;
void move(){
}
#override
Widget build(BuildContext context) {
return Column(
children: [
Container(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Padding(
padding: EdgeInsets.all(1.h),
child: const Text('Tall Frappuccino',
style: TextStyle(
fontWeight: FontWeight.w500
),
),
),
Padding(
padding: EdgeInsets.only(right: 5.h),
child: const Text('Swipe Down',
style: TextStyle(
fontWeight: FontWeight.w500
),
),
),
Padding(
padding: EdgeInsets.all(2.h),
child: const Text('Pickup',
style: TextStyle(
fontWeight: FontWeight.w500
),
),
)
],
),
),
SlideTransition(
position: widget.anime,
child: AnimatedContainer(
// height: 11.h,
width: _bigger ? 35.h: 80.h,
duration: const Duration(milliseconds: 500),
child: Stack(
fit: StackFit.loose,
children: [
Center(child: Image.asset('assets/images/baggie.png')),
Center(
child: Padding(
padding: EdgeInsets.only(bottom: 4.h),
child: GestureDetector(
onTap: (){
widget.controller.forward();
setState(() {
_bigger = !_bigger;
_fade = !_fade;
widget.rep = !widget.rep;
print('this is fade $_fade ');
});
},
child: AnimatedSwitcher(
duration: Duration(milliseconds: 300),
transitionBuilder: (Widget child, Animation<double> animation){
return FadeTransition(opacity: animation, child: child,);
},
child: _fade? Container(
key: Key('1'),
height: 8.h,
width: 7.w,
decoration: BoxDecoration(
color: Colors.black,
borderRadius: BorderRadius.circular(15)
),
child: Column(
children: [
Padding(
padding: EdgeInsets.all(0.3.h),
child: Icon(
Icons.lock_outline,
color: Colors.white54,
size: 2.5.h,
),
),
Icon(
Icons.arrow_drop_down,
color: Colors.white12,
size: 3.h,
),
],
),
):null,
),
),
),
)
],
),
),
)
],
);
}
use provider pacakges https://pub.dev/packages/provider
Create a class that inherits the functions of ChangeNotifyer to create a flag to control and create a setter.
provider class
class StateController extends ChangeNotifier{
bool _req = false;
bool get req => _req; //getter
setReqValue(){
_req = !_req;
notifyListener();
}
}
Declare the provider class in the main function. You can change the location of the declaration according to Wiget tree, but first declare it in main
Change main.dart
void main(){
runApp(
Multiprovider(
providers: [
ChangeNotifierProvider(create: (_) => StateController()),
],
child: HomePage(),
)
);
}
The UI is updated by notifyListener().
change UI
child: context.watch<StateController>().req == true ? Padding(
padding: const EdgeInsets.all(14.0),
key: const Key('1'),
child: Container(
height: 40,
width: 40,
decoration: BoxDecoration(
border: Border.all(
color: Colors.brown.shade300,
width: 3
),
borderRadius: BorderRadius.circular(10)
),
child: const Center(
child: Icon(
Icons.coffee_outlined,
size: 20,
),
)
),
):null,
Change State
onTap: (){
widget.controller.forward();
setState(() {
_bigger = !_bigger;
_fade = !_fade;
context.read<StateController>().setReqValue();
print('this is fade $_fade ');
});
},
I am too lazy to try understand your code. But if you want to update state of the page after you pop from Navigation to it.
In page you want to update
Navigation.push(context, /* Page that will change something */)
// Future will trigger then you return to this page.
.then((_) => setState(() {}))
The space between tab bar view and bottom navigation bar is the extra space that I want to remove.
in the image, you can see the space that shouldn't be there
class Tab_Bar2 extends StatefulWidget {
const Tab_Bar2({Key? key}) : super(key: key);
#override
_Tab_Bar2State createState() => _Tab_Bar2State();
}
class _Tab_Bar2State extends State<Tab_Bar2> with SingleTickerProviderStateMixin {
final bodyGlobalKey = GlobalKey();
final List<Widget> myTabs = [
Text(..),
Text(..),
Text(..),
Text(..),
Text(..),
Text(..),
];
late TabController _tabController;
late ScrollController _scrollController;
#override
void initState() {
_scrollController = ScrollController();
_tabController = TabController(length: 6, vsync: this);
super.initState();
}
#override
void dispose() {
_tabController.dispose();
_scrollController.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text("Dashboard"),
centerTitle: true,
backgroundColor: const Color(0xffFFC36A),
actions: [
IconButton(
onPressed: () {},
icon: const Icon(Icons.notifications),
),
]),
drawer: Drawer(
child: ListView(
padding: EdgeInsets.zero,
children: [
const DrawerHeader(
decoration: BoxDecoration(
color: Color(0xffFFC36A),
),
child: Padding(
padding: EdgeInsets.only(top: 20.0, left: 60),
child: Text(
'Drawer',
style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.bold,
fontSize: 20),
),
),
),
ListTile(
title: const Text('Log Out'),
onTap: () {
},
),
ListTile(
title: const Text('Item 2'),
onTap: () {
Navigator.pop(context);
},
),
],
),
),
body: NestedScrollView(
controller: _scrollController,
headerSliverBuilder: (BuildContext context, value) {
return [
SliverToBoxAdapter(child: Column(
children: [img1(), grid(), rsp(), LiveChart()],
),),
SliverToBoxAdapter(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
margin: EdgeInsets.symmetric(horizontal: 15,vertical: 15),
child: Text('Latest',
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
fontFamily: 'railway',
color: Theme_Data.font_color,
),
),
),
Container(
margin: EdgeInsets.symmetric(horizontal: 3.5),
padding: EdgeInsets.symmetric(horizontal: 2.5,vertical: 2.5),
height: 35,
decoration: BoxDecoration(
border: Border.all(color: Colors.grey.shade200),
borderRadius: BorderRadius.all(
Radius.circular(25),
),
),
child: TabBar(
controller: _tabController,
labelPadding: EdgeInsets.symmetric(horizontal: 2.0, vertical: 5),
indicator: BoxDecoration(
borderRadius: BorderRadius.circular(50), // Creates border
color: Theme_Data.th_light_color),
tabs: myTabs,
),
),
],
),
),
];
},
body: Container(
padding: EdgeInsets.symmetric(horizontal: 10),
child: Theme(
data: Theme.of(context).copyWith(
dividerColor: Colors.white
),
child: TabBarView(
controller: _tabController,
children: <Widget>[
SalesTable(),
QuotationsTable(),
PurchasesTable(),
TransfersTable(),
ConsumersTable(),
SuppliersTable(),
],
),
),
),
),
);
}
}
in above code i think there might be the issues between the usage of SviverToBoxAdapter what widget should i use instead to achieve the required design
Hey guys I'm working on some project and need to create a custom dropdown,
like this
I am able to make that here is the code, the code is messy but I will refactor it once I make it work. Or if you have some other way how I can accomplish this I'm open to suggestions.
GlobalKey? actionKey = GlobalKey();
List<String> picked = [];
List<IconData> icons = [
Icons.blur_circular_outlined,
Icons.sports_basketball,
Icons.sports_baseball_sharp,
Icons.sports_tennis_rounded,
Icons.people,
];
List<String> sports = [
"Fudbal",
"Kosarka",
"Tenis",
"Stoni tenis",
"Kuglanje"
];
List<int> ints = [0, 1, 2, 3, 4];
List<bool> booles = [false, false, false, false, false];
OverlayEntry? overlayEntry;
var position;
double? y;
double? x;
void findDropdownData() {
RenderBox renderBox =
actionKey!.currentContext!.findRenderObject() as RenderBox;
position = renderBox.localToGlobal(Offset.zero);
y = position!.dy;
x = position!.dx;
}
OverlayEntry _overlayEntryBuilder() {
return OverlayEntry(
builder: (context) {
return Positioned(
// top: position,
left: 16.w,
right: 16.w,
child: Material(
child: dropdownExpanded(),
),
);
},
);
}
Widget buildRows(i) {
return Padding(
padding: EdgeInsets.symmetric(horizontal: 17.w, vertical: 15.h),
child: Row(
children: [
SizedBox(
height: 24.h,
width: 24.w,
child: Checkbox(
activeColor: style.purpleMain,
value: booles[i],
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(4)),
onChanged: (value) {
setState(() {
booles[i] = value!;
booles[i] == true
? picked.add(sports[i])
: picked.remove(sports[i]);
});
},
),
),
SizedBox(
width: 10.w,
),
Text(
sports[i],
style: TextStyle(
color: booles[i] == true ? style.purpleMain : Colors.grey,
),
),
const Spacer(),
Icon(
icons[i],
color: booles[i] == true ? style.purpleMain : Colors.grey,
size: 15,
),
],
),
);
}
Widget dropdown() {
return GestureDetector(
key: actionKey,
onTap: () {
setState(() {
isPressed = !isPressed;
});
if (isPressed == false) {
overlayEntry = _overlayEntryBuilder();
Overlay.of(context)!.insert(overlayEntry!);
}
},
child: Container(
width: double.infinity,
height: 50.h,
decoration: BoxDecoration(
border: Border.all(color: style.e8e8e8),
borderRadius: BorderRadius.circular(8),
),
padding: EdgeInsets.only(left: 16.w, right: 13.w),
child: Row(
children: [
picked.isEmpty ? pickedEmpty() : pickedNotEmpty(),
const Spacer(),
const Icon(
Icons.arrow_drop_down,
color: style.bdbdbd,
),
],
),
),
);
}
Widget pickedEmpty() {
return Text(
"Možete obeležiti više aktivnosti",
style: TextStyle(
fontSize: 16.sp,
color: style.bdbdbd,
fontWeight: FontWeight.w400,
),
);
}
Widget pickedNotEmpty() {
List<Widget> list = <Widget>[];
for (var i = 0; i < picked.length; i++) {
list.add(
Padding(
padding: EdgeInsets.only(right: 5.w),
child: Text(
picked[i],
style: TextStyle(
fontSize: 16.sp,
color: style.bdbdbd,
fontWeight: FontWeight.w400,
),
),
),
);
}
return Row(children: list);
}
Widget dropdownExpanded() {
return Container(
decoration: BoxDecoration(
color: Colors.white,
border: Border.all(color: style.purpleMain),
borderRadius: BorderRadius.circular(8),
),
child: Column(
children: [
GestureDetector(
onTap: () {
setState(() {
isPressed = !isPressed;
});
overlayEntry?.remove();
},
child: Container(
width: double.infinity,
height: 50.h,
padding: EdgeInsets.only(left: 16.w, right: 13.w),
child: Row(
children: [
picked.isEmpty ? pickedEmpty() : pickedNotEmpty(),
const Spacer(),
const Icon(
Icons.arrow_drop_up,
color: style.bdbdbd,
),
],
),
),
),
const Divider(
height: 0,
thickness: 1,
color: style.e8e8e8,
indent: 17,
endIndent: 17,
),
Column(
children: [
for (int i in ints) buildRows(i),
],
),
],
),
);
}
Here are results
This is what I want to accomplish
So I just want to move down this expanded dropdown and how to update these booles in the overlay if I don't use overlay it's working as it should but I need to open that dropdown on the top of another content. Thanks for the help.
Use smart_select it is fully customizable and you can achieve the design you want easily using this library.
Updated Answer
Regarding the UI, it is like an Expansions Tile Widget in flutter. You can implement that dropdown with expansions tile and pass list of items in children,
for expand, collapse tile after select each item, you can create a global key and control that in UI.
final GlobalKey<AppExpansionTileState> expansionTile = new GlobalKey();
collapse → expansionTile.currentState.collapse();
ExpansionTile(
title: Text(
"Možete obeležiti više aktivnosti",
style: TextStyle(fontSize: 16.0, fontWeight: FontWeight.w500),
),
children: <Widget>[
// put items here
],
),
smaple :
Widget customDropDown() => Container(
// color: Colors.white,
padding: const EdgeInsets.all(10),
child: ListTileTheme(
dense: true,
child: ExpansionTile(
title: const Text(
"Možete obeležiti više aktivnosti",
style: TextStyle(fontSize: 16.0, fontWeight: FontWeight.w500),
),
children: <Widget>[
Container(
width: double.infinity,
decoration: const BoxDecoration(
color: Colors.white,
borderRadius:
BorderRadius.vertical(bottom: Radius.circular(20))),
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
children: const [
ListTile(
leading: Icon(Icons.ac_unit),
title: Text("something"),
),
ListTile(
leading: Icon(Icons.ac_unit),
title: Text("something"),
),
ListTile(
leading: Icon(Icons.ac_unit),
title: Text("something"),
),
ListTile(
leading: Icon(Icons.ac_unit),
title: Text("something"),
)
],
),
),
)
],
),
),
);
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: Scaffold(
body: SafeArea(
child: Stack(
children: [pageDesign(), customDropDown()],
),
),
),
);
}
fakeWidget(color) => Container(
height: 100,
width: double.infinity,
color: color,
child: const Center(
child: Text("widget1"),
),
);
Widget pageDesign() => Column(
children: [
/* you should control this size in diffrent orientation and for big size
device to handle responsive
*/
const SizedBox(
height: 80,
),
fakeWidget(
Colors.green,
),
fakeWidget(
Colors.yellow,
),
fakeWidget(
Colors.orange,
),
fakeWidget(
Colors.blue,
),
],
);
how to animate the added containers as soon as they appear ? ( animation of height going from 0 to containerHeight)
here is a code to illustrate my question:
import 'package:flutter/material.dart';
void main() {
runApp(MaterialApp(
home: Home(),
));
}
class Home extends StatefulWidget {
#override
_HomeState createState() => _HomeState();
}
List<Widget> widgetList = [Container()];
class _HomeState extends State<Home> {
TextEditingController controller = TextEditingController();
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Animated container'),
backgroundColor: Colors.blue,
),
body: Container(
alignment: Alignment.topCenter,
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Expanded(
child: Stack(
fit: StackFit.expand,
children: <Widget>[
Center(
child: Padding(
//shift to left
padding: const EdgeInsets.only(left: 55.0),
child: Row(
children: widgetList.toList(),
),
),
),
],
),
),
FlatButton(
child: Text(
'Add',
style: TextStyle(color: Colors.white),
),
onPressed: () {
setState(() {
add(controller.text);
});
},
color: Colors.blue,
),
FlatButton(
child: Text(
'Clear',
style: TextStyle(color: Colors.white),
),
onPressed: () {
setState(() {
widgetList.clear();
});
},
color: Colors.blue,
),
TextField(
onChanged: (text) {},
textAlign: TextAlign.center,
controller: controller,
keyboardType: TextInputType.number,
style: TextStyle(
color: Colors.white,
fontSize: 25.0,
fontWeight: FontWeight.w300),
decoration: InputDecoration(
hintStyle: TextStyle(
color: Colors.white, fontWeight: FontWeight.w300),
fillColor: Colors.blue,
filled: true,
),
),
]),
),
);
}
}
void add(String containerHeight) {
widgetList.add(Padding(
padding: const EdgeInsets.all(3.0),
child: AnimatedContainer(
decoration: BoxDecoration(
color: Colors.blue,
borderRadius: BorderRadius.circular(2.0),
),
duration: Duration(milliseconds: 165),
alignment: Alignment.center,
//color: Colors.red,
height: double.parse(containerHeight),
width: 29.0,
child: Text(
containerHeight,
style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.w600,
fontSize: containerHeight.length == 1
? 19.0
: containerHeight.length == 2
? 19.0
: containerHeight.length == 3
? 16.0
: containerHeight.length == 4 ? 14.0 : 10.0),
),
)));
}
Screenshot of the ui
You just have to put the height of the container in the text field and press 'add', then the containers will appear directly without animation,
so my question is how to animate so that the height goes from 0 to containerHeight ?
i know it works when the widget is already there and we modify it's height, but i couldn't figure out how to do in that scenario ( adding to a list and displaying it directly ).
thank you.
Try the following code. It is working.
import 'package:flutter/material.dart';
import 'dart:async';
void main() {
runApp(MaterialApp(
home: Home(),
));
}
class Home extends StatefulWidget {
#override
_HomeState createState() => _HomeState();
}
List<Widget> widgetList = [Container()];
StreamController<String> animationStream = StreamController();
class _HomeState extends State<Home> {
TextEditingController controller = TextEditingController();
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Animated container'),
backgroundColor: Colors.blue,
),
body: Container(
alignment: Alignment.topCenter,
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Expanded(
child: Stack(
fit: StackFit.expand,
children: <Widget>[
Center(
child: Padding(
//shift to left
padding: const EdgeInsets.only(left: 55.0),
child: Row(
children: widgetList.toList(),
),
),
),
],
),
),
FlatButton(
child: Text(
'Add',
style: TextStyle(color: Colors.white),
),
onPressed: () {
animationStream = StreamController();
setState(() {
add("0");
animationStream.sink.add(controller.text);
});
},
color: Colors.blue,
),
FlatButton(
child: Text(
'Clear',
style: TextStyle(color: Colors.white),
),
onPressed: () {
setState(() {
widgetList.clear();
});
},
color: Colors.blue,
),
TextField(
onChanged: (text) {},
textAlign: TextAlign.center,
controller: controller,
keyboardType: TextInputType.number,
style: TextStyle(
color: Colors.white,
fontSize: 25.0,
fontWeight: FontWeight.w300),
decoration: InputDecoration(
hintStyle: TextStyle(
color: Colors.white, fontWeight: FontWeight.w300),
fillColor: Colors.blue,
filled: true,
),
),
]),
),
);
}
}
void add(String containerHeight) {
widgetList.add(new MyWidget());
}
class MyWidget extends StatelessWidget {
const MyWidget({
Key key,
}) : super(key: key);
#override
Widget build(BuildContext context) {
return StreamBuilder(
stream: animationStream.stream,
builder: (context, snapshot) {
String _hight = "0";
if (snapshot.hasData ) {
_hight = snapshot.data;
try { double.parse(_hight);} catch (e) { print('please enter a valid hight');_hight="0"; }
}
return Padding(
padding: const EdgeInsets.all(3.0),
child: AnimatedContainer(
decoration: BoxDecoration(
color: Colors.blue,
borderRadius: BorderRadius.circular(2.0),
),
duration: Duration(milliseconds: 2165),
alignment: Alignment.center,
//color: Colors.red,
height: double.parse(_hight),
width: 29.0,
child: Text(
_hight,
style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.w600,
fontSize: _hight.length == 1
? 19.0
: _hight.length == 2
? 19.0
: _hight.length == 3
? 16.0
: _hight.length == 4 ? 14.0 : 10.0),
),
));
},
);
}
}