Scroll animation like yelp app in flutter - flutter

I'm trying to make a CustomScrollView similar to this:
I'm using a SliverAppBar but it seems that it is not the right way. My code so far:
CustomScrollView(
slivers: <Widget>[
SliverAppBar(
expandedHeight: 340,
pinned: true,
flexibleSpace: FlexibleSpaceBar(
background: BackgroundImageWidget(),
centerTitle: true,
// title: Text("Search by cities or activitry in Kreis Kleve"),
title: SearchButtonWidget(),
),
),
),
SliverList(...)
What I get:
I cant figure out why the SearchButtonWidget is so huge at first. When it's shrinked it has the right size.
Is sliverAppBar with fliexibleSpace even the right approach?
Edit: can someone also tell me how to make the search button overlapping with the widget below? I guess sliverAppBar can't do that.
Edit 2: maybe it's a white background added under the image. I need to investigate this.

#override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
top: true,
child: CustomScrollView(
slivers: <Widget>[
SliverPersistentHeader(
delegate: MySliverAppBar(
expandedHeight: 250,
title: Container(
margin: EdgeInsets.symmetric(horizontal: 20.0, vertical: 0),
decoration: BoxDecoration(
color: Colors.grey[200],
borderRadius: BorderRadius.all(Radius.circular(5.0))),
child: Row(children: <Widget>[
Padding(
padding: EdgeInsets.only(left: 20.0, right: 10.0),
child: Icon(Icons.search),
),
Expanded(
child: TextFormField(
keyboardType: TextInputType.text,
textInputAction: TextInputAction.done,
cursorColor: Colors.black,
autofocus: false,
decoration: InputDecoration(
filled: true,
fillColor: Colors.transparent,
contentPadding: EdgeInsets.symmetric(
vertical: 10, horizontal: 15),
hintText: "Search",
border: InputBorder.none,
disabledBorder: OutlineInputBorder(
borderSide:
new BorderSide(color: Colors.transparent),
borderRadius: new BorderRadius.circular(2),
),
focusedBorder: OutlineInputBorder(
borderSide:
new BorderSide(color: Colors.transparent),
borderRadius: new BorderRadius.circular(2),
)),
),
)
]),
)),
pinned: true,
),
SliverList(
delegate: SliverChildBuilderDelegate((context, index) {
return Container(
child: ListTile(
title: Text("${index}a"),
));
}, childCount: 25))
],
),
),
);
}
.
class MySliverAppBar extends SliverPersistentHeaderDelegate {
final double expandedHeight;
final Widget title;
MySliverAppBar({#required this.expandedHeight, this.title});
final _avatarMarginTween = EdgeInsetsTween(
begin: EdgeInsets.only(bottom: 20),
end: EdgeInsets.only(
bottom: 0.0,
));
final _searchMarginTween = EdgeInsetsTween(
begin: EdgeInsets.only(bottom: 0),
end: EdgeInsets.only(bottom: 8,));
final _avatarAlignTween =
AlignmentTween(begin: Alignment.bottomCenter, end: Alignment.center);
#override
Widget build(
BuildContext context, double shrinkOffset, bool overlapsContent) {
double tempVal = 75 * maxExtent / 100;
final progress = shrinkOffset > tempVal ? 1.0 : shrinkOffset / tempVal;
final avatarMargin = _avatarMarginTween.lerp(progress);
final searchMargin = _searchMarginTween.lerp(progress);
final searchAlignment = progress > 0.8 ? _avatarAlignTween.lerp(progress) : _avatarAlignTween.lerp(0);
return Stack(
fit: StackFit.expand,
overflow: Overflow.visible,
children: <Widget>[
Padding(
padding: avatarMargin,
child: Image.network(
"https://images.pexels.com/photos/396547/pexels-photo-396547.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500",
fit: BoxFit.cover,
),
),
Center(
child: Opacity(
opacity: shrinkOffset / expandedHeight > 0.7 ? shrinkOffset / expandedHeight : 0.0,
child: Container(
color: Colors.red,
)
),
),
Padding(
padding: searchMargin,
child: Align(
alignment: Alignment.bottomCenter,
child: title,
),
)
],
);
}
#override
double get maxExtent => expandedHeight;
#override
double get minExtent => kToolbarHeight;
#override
bool shouldRebuild(SliverPersistentHeaderDelegate oldDelegate) => true;
}

Related

In Flutter, How to make SliverAppBar respect the top safe area on Floating State when it is not primary

I have a SliverAppBar looks like this is normal state which is what I want:
but when scrolling down the app bar doesn't respect the top safe area on its floating state:
here is my build method code
return Scaffold(
body: CustomScrollView(
controller: _scrollController,
slivers: <Widget>[
SliverSafeArea(
bottom: false,
sliver: SliverPadding(
padding: const EdgeInsets.symmetric(horizontal: 5),
sliver: SliverAppBar(
primary: false,
centerTitle: true,
actions: actions,
floating: true,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)),
title: const Text('title'),
),
),
),
SliverGrid(
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 4,
),
delegate: SliverChildBuilderDelegate(
(BuildContext context, int index) {
return Container(
margin: const EdgeInsets.all(20),
color: Colors.amber,
);
},
childCount: 130,
),
),
],
),
);
I think you need a custom app bar for your purpose.
something like this
class FloatingAppBar extends StatelessWidget {
const FloatingAppBar(
this.title, {
this.actions = const <Widget>[],
Key? key,
this.leading = const BackButton(),
this.height = 48,
}) : super(key: key);
final String? title;
final List<Widget> actions;
final Widget leading;
final double height;
#override
Widget build(BuildContext context) {
//final Color bgColor = isDark(context) ? Colors.grey.shade800 : Colors.white;
return Center(
child: Container(
height: height,
width: MediaQuery.of(context).size.width - 20,
constraints: const BoxConstraints(maxWidth: 600),
decoration: BoxDecoration(
color: isDark(context) ? Colors.grey.shade800 : Colors.white,
borderRadius: BorderRadius.circular(8),
boxShadow: <BoxShadow>[
BoxShadow(
color: isDark(context) ? Colors.black54 : Colors.grey.shade500,
blurRadius: 1,
spreadRadius: 0.1,
offset: const Offset(0, 0.7),
),
],
),
padding: const EdgeInsets.all(0),
margin: const EdgeInsets.only(top: 5),
child: Row(
children: <Widget>[
leading,
Expanded(
child: Center(
child: Text(
title ?? '',
textDirection: getTextDirection(title ?? ''),
style: const TextStyle(
fontWeight: FontWeight.bold,
//color: Colors.black87,
),
),
),
),
if (actions.isEmpty)
const IconButton(
padding: EdgeInsets.all(0),
iconSize: 20,
icon: Icon(iconArrowLeft, color: Colors.transparent),
onPressed: null,
),
//
...actions
],
),
),
);
}
}

sliver app bar with search functionality in flutter

hope you have good day. I wanna achieve something like this below => gif image 1
for whom gif is not clear.it is screenshot from app called Yelp. it is sliver app bar with expanding and collapsing. when it collapse search bar goes fixed to title.
anyway i have done by far this => gif image 2
my search bar is shrinking when i collapse sliver app bar. i want that search wont shrink when i collapse sliver app bar and fix search bar in title above. this is my code
import 'package:flutter/material.dart';
class HomePage extends StatefulWidget {
#override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
double changingHeight;
double appBarHeight;
bool appBarSearchShow = false;
final TextEditingController _filter = new TextEditingController();
List<String> itemList = [];
#override
void initState() {
for (int count = 0; count < 50; count++) {
itemList.add("Item $count");
}
changingHeight = 300;
}
#override
Widget build(BuildContext context) {
appBarHeight = MediaQuery.of(context).padding.top + kToolbarHeight;
return Scaffold(
backgroundColor: Colors.white,
body: NestedScrollView(
headerSliverBuilder: (BuildContext context, bool innerBoxScrolled) {
return <Widget>[createSilverAppBar()];
},
body: ListView.builder(
itemCount: itemList.length,
itemBuilder: (context, index) {
return Card(
child: ListTile(
title: Text(itemList[index]),
),
);
})),
);
}
SliverAppBar createSilverAppBar() {
return SliverAppBar(
backgroundColor: Colors.white,
expandedHeight: 300,
floating: false,
pinned: true,
// title: appBarSearchShow == true
// ? CupertinoTextField(
// controller: _filter,
// keyboardType: TextInputType.text,
// placeholder: "Search..",
// placeholderStyle: TextStyle(
// color: Color(0xffC4C6CC),
// fontSize: 14.0,
// fontFamily: 'Brutal',
// ),
// prefix: Padding(
// padding: const EdgeInsets.fromLTRB(9.0, 6.0, 9.0, 6.0),
// child: Icon(
// Icons.search,
// ),
// ),
// decoration: BoxDecoration(
// borderRadius: BorderRadius.circular(8.0),
// color: Colors.white,
// ),
// )
// : Container(),
flexibleSpace: LayoutBuilder(
builder: (BuildContext context, BoxConstraints constraints) {
if (constraints.biggest.height == appBarHeight) {
appBarSearchShow = true;
} else {
appBarSearchShow = false;
}
return FlexibleSpaceBar(
collapseMode: CollapseMode.parallax,
titlePadding: EdgeInsets.only(bottom: 10),
centerTitle: true,
title: constraints.biggest.height != appBarHeight
? Container(
//margin: EdgeInsets.symmetric(horizontal: 10),
constraints: BoxConstraints(minHeight: 30, maxHeight: 30),
width: 220,
decoration: BoxDecoration(
boxShadow: <BoxShadow>[
BoxShadow(
color: Colors.grey.withOpacity(0.6),
offset: const Offset(1.1, 1.1),
blurRadius: 5.0),
],
),
child: CupertinoTextField(
controller: _filter,
keyboardType: TextInputType.text,
placeholder: 'Search',
placeholderStyle: TextStyle(
color: Color(0xffC4C6CC),
fontSize: 14.0,
fontFamily: 'Brutal',
),
prefix: Padding(
padding: const EdgeInsets.fromLTRB(5.0, 5.0, 0.0, 5.0),
child: Icon(
Icons.search,
size: 18,
),
),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(8.0),
color: Colors.white,
),
),
)
: Container(),
background: Container(
//height: constraints.maxHeight - 15,
color: Colors.white,
margin: EdgeInsets.only(bottom: 30),
child: Image.asset(
'assets/mainBackImage.jpg',
fit: BoxFit.cover,
),
),
);
}),
);
}
}
any help would be appreciated.
This is a solution to make the search bar fixed and stop it from shrinking:
You can use two SilverAppBars, one for the background image and one for the search bar. The first SilverAppBar has no title and elevation and is not pinned. The second SilverAppBar is pinned and has elevation and its title is the SearchBar.
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
body: NestedScrollView(
headerSliverBuilder: (BuildContext context, bool innerBoxScrolled) {
return <Widget>[
createSilverAppBar1(),
createSilverAppBar2()
];
},
body: ListView.builder(
itemCount: itemList.length,
itemBuilder: (context, index) {
return Card(
child: ListTile(
title: Text(itemList[index]),
),
);
})),
);
}
SliverAppBar createSilverAppBar1() {
return SliverAppBar(
backgroundColor: Colors.redAccent,
expandedHeight: 300,
floating: false,
elevation: 0,
flexibleSpace: LayoutBuilder(
builder: (BuildContext context, BoxConstraints constraints) {
return FlexibleSpaceBar(
collapseMode: CollapseMode.parallax,
background: Container(
color: Colors.white,
child: Image.asset(
'assets/mainBackImage.jpg',
fit: BoxFit.cover,
),
),
);
}),
);
}
SliverAppBar createSilverAppBar2() {
return SliverAppBar(
backgroundColor: Colors.redAccent,
pinned: true,
title: Container(
margin: EdgeInsets.symmetric(horizontal: 10),
height: 40,
decoration: BoxDecoration(
boxShadow: <BoxShadow>[
BoxShadow(
color: Colors.grey.withOpacity(0.6),
offset: const Offset(1.1, 1.1),
blurRadius: 5.0),
],
),
child: CupertinoTextField(
controller: _filter,
keyboardType: TextInputType.text,
placeholder: 'Search',
placeholderStyle: TextStyle(
color: Color(0xffC4C6CC),
fontSize: 14.0,
fontFamily: 'Brutal',
),
prefix: Padding(
padding: const EdgeInsets.fromLTRB(5.0, 5.0, 0.0, 5.0),
child: Icon(
Icons.search,
size: 18,
color: Colors.black,
),
),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(8.0),
color: Colors.white,
),
),
),
);
}
Result:
This is a solution to make a layout based on gif image 1:
Using Stack you can make the search bar stack on top of the background. The search bar's offset would be expandedHeight - shrinkOffset - 20 since it should be dependent on how much the app bar is shrinked and the total height of the app bar when its not shrinked. The 20 is half the height of the search bar and its subtracted to make the search bar move up half its height.
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
body: NestedScrollView(
headerSliverBuilder: (BuildContext context, bool innerBoxScrolled) {
return <Widget>[
SliverPersistentHeader(
delegate: MySliverAppBar(expandedHeight: 200, filter: _filter),
pinned: true,
),
];
},
body: ListView.builder(
itemCount: itemList.length,
itemBuilder: (context, index) {
return Card(
child: ListTile(
title: Text(itemList[index]),
),
);
})),
);
}
class MySliverAppBar extends SliverPersistentHeaderDelegate {
final double expandedHeight;
final TextEditingController filter;
MySliverAppBar({#required this.expandedHeight, #required this.filter});
#override
Widget build(
BuildContext context, double shrinkOffset, bool overlapsContent) {
var searchBarOffset = expandedHeight - shrinkOffset - 20;
return Stack(
fit: StackFit.expand,
overflow: Overflow.visible,
children: [
Container(
child: Image.network(
'assets/mainBackImage.jpg',
fit: BoxFit.cover,
),
),
(shrinkOffset < expandedHeight - 20) ? Positioned(
top: searchBarOffset,
left: MediaQuery.of(context).size.width / 4,
child: Card(
elevation: 10,
child: SizedBox(
height: 40,
width: MediaQuery.of(context).size.width / 2,
child: CupertinoTextField(
controller: filter,
keyboardType: TextInputType.text,
placeholder: 'Search',
placeholderStyle: TextStyle(
color: Color(0xffC4C6CC),
fontSize: 14.0,
fontFamily: 'Brutal',
),
prefix: Padding(
padding: const EdgeInsets.fromLTRB(5.0, 5.0, 0.0, 5.0),
child: Icon(
Icons.search,
size: 18,
color: Colors.black,
),
),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(8.0),
color: Colors.white,
),
),
),
),
) : Container(
margin: EdgeInsets.symmetric(
horizontal: MediaQuery.of(context).size.width / 4,
vertical: (kToolbarHeight - 40) / 4
),
child: Card(
elevation: 10,
child: CupertinoTextField(
controller: filter,
keyboardType: TextInputType.text,
placeholder: 'Search',
placeholderStyle: TextStyle(
color: Color(0xffC4C6CC),
fontSize: 14.0,
fontFamily: 'Brutal',
),
prefix: Padding(
padding: const EdgeInsets.fromLTRB(5.0, 5.0, 0.0, 5.0),
child: Icon(
Icons.search,
size: 18,
color: Colors.black,
),
),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(8.0),
color: Colors.white,
),
),
),
),
],
);
}
#override
double get maxExtent => expandedHeight;
#override
double get minExtent => kToolbarHeight;
#override
bool shouldRebuild(SliverPersistentHeaderDelegate oldDelegate) => true;
}
Result:

scrolling to the top when typing on TextField on Flutter

I added TextFormField on SliverPersistentHeaderDelegate. After scroll to the middle/bottom and then typing on to the textField, SliverList automatically come to the top. How do I disable this?
Full Code.
class MyWidget extends StatelessWidget {
static const String route = '/myWidget';
#override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
child: CustomScrollView(
slivers: <Widget>[
SliverPersistentHeader(
pinned: true,
delegate: MyDynamicHeader(),
),
SliverList(
delegate: SliverChildBuilderDelegate((BuildContext context, int index) {
return Container(
height: 200,
color: Color(Random().nextInt(0xffffffff)),
);
},
)
)
],
)
)
);
}
}
class MyDynamicHeader extends SliverPersistentHeaderDelegate {
int index = 0;
#override
Widget build(BuildContext context, double shrinkOffset, bool overlapsContent) {
return LayoutBuilder(
builder: (context, constraints) {
final Color color = Colors.primaries[index];
final double percentage = (constraints.maxHeight - minExtent)/(maxExtent - minExtent);
if (++index > Colors.primaries.length-1)
index = 0;
return Container(
decoration: BoxDecoration(
boxShadow: [BoxShadow(blurRadius: 4.0, color: Colors.black45)],
gradient: LinearGradient(
colors: [Colors.blue, color]
)
),
height: constraints.maxHeight,
child: SafeArea(
child: Center(
child: Row(
children: <Widget>[
CircularProgressIndicator(
value: percentage,
valueColor: AlwaysStoppedAnimation<Color>(Colors.white),
),
InkWell(
onTap: (){
print('is working');
},
child: Container(
height: 50,
width: 100,
color: Palette.orelPay,
),
),
Expanded(child: TextFormField(
//controller: searchController,
decoration: InputDecoration(
contentPadding:
EdgeInsets.fromLTRB(20.0, 15.0, 20.0, 15.0),
hintText: "Search on OrelBuy",
border: OutlineInputBorder(
borderSide:
BorderSide(color: Palette.background, width: 32.0),
borderRadius: BorderRadius.circular(50.0)),
fillColor: Palette.background,
filled: true,
enabledBorder: OutlineInputBorder(
borderSide:
BorderSide(color: Palette.background, width: 32.0),
borderRadius: BorderRadius.circular(50.0)),
focusedBorder: OutlineInputBorder(
borderSide:
BorderSide(color: Palette.background, width: 32.0),
borderRadius: BorderRadius.circular(50.0))),
),)
],
),
)
),
);
}
);
}
#override
bool shouldRebuild(SliverPersistentHeaderDelegate old) => false;
#override
double get maxExtent => 250.0;
#override
double get minExtent => 80.0;
}
you can use physics of CustomScrollView widget to control scroll.
CustomScrollView(
physics: PageScrollPhysics(), // added
slivers: <Widget>[

Design this animation using SliverAppBar flutter

Here's what I want to build but I am able to achieve this
by the following code,
#override
Widget build(BuildContext context) {
return Scaffold(
body: NestedScrollView(
headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled){
return [
SliverAppBar(
expandedHeight: 120,
floating: false,
pinned: false,
flexibleSpace: Container(
padding: EdgeInsets.all(10),
height: 160,
width: double.infinity,
child: Column(
mainAxisAlignment: MainAxisAlignment.end,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Align(
alignment: Alignment.topCenter,
child: Text(
'Hello World',
)),
Padding(
padding: EdgeInsets.only(top: 16),
child: Image.asset(
'assets/images/banner.png',
),
),
],
),
),
),
];
},
body: ListView.builder(),
),
);
}
I have tried SliverAppBar using flexible and expanded, but was not able to achieve.
Update -
First element of list is going behind text field. I want to scroll only when the animation is completed
updated answer,
#override
Widget build(BuildContext context) {
return Scaffold(
body: CustomScrollView(
slivers: <Widget>[
TransitionAppBar(
extent: 250,
avatar: Text("Rancho"),
title: Container(
margin: EdgeInsets.symmetric(horizontal: 20.0, vertical: 0),
decoration: BoxDecoration(
color: Colors.grey[200],
borderRadius: BorderRadius.all(Radius.circular(5.0))),
child: Row(children: <Widget>[
Padding(
padding: EdgeInsets.only(left: 20.0, right: 10.0),
child: Icon(Icons.search),
),
Expanded(
child: TextFormField(
keyboardType: TextInputType.text,
textInputAction: TextInputAction.done,
cursorColor: Colors.black,
autofocus: false,
style: TextField_Style,
decoration: InputDecoration(
filled: true,
fillColor: Colors.transparent,
contentPadding:
EdgeInsets.symmetric(vertical: 10, horizontal: 15),
hintText: "Search",
border: InputBorder.none,
disabledBorder: OutlineInputBorder(
borderSide: new BorderSide(color: Colors.transparent),
borderRadius: new BorderRadius.circular(2),
),
focusedBorder: OutlineInputBorder(
borderSide: new BorderSide(color: Colors.transparent),
borderRadius: new BorderRadius.circular(2),
)),
),
)
]),
),
),
SliverList(
delegate: SliverChildBuilderDelegate((context, index) {
return Container(
color: Colors.blue,
child: ListTile(
title: Text("${index}a"),
));
}, childCount: 25))
],
),
);
}
.
class TransitionAppBar extends StatelessWidget {
final Widget avatar;
final Widget title;
final double extent;
TransitionAppBar({this.avatar, this.title, this.extent = 250, Key key}) : super(key: key);
#override
Widget build(BuildContext context) {
return SliverPersistentHeader(
pinned: true,
delegate: _TransitionAppBarDelegate(
avatar: avatar,
title: title,
extent: extent > 200 ? extent : 200
),
);
}
}
class _TransitionAppBarDelegate extends SliverPersistentHeaderDelegate {
final _avatarMarginTween = EdgeInsetsTween(
begin: EdgeInsets.only(bottom: 70, left: 30),
end: EdgeInsets.only(left: 0.0, top: 30.0));
final _avatarAlignTween =
AlignmentTween(begin: Alignment.bottomLeft, end: Alignment.topCenter);
final Widget avatar;
final Widget title;
final double extent;
_TransitionAppBarDelegate({this.avatar, this.title, this.extent = 250})
: assert(avatar != null),
assert(extent == null || extent >= 200),
assert(title != null);
#override
Widget build(
BuildContext context, double shrinkOffset, bool overlapsContent) {
double tempVal = 34 * maxExtent / 100;
final progress = shrinkOffset > tempVal ? 1.0 : shrinkOffset / tempVal;
print("Objechjkf === ${progress} ${shrinkOffset}");
final avatarMargin = _avatarMarginTween.lerp(progress);
final avatarAlign = _avatarAlignTween.lerp(progress);
return Stack(
children: <Widget>[
AnimatedContainer(
duration: Duration(milliseconds: 100),
height: shrinkOffset * 2,
constraints: BoxConstraints(maxHeight: minExtent),
color: Colors.redAccent,
),
Padding(
padding: avatarMargin,
child: Align(
alignment: avatarAlign,
child: avatar
),
),
Padding(
padding: EdgeInsets.only(bottom: 10),
child: Align(
alignment: Alignment.bottomCenter,
child: title,
),
)
],
);
}
#override
double get maxExtent => extent;
#override
double get minExtent => (maxExtent * 68) / 100;
#override
bool shouldRebuild(_TransitionAppBarDelegate oldDelegate) {
return avatar != oldDelegate.avatar || title != oldDelegate.title;
}
}

How to reuse a widget in flutter

I am learning flutter I want a particular widget to be reused with different images at run time.
How to attain this is giving me difficulties I would like to know how to get this.
I am writing the peice of code kindly suggest what is a correct way
scaffold: CupertinoPageScaffold(
navigationBar: CupertinoNavigationBar(
trailing: Image.asset('assets/Menu_Button.png'),
automaticallyImplyLeading: false,
backgroundColor: Colors.blueAccent,
),
child: SafeArea(
child: Material(
child: Container(
child: Column(
children: [
Column(
children: <Widget>[
new Stack(children: <Widget>[
new Container(
child: background.Row1
),
Container(
color: Colors.blueAccent,
child: Image.asset('assets/card_bg.png')
),
]
),
Container(
color: Colors.blueAccent,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
ShowingOptions('assets/image1.png').Options,//*****calling function with parameter so that it can put widget**********//
ShowingOptions('assets/image2.png').Options,
ShowingOptions('assets/image3.png').Options,
ShowingOptions('assets/image4.png').Options,
],
),
background.Row2,
background.Row3
],
),
),
))
),
);
}
}
/**********function defination starts *************/
ShowingOptions(image) {
Widget Options = padding: EdgeInsets.only(bottom: 5, left: 7,
right: 7, top: 5),
child: Container(
height: 55.0,
width: 55.0,
child: Padding(
padding: EdgeInsets.all(1),
child: CircleAvatar(
backgroundColor: Colors.transparent,
radius: 10,
child: new Image.asset(image, height: 150, width:
150),
)),
decoration: new BoxDecoration(
shape: BoxShape.circle,
color: Colors.white,
border: new Border.all(
color: Colors.orange,
width: 5.0,
),
)
),
);
}
}
/**********function defination ends *************/
What Iam doing is making a funciton and when I am calling the function 'showOptions('assets/image1')' I am passing the image that I need to show.
Inside the function defination I am writing a widget that I wanted to be placed whenevr I call that funcition bys showing the image that I have passed
the way I implemented this whole is not working want a solution. I know this is not the proper way as I am new I would like to have some guidance.
Create a Custom Widget,
Create a Stateless or Stateful Class
declare Required Vairables
return your Custom Widget
below is Example of CustomButton with onPressed event.
//Create a Stateless or Stateful Class
class CustomButton extends StatelessWidget {
//declare Required Vairables
final String buttonText;
final VoidCallback onPressed;
final bool loading;
//constructor
CustomButton({this.buttonText,this.onPressed,this.loading});
#override
Widget build(BuildContext context) {
return Row(
children: <Widget>[
Expanded(
child: Padding(
padding: const EdgeInsets.only(left: 30,right: 30),
child: Container(
decoration: BoxDecoration(borderRadius: BorderRadius.all(Radius.circular(100)),
color: Colors.red),
child: Material(
color: Colors.transparent,
child: InkWell(
borderRadius: BorderRadius.all(Radius.circular(100)),
splashColor: Colors.green,
onTap: onPressed,
child: Padding(
padding: const EdgeInsets.all(15.0),
child: Center(child:
loading==true?
CircularProgressIndicator(backgroundColor: Colors.white,)
:
Text(buttonText,style: TextStyle(fontSize: 30,color: Colors.white),)),
),
),
),
),
),
),
],
);
}
}
Use :
CustomButtonSmall(buttonText: "Direction",onPressed: (){})
Here is a wonderfully explained example of how to achieve this easily.
I just copy the code from there. You basically have to create a separate class for the widget you have in mind:
import 'package:flutter/material.dart';
class AppTextFormField extends StatelessWidget {
//
AppTextFormField({
this.controller,
this.hintText,
this.helpText,
this.prefixIcon,
this.suffixIcon,
this.isPassword,
this.enabled,
this.readOnly,
this.borderColor,
});
final TextEditingController controller;
final String hintText;
final String helpText;
final IconData prefixIcon;
final IconData suffixIcon;
final bool isPassword;
final bool enabled;
final bool readOnly;
final Color borderColor;#override
Widget build(BuildContext context) {
return Container(
child: TextFormField(
controller: controller,
readOnly: null == readOnly ? false : true,
obscureText: null == isPassword ? false : true,
decoration: InputDecoration(
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(
color: Colors.greenAccent,
width: 1.0,
),
),
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(
color: Colors.greenAccent,
width: 1.0,
),
),
border: OutlineInputBorder(
borderSide: BorderSide(
color: null == borderColor ? Colors.teal : borderColor,
width: 1.0,
),
),
hintText: null == hintText ? '' : hintText,
helperText: null == helpText ? '' : helpText,
prefixIcon: null == prefixIcon ? null : Icon(prefixIcon),
suffix: null == suffixIcon ? null : Icon(suffixIcon),
enabled: null == enabled ? true : false,
),
),
);
}
}
And then in the class where you want to use the widget you call the it like this:
Container(
child: Column(
children: [
AppTextFormField(
controller: _emailController,
helpText: 'Email',
hintText: 'Email',
prefixIcon: Icons.email,
),
AppTextFormField(
controller: _passwordController,
helpText: 'Password',
hintText: 'Password',
isPassword: true,
prefixIcon: Icons.lock_open,
),
You don't have to use all the methods, just the ones you need.