Flutter: Convert Simple Dialog To Full Screen Dialog On Scroll - android

I have a UI layout in my head, essentially the same as the new menu/account chooser as in the Google Maps app. It is a modal dialog that pops up on the press of the profile button and is scrollable. When scrolled, the dialog animates into a full screen dialog, and vice-versa.
I am aiming to use a Material Design compatible way of doing this, and it currently only needs to work on Android.
Some minor changes would be made, but my question is: Is that possible in Flutter? Thanks.

Well, to implement this kind of animation on dialog might be bit complex.
You can use animations plugins for this.
For more details you can see this video.
Chances are that you might not manage to create animations with dialog, so in that case you can use stack and show custom dialog to user.

Author here,
I have created this menu, and the code snippet is below:
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import - ANOTHER PACKAGE -
import 'package:google_fonts/google_fonts.dart';
import 'package:provider/provider.dart';
import 'package:theme_provider/theme_provider.dart';
import '../../services/authManager.dart';
import '../../services/models.dart';
import '../home.dart';
class MainMenu extends StatefulWidget {
const MainMenu({
Key key,
}) : super(key: key);
#override
_MainMenuState createState() => _MainMenuState();
}
class _MainMenuState extends State<MainMenu>
with SingleTickerProviderStateMixin {
#override
Widget build(BuildContext context) {
final mainProps = Provider.of<MainProps>(context);
final authVals = Provider.of<AuthVals>(context);
final userData = Provider.of<CustomUser>(context);
final userDataPrivate = Provider.of<CustomUserPrivate>(context);
final userDataReadOnly = Provider.of<CustomUserReadOnly>(context);
return IgnorePointer(
ignoring: !mainProps.menuOpen,
child: AnimatedOpacity(
opacity: mainProps.menuOpen ? 1 : 0,
duration: Duration(milliseconds: 150),
child: Container(
color: Colors.black.withOpacity(0.75),
child: Stack(
children: [
SafeArea(
child: Container(
width: MediaQuery.of(context).size.width,
margin: EdgeInsets.only(
top: mainProps.menuPadTop + 10,
left: mainProps.menuPadLeft,
right: mainProps.menuPadRight,
),
child: Container(
width: 100.0,
decoration: BoxDecoration(
borderRadius: BorderRadius.all(
Radius.circular(mainProps.menuCorners)),
color: Theme.of(context).backgroundColor,
),
padding: EdgeInsets.only(
top: 10,
left: 10,
right: 10,
),
child: NotificationListener<ScrollNotification>(
onNotification: (scrollNotification) {
if (scrollNotification is ScrollEndNotification) {
if (((mainProps.menuScrollCtrl.position.pixels > 100
? 100
: mainProps
.menuScrollCtrl.position.pixels) -
100)
.abs() >=
25) {
WidgetsBinding.instance.addPostFrameCallback((_) {
mainProps.menuScrollCtrl.animateTo(0,
duration: Duration(milliseconds: 150),
curve: Curves.easeInOut);
});
} else if (mainProps.menuScrollCtrl.position.pixels
.abs() >
75 &&
mainProps.menuScrollCtrl.position.pixels.abs() <
100) {
WidgetsBinding.instance.addPostFrameCallback((_) {
mainProps.menuScrollCtrl.animateTo(100,
duration: Duration(milliseconds: 150),
curve: Curves.easeInOut);
});
}
}
return true;
},
child: Container(
height: 155,
child: Padding(
padding: const EdgeInsets.only(top: 8.0),
child: Column(
children: [
Row(
crossAxisAlignment: CrossAxisAlignment.baseline,
mainAxisAlignment:
MainAxisAlignment.spaceEvenly,
children: [
(userData.public != 'Local Account'
? CircleAvatar(
radius: 20,
backgroundImage: NetworkImage(
authVals.authUser.photoURL,
),
)
: CircleAvatar(
radius: 20,
child: SvgPicture.network(
userData.photoURL,
color: Theme.of(context)
.primaryColor ==
Color(0xffff9800)
? Colors.black
: Colors.white),
backgroundColor:
Theme.of(context).backgroundColor,
)),
Column(
children: [
Text(
userData.publicExt,
style: TextStyle(
fontWeight: FontWeight.bold),
),
Text(userDataPrivate?.realName ??
'Please Wait...'),
Text(authVals.authUser.email == ''
? 'Anonymous'
: authVals.authUser.email),
Text(userDataReadOnly != null
? userDataReadOnly.joined
.toDate()
.toLocal()
.toString()
: 'Please Wait...'),
],
),
],
),
Spacer(),
Row(
mainAxisAlignment:
MainAxisAlignment.spaceEvenly,
children: [
Visibility(
visible: !mainProps.signingOut,
child: OutlineButton(
onPressed: null,
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
Icon(Icons.account_circle),
SizedBox(width: 15),
Text('View Profile'),
],
),
),
),
OutlineButton(
onPressed: () async {
if (!mainProps.signingOut) {
mainProps.signingOut = true;
} else {
await AuthService().signOut();
Navigator.of(context).popAndPushNamed(
-SCREEN-);
}
},
child: AnimatedContainer(
duration: Duration(milliseconds: 250),
constraints: mainProps.signingOut
? BoxConstraints(
maxWidth: MediaQuery.of(context)
.size
.width -
82)
: BoxConstraints(maxWidth: 93),
child: Row(
mainAxisSize: !mainProps.signingOut
? MainAxisSize.min
: MainAxisSize.max,
mainAxisAlignment:
MainAxisAlignment.center,
children: [
Icon(Icons.logout,
color: mainProps.signingOut
? Colors.red
: null),
SizedBox(width: 15),
LimitedBox(
child: Text(
'Sign Out',
style: TextStyle(
color: mainProps.signingOut
? Colors.red
: null),
),
),
],
),
),
),
],
),
Spacer(),
],
),
),
),
),
),
),
),
SafeArea(
child: Container(
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height,
margin: EdgeInsets.only(
top: mainProps.menuPadTop +
(mainProps.menuScrollCtrl.hasClients
? (((mainProps.compassExpanded ? 195 : 195) / 100) *
(100 -
(mainProps.menuScrollCtrl.position.pixels >
100
? 100
: mainProps
.menuScrollCtrl.position.pixels)))
: -mainProps.menuPadTop),
left: mainProps.menuPadLeft,
right: mainProps.menuPadRight,
),
child: Container(
width: 100.0,
height: 100.0,
decoration: BoxDecoration(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(mainProps.menuCorners),
topRight: Radius.circular(mainProps.menuCorners),
),
color: Theme.of(context).backgroundColor,
),
padding: EdgeInsets.only(
top: 10,
left: 10,
right: 10,
),
child: NotificationListener<ScrollNotification>(
onNotification: (scrollNotification) {
if (scrollNotification is ScrollEndNotification) {
if (((mainProps.menuScrollCtrl.position.pixels > 100
? 100
: mainProps
.menuScrollCtrl.position.pixels) -
100)
.abs() >=
25) {
WidgetsBinding.instance.addPostFrameCallback((_) {
mainProps.menuScrollCtrl.animateTo(0,
duration: Duration(milliseconds: 150),
curve: Curves.easeInOut);
});
} else if (mainProps.menuScrollCtrl.position.pixels
.abs() >
75 &&
mainProps.menuScrollCtrl.position.pixels.abs() <
100) {
WidgetsBinding.instance.addPostFrameCallback((_) {
mainProps.menuScrollCtrl.animateTo(100,
duration: Duration(milliseconds: 150),
curve: Curves.easeInOut);
});
}
}
},
child: SingleChildScrollView(
child: const Text(
'hello\n\n\n\na\n\n\n\no\n\n\n\na\n\n\n\no\n\n\n\na\n\n\n\no\n\n\n\no\n\n\n\no\n\n\n\no\n\n\n\no\n\n\n\no\n\n\n\no\n\n\n\no\n\n\n\no\n\n\n\no\n\n\n\no\n\n\n\no\n\n\n\no\n\n\n\no\n\n\n\no\n\n\n\no\n\n\n\no\n\n\n\no\n\n\n\no\n\n\n\no\n\n\n\no\n\n\n\no\n\n\n\no\n\n\n\no\n\n\n\no\n\n\n\no\n\n\n\no\n\n\n\no\n\n\n\no\n\n\n\no\n\n\n\no\n\n\n\no\n\n\n\no\n\n\n\no\n\n\n\no\n\n\n\no\n\n\n\no\n\n\n\no\n\n\n\no\n\n\n\no\n\n\n\no\n\n\n\no\n\n\n\n'),
controller: mainProps.menuScrollCtrl,
),
),
),
),
),
SafeArea(
child: Container(
width: MediaQuery.of(context).size.width,
height: mainProps.compassExpanded ? 60 : 52,
decoration: BoxDecoration(
borderRadius: BorderRadius.all(
Radius.circular(mainProps.menuCorners * 4),
),
),
margin: EdgeInsets.only(
top: mainProps.topMenuPadTop,
left: mainProps.menuPadLeft,
right: mainProps.menuPadRight,
),
child: Material(
borderRadius: BorderRadius.all(
Radius.circular(mainProps.menuCorners * 4),
),
elevation: 4,
color: Theme.of(context).backgroundColor,
child: Row(
children: [
Padding(
padding: const EdgeInsets.only(left: 10.0),
child: IconButton(
icon: Icon(Icons.close),
onPressed: () {
mainProps.menuOpen = false;
mainProps.signingOut = false;
mainProps.menuScrollCtrl.jumpTo(0);
},
),
),
Expanded(
child: Text(
-TEXT-,
style: GoogleFonts.ubuntu(
textStyle: TextStyle(fontSize: 17),
fontWeight: FontWeight.w600,
),
textAlign: TextAlign.center,
),
),
Padding(
padding: const EdgeInsets.only(right: 10.0),
child: Stack(
children: [
Opacity(
opacity: mainProps.menuScrollCtrl.hasClients
? ((mainProps.menuScrollCtrl.position
.pixels >
100
? 0
: 100 -
mainProps.menuScrollCtrl
.position.pixels) /
100)
: 1,
child: IgnorePointer(
ignoring: mainProps.menuScrollCtrl.hasClients
? (mainProps.menuScrollCtrl.position
.pixels >=
100
? -1
: 100 -
mainProps.menuScrollCtrl
.position.pixels) <
0
: false,
child: IconButton(
icon: Icon(Icons.palette),
onPressed: () => showDialog(
context: context,
builder: (_) => ThemeConsumer(
child: ThemeDialog(
title: Row(
children: [
Icon(Icons.palette),
SizedBox(width: 15),
Text('Choose Theme'),
],
),
hasDescription: false,
),
),
),
),
),
),
Opacity(
opacity: 1.0 -
(mainProps.menuScrollCtrl.hasClients
? ((mainProps.menuScrollCtrl.position
.pixels >
100
? 0
: 100 -
mainProps.menuScrollCtrl
.position.pixels) /
100)
: 1),
child: IgnorePointer(
ignoring:
!(mainProps.menuScrollCtrl.hasClients
? (mainProps.menuScrollCtrl.position
.pixels >=
100
? -1
: 100 -
mainProps.menuScrollCtrl
.position.pixels) <
0
: false),
child: IconButton(
icon: Icon(Icons.keyboard_arrow_down),
onPressed: () =>
mainProps.menuScrollCtrl.animateTo(
0,
duration: Duration(milliseconds: 250),
curve: Curves.easeInOut,
),
),
),
),
],
),
),
],
),
),
),
),
],
),
),
),
);
}
}
mainProps is just my state management solution, using Provider. Doing this using setState would be a nightmare and would probably bulk the code considerably. I think the rest of the code is self-explanatory. It has nice animations and some cool features.
You can see it working here: https://photos.app.goo.gl/aH6otb6CkbYbwpsr7
I'm considering creating a package with similar code to the code above, and sharing it on pub.dev. If you think that would help you, please let me know in the comments of this answer.

Related

Using carousel slider with page view

I am using carousal slider with page view but when I am sliding the images in scroll view it is sliding to me to next page instead of next image. I just want to slide images when I slide on image and i want to slide to the next page when i slide below the image. but now wherever i slide on the screen it take me to the next page.
This is my page view.
import 'package:bartermade/controllers/profileController.dart';
import 'package:bartermade/models/tradeModel.dart';
import 'package:bartermade/widgets/profileView.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import '../screens/home/bottomBarViews/homeView/categoriesDetailScreen.dart';
class PageViewHolder extends StatelessWidget {
final PageController pageController = PageController(
initialPage: 0,
);
ProfileController _profileController = Get.find();
final String reciverId;
final String currentUserId;
final TradeModel catData;
PageViewHolder(
{required this.reciverId,
required this.currentUserId,
required this.catData});
var followersList = ['Ali', 'Hussain', 'Hassan', 'Akhtar'];
#override
Widget build(BuildContext context) {
// print("cat ID " + "${catData.user.id}");
// print("profile ID " + "${_profileController.profileId}");
return Scaffold(
body: PageView(
// physics: catData.user.id != _profileController.profileId.value
// ? AlwaysScrollableScrollPhysics()
// : NeverScrollableScrollPhysics(),
physics: ClampingScrollPhysics(),
pageSnapping: false,
onPageChanged: (index) {
},
controller: pageController,
children: [
//first screen in page view
TradeDetailScreen(
catData: catData,
currentUserId: currentUserId,
reciverId: reciverId,
),
//second screen here
ProfileView(
firstName: catData.user.firstName,
lastName: catData.user.lastName,
followers: followersList,
profileUrl: catData.user.profilePictureUrl,
screenState: true,
),
],
),
);
}
}
And this is my screen page
#override
Widget build(BuildContext context) {
return Scaffold(
body: LayoutBuilder(
builder: (context, constraints) {
return OrientationBuilder(
builder: (context, orientation) => SafeArea(
child: SingleChildScrollView(
child: Column(children: [
Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
IconButton(
onPressed: () {
Get.back();
},
icon: Icon(
Icons.arrow_back_ios,
color: Colors.grey,
)),
Container(
clipBehavior: Clip.antiAlias,
height: 50,
width: 50,
decoration: BoxDecoration(
shape: BoxShape.circle,
),
child: CachedNetworkImage(
fit: BoxFit.cover,
imageUrl: '${widget.profileUrl}',
placeholder: (context, url) =>
Center(child: CircularProgressIndicator()),
errorWidget: (context, url, error) =>
Icon(Icons.error),
),
),
SizedBox(
width: 7,
),
Flexible(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Row(
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: [
Text(
"${widget.lastName ?? " " "${widget.firstName ?? " "}"}",
maxLines: 2,
overflow: TextOverflow.ellipsis,
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: (MediaQuery.of(context)
.size
.height /
100) *
2),
),
widget.catData["user"] ==
profileController.userId.value
? Container(
height: 0,
width: 0,
)
: Container(
padding: EdgeInsets.all(5),
child: Center(
child: Text(
'Follow',
style: TextStyle(
color: Colors.white,
fontSize: 12),
),
),
//width: 50,
decoration: BoxDecoration(
color: AppColors.pinkAppBar,
borderRadius: BorderRadius.all(
Radius.circular(20)))),
],
),
Row(
//crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'4.3',
style: TextStyle(
color: Colors.grey,
fontWeight: FontWeight.bold,
fontSize: (MediaQuery.of(context)
.size
.height /
100) *
1.8),
),
Icon(
Icons.star,
size: 15,
color: Colors.yellow,
),
],
),
],
),
)
],
),
),
Column(
children: [
widget.catData["pictures"] == [] ||
widget.catData["pictures"].length == 0 ||
widget.catData["pictures"].isEmpty ||
widget.catData["pictures"] == null
? Container(
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height * 0.6,
child: Center(child: Text(" No Image to show")))
: Stack(
children: [
CarouselSlider(
items: widget.catData["tradeWithPictures"]
.map<Widget>((e) {
return Container(
width: Get.width,
child: CachedNetworkImage(
fit: BoxFit.cover,
imageUrl: e['url'],
placeholder: (context, url) => Center(
child: CircularProgressIndicator()),
errorWidget: (context, url, error) =>
Icon(Icons.error),
),
);
}).toList(),
carouselController:
postController.carouselController,
options: CarouselOptions(
autoPlay: true,
enableInfiniteScroll: true,
height: Get.height * .7,
viewportFraction: 1.0,
enlargeCenterPage: false,
aspectRatio: 1 / 1.3,
onPageChanged: (index, reason) {
// postController.tradeImagesIndex(index);
// postController.carouselController.nextPage();
},
),
),
Positioned(
top: MediaQuery.of(context).size.height * 0.3,
bottom:
MediaQuery.of(context).size.height * 0.3,
left: 0,
right: 0,
child: Container(
padding:
EdgeInsets.symmetric(horizontal: 10),
width: MediaQuery.of(context).size.width,
child: Row(
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: [
ElevatedButton(
child: Icon(Icons.arrow_back_ios),
style: ButtonStyle(
splashFactory:
NoSplash.splashFactory,
shape: MaterialStateProperty.all<
RoundedRectangleBorder>(
RoundedRectangleBorder(
borderRadius:
BorderRadius.circular(25.0),
side: BorderSide(
color: AppColors.pinkColor),
),
),
),
onPressed: () {
postController.carouselController
.previousPage();
},
),
ElevatedButton(
child: Icon(Icons.arrow_forward_ios),
style: ButtonStyle(
splashFactory:
NoSplash.splashFactory,
shape: MaterialStateProperty.all<
RoundedRectangleBorder>(
RoundedRectangleBorder(
borderRadius:
BorderRadius.circular(25.0),
side: BorderSide(
color: AppColors.pinkColor),
),
),
),
onPressed: () {
postController.carouselController
.nextPage();
},
),
],
),
),
),
],
),
SizedBox(
height: 10,
),
],
),
Container(
margin: EdgeInsets.all(10),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
widget.catData["title"],
style: TextStyle(
color: AppColors.detailTextsColor,
fontWeight: FontWeight.bold),
),
profileController.userId == widget.catData["user"]
? Container(
height: 0,
width: 0,
)
: InkWell(
onTap: () {
},
child: Container(
padding: EdgeInsets.all(5),
child: Center(
child: Text(
'Offer Trade',
style: TextStyle(
color: Colors.white,
fontSize: 12),
),
),
//width: 50,
decoration: BoxDecoration(
color: AppColors.pinkAppBar,
borderRadius: BorderRadius.all(
Radius.circular(20),
),
),
),
),
],

Make an animated container behave like collapsing toolbar in flutter

Image looks like this
I have this widget that acts as a tab bar but was not create with a Tab bar. I want that widget to behave like a collapsing toolbar. Can anyone please help me out? This is the code
This is the code for the animated container which I want to behave like a collapsing toolbar...
Here is the code:
class Watching extends StatefulWidget {
final set_state;
const Watching(this.set_state, {Key? key}) : super(key: key);
#override
_WatchState createState() => _WatchState();
}
class _WatchState extends State<Watching> with TickerProviderStateMixin {
late AnimationController _controller;
late Animation<double> animation, animation2;
final double startingHeight = 20.0;
List pages = [];
int index = 0;
GlobalKey _bottomNavigationKey = GlobalKey();
List titles = [feed, trending, explore];
#override
void initState() {
super.initState();
pages = [
MainPage(
set_state: widget.set_state,
),
TrendingPage(set_state: widget.set_state),
ExplorePage()
];
_controller =
AnimationController(vsync: this, duration: Duration(seconds: 5));
animation = Tween<double>(begin: 125, end: 150).animate(_controller);
animation2 = Tween<double>(begin: 125, end: 150).animate(_controller);
_controller.forward(from: 0.0);
}
#override
void dispose() {
_controller.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
backgroundColor: Colors.white,
appBar: PreferredSize(
preferredSize: Size(MediaQuery.of(context).size.width, twoFiftyDp),
child: Container(
color: Colors.teal,
child: Stack(
children: [
AnimatedContainer(
duration: Duration(milliseconds: 400),
width: animation.value,
height: animation.value <= 150 ? 150 : animation.value,
decoration: BoxDecoration(
color: Colors.teal,
),
),
Align(
alignment: Alignment.bottomRight,
child: RotationTransition(
turns: AlwaysStoppedAnimation(0 / 360),
child: ClipPath(
clipper: LeftRoundedClipper(flip: true),
child: AnimatedContainer(
duration: Duration(milliseconds: 400),
width: animation2.value - 10,
height: animation2.value *
MediaQuery.of(context)
.size
.height, //<= 150 ? 200 :animation.value,
decoration: BoxDecoration(
color: Colors.teal,
gradient: LinearGradient(
colors: [
Colors.lightGreen.withGreen(10),
Colors.greenAccent,
Colors.greenAccent
],
)),
),
),
),
),
Align(
alignment: Alignment.bottomCenter,
child: CurvedNavigationBar(
key: _bottomNavigationKey,
height: 65,
color: Colors.white,
buttonBackgroundColor: Colors.transparent,
backgroundColor: Colors.transparent,
animationCurve: Curves.easeInOut,
animationDuration: Duration(milliseconds: 600),
index: 0,
onTap: (value) {
switch (value) {
case 0:
/* animation = Tween<double>(begin: 125, end: 0)
.animate(_controller);*/
animation2 = Tween<double>(begin: 125, end: 500)
.animate(_controller);
break;
case 1:
animation2 = Tween<double>(begin: 125, end: 700)
.animate(_controller);
/* animation = Tween<double>(begin: -10, end: 50)
.animate(_controller);*/
break;
case 2:
animation = Tween<double>(begin: 125, end: 500)
.animate(_controller);
animation2 = Tween<double>(begin: 150, end: 200)
.animate(_controller);
break;
}
setState(() {
index = value;
});
},
items: [
Text(
Main,
style: index == 0
? TextStyle(
color: Colors.white, fontWeight: FontWeight.bold)
: TextStyle(color: Colors.black54),
),
Text(
trending,
style: index == 1
? TextStyle(
color: Colors.white, fontWeight: FontWeight.bold)
: TextStyle(color: Colors.black54),
),
Text(
explore,
style: index == 2
? TextStyle(
color: Colors.white, fontWeight: FontWeight.bold)
: TextStyle(color: Colors.black54),
),
],
),
),
Align(
alignment: Alignment.bottomLeft,
child: Padding(
padding:
const EdgeInsets.only(bottom: sixtyDp, left: tenDp),
child: ListTile(
title: Text(
titles[index],
style: TextStyle(
fontSize: fiftyDp,
fontWeight: FontWeight.bold,
color: Colors.white),
)),
)),
Align(
alignment: Alignment.topLeft,
child: Padding(
padding: const EdgeInsets.only(top: fiftyDp, left: twentyDp),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
index == 0
? ShowIcon(
iconName: 'assets/icons/User.png',
onIconTap: () {},
)
: SizedBox(),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 25),
child: Row(
children: [
Padding(
padding: const EdgeInsets.only(right: fourteenDp),
child: ShowIcon(
iconName: 'assets/icons/MagnifyingGlass.png',
onIconTap: () {},
),
),
Padding(
padding: const EdgeInsets.only(right: fourteenDp),
child: ShowIcon(
iconName: 'assets/icons/BellRinging.png',
onIconTap: () {},
),
),
ShowIcon(
iconName: 'assets/icons/PaperPlane.png',
onIconTap: () {},
),
],
),
)
// Spacer(),
],
),
),
)
],
),
),
),
// body: pages[index],
body: DefaultTabController(
length: pages.length, child: NestedScrollView(headerSliverBuilder: (context, innerBoxIsScrolled) {
return <Widget>[
SliverList(delegate: SliverChildListDelegate([]))
];
}, body: pages[index]),
),
),
);
}
}

How to delete blank spaces or null Container in SliverGrid.count?

I'm trying to delete the Null Container in SliverGrid.count after validated the map entries . I wish the issue arrive you . thanks in advance for you solution .
class myGridItem extends StatefulWidget {
final Item item;
final EdgeInsets? margin;
const myGridItem({
Key? key,
required this.item,
this.margin,
}) : super(key: key);
#override
_myGridItemState createState() => _myGridItemState();
}
class _myGridItemState extends State<myGridItem> {
#override
Widget build(BuildContext context) {
return Container(
margin: widget.margin == null ? EdgeInsets.zero : widget.margin,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(7),
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.05),
offset: Offset.zero,
blurRadius: 15.0,
)
],
),
child: Column(
children: [
Expanded(
child: Stack(
alignment: Alignment.center,
children: [
Container(
margin: EdgeInsets.only(top: 37),
height: 180,
decoration: BoxDecoration(
image: DecorationImage(
alignment: Alignment.bottomCenter,
image: AssetImage(widget.item.imagePath),
),
),
),
// --------------------------- create favourit widget
Positioned(
top: 16,
right: 16,
child: Container(
width: 40,
height: 40,
alignment: Alignment.center,
decoration: BoxDecoration(
color: primaryColor,
shape: BoxShape.circle,
),
child: Text(
'999%',
textAlign: TextAlign.center,
style: TextStyle(color: Colors.white),
),
),
),
// ------------------------- discont missing
],
),
),
Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
widget.item.name,
style: TextStyle(
color: Colors.black,
fontSize: 13,
height: 1.5,
),
),
SizedBox(
height: 10,
),
Wrap(
spacing: 3,
crossAxisAlignment: WrapCrossAlignment.center,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
'${Item.format(widget.item.price)}',
style: TextStyle(
fontSize: 18,
color: primaryColor,
height: 1.5,
),
),
],
)
],
),
],
),
)
],
),
);
}
}
Here the creation of SliverGrid.count to display the items I tried to use SliverChildBuilderDelegate but the same issue after some Editing on it to reach the same level of SliverGrid.count .
class myCartItemDisplay extends StatefulWidget {
#override
_myCartItemDisplayState createState() => _myCartItemDisplayState();
}
class _myCartItemDisplayState extends State<myCartItemDisplay> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: myAppBar(
title: 'Cart',
myBarColor: Colors.white,
mybackWidget: HomeScreen(),
),
bottomNavigationBar: AppBottomNavigation(),
backgroundColor: Colors.white,
body: SafeArea(
child: CustomScrollView(
slivers: [
Container(
child: SliverGrid.count(
crossAxisCount: 2,
childAspectRatio: 0.65,
mainAxisSpacing: 16,
crossAxisSpacing: 16,
children: Fake.furniture.asMap().entries.map((f) {
return Container(
child: f.value.addToCart == 1
? myGridItem(
item: f.value,
margin: EdgeInsets.only(
left: f.key.isEven ? 16 : 0,
right: f.key.isOdd ? 16 : 0,
))
: null,
);
}).toList(),
),
),
],
),
),
);
}
}
You can add a filter before your map:
children: Fake.furniture.asMap().entries
.where((f) => f.value.addToCart == 1)
.map((f) {
return Container(
child: myGridItem(
item: f.value,
margin: EdgeInsets.only(
left: f.key.isEven ? 16 : 0,
right: f.key.isOdd ? 16 : 0,
),
),
);
}).toList(),
This way you won't end up with any null entries in the first place.
I fixed it by add a new List it has my target entries
List<Item> _names = Fake.furniture.where((i) => i.addToCart == 1).toList();
And then :
_names.asMap().entries.map((f)
But if you have another solution with flutter give us it , thanks

Nested Gesture Does not change on Tap

I am currently working on the ui stuff for the appliction, so the thing is i have one gesture as a parent that swipes up and down and based on it the position of the widgets gets changed but the problem is the child gesture does not get any precedence when tapped on it it gives the precedence. So my tree structure is Pageview.builder which has single widget with topmost parent as Gesturedetector and the children accrodingly, Can any one tell me what i am doing wrong or any improvements to get the gesture for each.
Below is the sample code that i have been working on:
import 'dart:math';
import 'package:LocationAnimation/Model/device_model.dart';
import 'package:LocationAnimation/SplashPage/splash_page.dart';
import 'package:LocationAnimation/widgets/device_function_widget.dart';
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:google_fonts/google_fonts.dart';
import 'Model/device_model.dart' as devices;
import 'Model/locations_model.dart' as locations;
import 'extensions/capitalize.dart';
void main() {
runApp(new MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'HAL',
home: MyHomePage(),
);
}
}
class SampleList {
final String locationName;
SampleList({this.locationName});
}
class MyHomePage extends StatefulWidget {
#override
State createState() => new MyHomePageState();
}
class MyHomePageState extends State<MyHomePage> with TickerProviderStateMixin {
final _controller = new PageController();
final _kArrowColor = Colors.black.withOpacity(0.8);
bool _isSwipe = false;
bool _isLoading = false;
var list = [
SampleList(locationName: 'Living Room'),
SampleList(locationName: 'Bed Room'),
SampleList(locationName: 'Back Porch Lights'),
SampleList(locationName: 'Basement Porch Lights'),
SampleList(locationName: 'Sample Room'),
];
#override
Widget build(BuildContext context) {
return new Scaffold(
body: new IconTheme(
data: new IconThemeData(color: _kArrowColor),
child: new Stack(
children: <Widget>[
new PageView.builder(
physics: _isSwipe
? NeverScrollableScrollPhysics()
: AlwaysScrollableScrollPhysics(),
controller: _controller,
itemCount: list.length,
itemBuilder: (BuildContext context, int index) {
return LocationDetails(
isLoading: _isLoading,
item: list[index],
onSwipeDown: () {
setState(() {
_isSwipe = false;
});
},
onSwipeUp: () {
setState(() {
_isSwipe = true;
});
},
);
},
),
],
),
),
);
}
}
class LocationDetails extends StatefulWidget {
final bool isLoading;
SampleList item;
final Function() onSwipeUp;
final Function() onSwipeDown;
LocationDetails(
{Key key, this.item, this.onSwipeUp, this.onSwipeDown, this.isLoading})
: super(key: key);
#override
_LocationDetailsState createState() => _LocationDetailsState();
}
class _LocationDetailsState extends State<LocationDetails> {
DragStartDetails startVerticalDragDetails;
DragUpdateDetails updateVerticalDragDetails;
bool moveWidget = false;
bool dismissSwipeText = true;
bool _isRotate = false;
int currentSelectedIndex = 0;
bool ignoreChildGestures = true;
bool _isSwpie = false;
#override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Container(
child: GestureDetector(
onTap: () {
print('Tap');
},
onVerticalDragStart: (dragDetails) {
startVerticalDragDetails = dragDetails;
},
onVerticalDragUpdate: (dragDetails) {
updateVerticalDragDetails = dragDetails;
},
onVerticalDragEnd: (endDetails) {
double dx = updateVerticalDragDetails.globalPosition.dx -
startVerticalDragDetails.globalPosition.dx;
double dy = updateVerticalDragDetails.globalPosition.dy -
startVerticalDragDetails.globalPosition.dy;
double velocity = endDetails.primaryVelocity;
//Convert values to be positive
if (dx < 0) dx = -dx;
if (dy < 0) dy = -dy;
if (velocity < 0) {
widget.onSwipeUp();
print('drag up');
setState(() {
moveWidget = true;
_isSwpie = true;
});
} else {
widget.onSwipeDown();
print(' drag down');
setState(() {
moveWidget = false;
_isSwpie = false;
});
}
},
child: Container(
height: MediaQuery.of(context).size.height,
width: MediaQuery.of(context).size.width,
decoration: new BoxDecoration(
image: new DecorationImage(
colorFilter: ColorFilter.mode(
Colors.black.withOpacity(0.8), BlendMode.srcOver),
image: /* moveWidget
? */
AssetImage(
'Assets/backgroundImage.jpg',
),
/* : NetworkImage(widget.samplePage.networkImage), */
fit: BoxFit.fill,
),
),
child:
/* widget.isLoading
? Center(
child: CircularProgressIndicator(),
)
: */
Stack(
children: <Widget>[
AnimatedOpacity(
opacity: moveWidget ? 0 : 1,
duration: Duration(microseconds: 100),
child: Padding(
padding: const EdgeInsets.all(20.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Column(
children: <Widget>[
Icon(
Icons.power_settings_new,
color: Colors.white,
size: 30,
),
Icon(
Icons.more_horiz,
color: Colors.white,
size: 25,
)
],
),
Row(
children: <Widget>[
Column(
children: <Widget>[
Text(
'Inside Temp',
style: TextStyle(
color: Colors.white, fontSize: 18),
),
SizedBox(
height: 5,
),
Row(
children: <Widget>[
Icon(
Icons.ac_unit,
color: Colors.white,
size: 20,
),
SizedBox(
width: 10,
),
Text(
'19 C',
style: TextStyle(color: Colors.white),
),
],
)
],
),
SizedBox(
width: 10,
),
Column(
children: <Widget>[
Text(
'Outside Temp',
style: TextStyle(
color: Colors.white, fontSize: 18),
),
SizedBox(
height: 5,
),
Row(
children: <Widget>[
Icon(
Icons.ac_unit,
color: Colors.white,
size: 20,
),
SizedBox(
width: 10,
),
Text(
'19 C',
style: TextStyle(color: Colors.white),
),
],
)
],
),
],
)
],
),
),
),
AnimatedPositioned(
onEnd: () {
setState(() {
dismissSwipeText = !dismissSwipeText;
//print(dismissSwipeText);
});
},
curve: Curves.ease,
duration: Duration(milliseconds: 700),
bottom: moveWidget
? 10
: MediaQuery.of(context).size.height * 0.18,
left: 10.0,
right: 0.0,
top: moveWidget
? 50
: MediaQuery.of(context).size.height * 0.75,
child: AnimatedOpacity(
opacity: dismissSwipeText ? 1 : 0,
duration: Duration(milliseconds: 500),
child: Text(
'Swipe up to customize',
style: TextStyle(color: Colors.white, fontSize: 20),
),
),
),
AnimatedPositioned(
curve: Curves.ease,
duration: Duration(milliseconds: 700),
onEnd: () {
setState(() {
_isSwpie = true;
});
},
left: 10,
top: moveWidget
? 80
: MediaQuery.of(context).size.height * 0.80,
child: Container(
width: MediaQuery.of(context).size.width * 0.97,
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
GestureDetector(
onTap: () {
setState(() {
currentSelectedIndex = 0;
});
},
child: Container(
width: MediaQuery.of(context).size.width * 0.20,
height:
MediaQuery.of(context).size.height * 0.10,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20),
color: currentSelectedIndex == 0
? Colors.blue
: Colors.grey[900],
),
child: Center(
child: Text(
'Lights',
style: GoogleFonts.lato(
color: Colors.white,
fontWeight: FontWeight.w700),
)),
),
),
Row(
children: <Widget>[
SizedBox(
width: 10,
),
GestureDetector(
onTap: () {
setState(() {
currentSelectedIndex = 1;
});
},
child: Container(
width: MediaQuery.of(context).size.width *
0.20,
height: MediaQuery.of(context).size.height *
0.10,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20),
color: currentSelectedIndex == 1
? Colors.blue
: Colors.grey[900],
),
child: Center(
child: Text(
'Applicanes',
style: GoogleFonts.lato(
color: Colors.white,
fontWeight: FontWeight.w700),
)),
),
),
],
),
Row(
children: <Widget>[
SizedBox(
width: 10,
),
GestureDetector(
onTap: () {
setState(() {
currentSelectedIndex = 2;
});
},
child: Container(
width: MediaQuery.of(context).size.width *
0.20,
height: MediaQuery.of(context).size.height *
0.10,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20),
color: currentSelectedIndex == 2
? Colors.blue
: Colors.grey[900],
),
child: Center(
child: Text(
'Sensors',
style: GoogleFonts.lato(
color: Colors.white,
fontWeight: FontWeight.w700),
)),
),
),
],
),
Row(
children: <Widget>[
SizedBox(
width: 10,
),
Container(
width:
MediaQuery.of(context).size.width * 0.20,
height:
MediaQuery.of(context).size.height * 0.10,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20),
color: Colors.grey[900],
),
child: Center(
child: Text(
'Doors \n& Locks',
style: GoogleFonts.lato(
color: Colors.white,
fontWeight: FontWeight.w700),
)),
),
],
),
SizedBox(
width: 10,
),
],
),
),
),
AnimatedPositioned(
curve: Curves.ease,
duration: Duration(milliseconds: 400),
bottom: moveWidget
? 10
: MediaQuery.of(context).size.height * 0.20,
left: 10.0,
right: 0.0,
top: moveWidget
? 15
: MediaQuery.of(context).size.height * 0.70,
child: Text(
'${widget.item.locationName}',
style: TextStyle(fontSize: 30, color: Colors.white),
),
),
],
)),
),
),
),
);
}
}
You can add Color to the last AnimatedPositioned which use text widget.item.locationName in your code, like:
AnimatedPositioned(
curve: Curves.ease,
duration: Duration(milliseconds: 400),
bottom: moveWidget
? 10
: MediaQuery.of(context).size.height * 0.20,
left: 10.0,
right: 0.0,
top: moveWidget
? 15
: MediaQuery.of(context).size.height * 0.70,
child: Container(
color: Colors.white,
Text(
'${widget.item.locationName}',
style: TextStyle(fontSize: 30, color: Colors.white),
),
),
),
You will see a white screen (the widget which blocking you) when you scroll up. You can fix it by 2 ways
Change the bottom 10 to a larger number
Move this part of AnimatedPositioned to Top of the Stack widget
The Nested Gesture should work probably as you expected.
First of All you are using multiple Scaffold in a single page which is not recommended.
And remove the unwanted widgets from your tree which will help you to debug a way more better level. And Next you can try with passing a Callback function from parent to child which can eventually solve your problem

I keep getting a bottom overflowed by 128 pixels for my flutter app even when tried wrapping some widgets in an Expanded

I keep getting an error which says a part of my app overflowed by certain pixels, as i was developing it on my phone it looked fine, but as i installed it on other devices i keep getting errors, i tried wrapping some of my widgets in an Expanded but im still getting the error
this is how it looked on my phone, it looked great
How the app looked on my device
How the app looked after i installed on a different device
Here is my code
import 'package:flutter/material.dart';
import 'package:hotel_search/FadeAnimation.dart';
import 'package:hotel_search/home_page.dart';
import 'package:page_transition/page_transition.dart';
class StarterPage extends StatefulWidget {
#override
_StarterPageState createState() => _StarterPageState();
}
class _StarterPageState extends State<StarterPage> with TickerProviderStateMixin{
AnimationController _animationController;
Animation<double> _animation;
bool _textVisible = true;
#override
void initState() {
_animationController = AnimationController(
vsync: this,
duration: Duration(milliseconds: 100)
);
_animation = Tween<double>(
begin: 1.0,
end: 25.0
).animate(_animationController);
super.initState();
}
#override
void dispose() {
_animationController.dispose();
super.dispose();
}
void _onTap() {
setState(() {
_textVisible = false;
});
_animationController.forward().then((f) =>
Navigator.push(context, PageTransition(type: PageTransitionType.fade, child: HomePage()))
);
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage('assets/images/back.jpg'),
fit: BoxFit.cover
)
),
child: Container(
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.bottomCenter,
colors: [
Colors.black.withOpacity(.9),
Colors.black.withOpacity(.8),
Colors.black.withOpacity(.2),
]
)
),
child: Padding(
padding: EdgeInsets.all(20.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
Expanded(
child:Container(
child: Column(
children: <Widget>[
Container( width: MediaQuery.of(context).size.width,height: 400,
child:FadeAnimation(.5, Image.asset(
"assets/images/brand.png",
width: 0,
height:0,
fit: BoxFit.contain,)),),
SizedBox(height: 30,),
Container( width: MediaQuery.of(context).size.width,
child:FadeAnimation(.5, Text('Welcome', style: TextStyle(color: Colors.white, fontSize: 50, fontWeight: FontWeight.bold),)),),
SizedBox(height: 20,),
Container( width: MediaQuery.of(context).size.width,
child: FadeAnimation(1, Text("Sunbird Hotels and Resorts is Malawi’s leading hotel chain", style: TextStyle(color: Colors.white, height: 1.4, fontSize: 18),)),),
SizedBox(height: 0,)
]
)
))
,Row(
children: <Widget>[
FadeAnimation(1.2,
ScaleTransition(
scale: _animation,
child: Container(
width: MediaQuery.of(context).size.width/2.3,
decoration: BoxDecoration(
color: Colors.white
),
child: AnimatedOpacity(
opacity: _textVisible ? 1.0 : 0.0,
duration: Duration(milliseconds: 50),
child: MaterialButton(
onPressed: () {
Navigator.of(context).pushReplacement(MaterialPageRoute(
builder: (BuildContext context) => HomePage()));
},
minWidth: double.infinity,
child: Text("JOIN", style: TextStyle(color: Colors.black, fontSize: 20,fontWeight: FontWeight.w800),),
),
)
)),
),
SizedBox(width: 10,),
FadeAnimation(1.2,
ScaleTransition(
scale: _animation,
child: Container(
width: MediaQuery.of(context).size.width/2.3,
decoration: BoxDecoration(
color: Color(0xff008d4b)
),
child: AnimatedOpacity(
opacity: _textVisible ? 1.0 : 0.0,
duration: Duration(milliseconds: 50),
child: MaterialButton(
onPressed: () {
Navigator.of(context).pushReplacement(MaterialPageRoute(
builder: (BuildContext context) => HomePage()));
},
minWidth: double.infinity,
child: Text("SIGN IN", style: TextStyle(color: Colors.white, fontSize: 20,fontWeight: FontWeight.w800),),
),
)
)),
)
]),
SizedBox(height: 30,),
FadeAnimation(1.4,
AnimatedOpacity(
opacity: _textVisible ? 1.0 : 0.0,
duration: Duration(milliseconds: 50),
child: Align(
child: Text("Continue as a Guest", style: TextStyle(color: Colors.white70, fontSize: 15),),
),
)),
SizedBox(height: 30,),
],
),
),
),
),
);
}
}
Make the body of your Scaffold a SingleChildScrollView and the first container it's child.

Categories

Resources