I am trying to implement Shared Axis Transition between two tabs.
When the bottomNavigationBar is tapped, the selectedIndex goes from 0 to 1, and vice versa. During that change, the transition should animate. My code does not have any errors but no animations occurs.
Appreciate any advice.
Thanks.
body: PageTransitionSwitcher(
duration: const Duration(milliseconds: 500),
transitionBuilder: (Widget child, Animation<double> primaryAnimation,
Animation<double> secondaryAnimation) {
return SharedAxisTransition(
animation: primaryAnimation,
secondaryAnimation: secondaryAnimation,
transitionType: SharedAxisTransitionType.horizontal,
child: child);
},
child: selectedIndex == 0
? AnimationLimiter(
child: AnimatedList(
key: _key,
initialItemCount: db.dailyList.length,
itemBuilder: (context, index, animation) {
return AnimationConfiguration.staggeredList(
position: index,
duration: const Duration(milliseconds: 375),
child: SlideAnimation(
verticalOffset: 50.0,
child: FadeInAnimation(
child: SizeTransition(
sizeFactor: animation,
child: Tile(
title: db.dailyList[index][0],
goalAchieved: db.dailyList[index][1],
onChanged: (value) =>
{checkBoxChanged(value, index)},
deleteFunction: (context) => deleteGoal(index),
),
),
),
),
);
},
),
)
: AnimationLimiter(
child: ListView.builder(
itemCount: dbAchieved.dailyAchievedList.length,
itemBuilder: (context, index) {
return AchievedTile(
title: dbAchieved.dailyAchievedList[index][0],
deleteFunction: (context) => deleteAchievedGoal(index),
);
},
),
),
),
bottomNavigationBar: BottomNavigationBar(
backgroundColor: Theme.of(context).backgroundColor,
unselectedItemColor: Colors.black.withOpacity(0.7),
selectedItemColor: Colors.black,
currentIndex: selectedIndex,
onTap: (index) => setState(() {
selectedIndex = index;
}),
items: const [
BottomNavigationBarItem(
icon: Icon(Icons.fact_check_outlined), label: 'Carpe Diem'),
BottomNavigationBarItem(icon: Icon(Icons.done), label: 'Achieved')
],
),
turns out, i just need to declare a key for each of the AnimationLimiter for it to work. I just added the following:
static const dailyKey = Key('dailyKey');
static const dailyAcheivedKey = Key('dailyAchievedKey');
and then adding it in the AnimationLimiter
key: dailyKey
key: dailyAchievedKey
Related
how can i do this i tried to use popupmenubutton but it didn't work as i wanted. is there any widget or something you can suggest?What can i do for this anyone know?Can i use showdialog.What is the solve of this problem in flutter.How can i show this popup on screen.I tried almost everything anyone help pls.is there a way to do this in flutter
first use this code where you want to call the dialog box like in onTap function
showGeneralDialog(
context: context,
barrierDismissible: true,
barrierLabel: MaterialLocalizations.of(context).modalBarrierDismissLabel,
barrierColor: Colors.black.withOpacity(0.5),
pageBuilder: (context, animation1, animation2) =>BargainRespondDialog(),
transitionDuration: Duration(milliseconds: 500),
transitionBuilder: (context, a1, a2, widget) {
return Transform.scale(
scale: a1.value,
child: Opacity(
opacity: a1.value,
child: widget,
),
);
},
);
make a class and use this code
import 'package:flutter/material.dart';
class BargainRespondDialog extends StatefulWidget {
#override
State<BargainRespondDialog> createState() => _BargainRespondDialogState();
}
class _BargainRespondDialogState extends State<BargainRespondDialog> {
#override
Widget build(BuildContext context) {
return Dialog(
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(0)),
child: SingleChildScrollView(
child:Column(
children:[
SizedBox(height:10),
Icon(Icons.beenhere_sharp ),
SizedBox(height:10),
Text('We have received your bargain request', style: TextStyle(fontSize: 18,color: Colors.blue), textAlign: TextAlign.center,
),
Padding(
padding: EdgeInsets.only(top:15,left:5,right:5),
child: Text('Our team will review your request and get back to you within 24 to 48 hours.', textAlign: TextAlign.center),
),
SizedBox(height:10),
GestureDetector(
onTap: (){
Navigator.of(context).pop();
},
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
height: 30,
width: 50,
color: Colors.blue,
child: Center(
child: Text('OK', style: TextStyle(fontSize: 15,color: Colors.white), textAlign: TextAlign.center,
),
),
),
),
),
]), ),
);
}
}
if it helps you .please mark it as an accepted answer
void showCustomDialog(BuildContext context) {
showGeneralDialog(
context: context,
barrierLabel: "Barrier",
barrierDismissible: true,
barrierColor: Colors.black.withOpacity(0.6),
transitionDuration: Duration(milliseconds: 800),
pageBuilder: (_, __, ___) {
return Center(
child: Container(
height: 250,
child: SizedBox.expand(child: FlutterLogo()),
margin: EdgeInsets.symmetric(horizontal: 20),
decoration: BoxDecoration(color: Colors.white, borderRadius: BorderRadius.circular(30)),
),
);
},
transitionBuilder: (_, anim, __, child) {
Tween<Offset> tween;
if (anim.status == AnimationStatus.reverse) {
tween = Tween(begin: Offset(-1, 0), end: Offset.zero);
} else {
tween = Tween(begin: Offset(1, 0), end: Offset.zero);
}
return SlideTransition(
position: tween.animate(anim),
child: FadeTransition(
opacity: anim,
child: child,
),
);
},
);
}
import 'package:flutter_event_app/constant/color.dart';
import 'package:flutter_event_app/network/models/categories.dart';
import 'package:flutter_event_app/network/models/event_model.dart';
import 'package:flutter_event_app/network/models/time.dart';
import 'package:flutter_event_app/network/services/event_api.dart';
import 'package:flutter_event_app/pages/event_detail_page.dart';
import 'package:flutter_event_app/pages/search/home_search.dart';
import 'package:flutter_event_app/widgets/event_card.dart';
import 'package:flutter_event_app/widgets/no_events.dart';
import 'package:flutter_event_app/widgets/onload.dart';
class SelectedCategory extends StatefulWidget {
// SelectedCategory(Categories categories);
final Categories categories;
final Time time;
SelectedCategory(this.categories, [this.time]);
#override
_SelectedCategoryState createState() => _SelectedCategoryState();
}
class _SelectedCategoryState extends State<SelectedCategory> {
Categories categories;
Time timing;
String timeselect;
// Event event;
void viewEventDetail(Events event) {
Navigator.of(context).push(
PageRouteBuilder(
opaque: false,
barrierDismissible: true,
transitionDuration: Duration(milliseconds: 300),
pageBuilder: (BuildContext context, animation, __) {
return FadeTransition(
opacity: animation,
child: EventDetailPage(event),
);
},
),
);
}
bool isLoading = false;
List<Events> upcomingEvents;
List categorizedupcomingEvents = [];
List categorizedPaidupcomingEvents = [];
List categorizedFreeupcomingEvents = [];
#override
void initState() {
_fetchData();
categories = widget.categories;
timing = widget.time;
// print(timing.id);
super.initState();
}
Future _fetchData() async {
setState(() => isLoading = true);
upcomingEvents = await getEventss();
categorizedupcomingEvents = upcomingEvents
.where((category) => category.category == categories.id)
.toList();
categorizedPaidupcomingEvents = categorizedupcomingEvents
.where((paid) => paid.is_paid == true)
.toList();
categorizedFreeupcomingEvents = categorizedupcomingEvents
.where((free) => free.is_paid == false)
.toList();
setState(() => isLoading = false);
}
#override
Widget build(BuildContext context) {
return DefaultTabController(
length: 3,
child: Scaffold(
appBar: PreferredSize(
preferredSize: Size.fromHeight(
MediaQuery.of(context).size.height / 9.5,
),
child: AppBar(
title: Text(categories.categoryName),
centerTitle: true,
actions: <Widget>[
IconButton(
icon: Icon(
Icons.sort,
),
onPressed: () {
// Navigator.push(
// context,
// MaterialPageRoute(
// builder: (context) =>
showFilterByTimeDialog(context);
// )
// );
}),
IconButton(
icon: Icon(
Icons.more_vert,
),
onPressed: () {})
],
bottom: TabBar(
tabs: [
Text('All'),
Text('Paid'),
Text('Free'),
],
),
),
),
body: TabBarView(
children: <Widget>[
// All
isLoading
? OnloadingCards()
: Column(
children: <Widget>[
Expanded(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: categorizedupcomingEvents.isEmpty
? NoItems()
: ListView.builder(
itemCount: categorizedupcomingEvents.length,
shrinkWrap: true,
primary: false,
physics: BouncingScrollPhysics(),
// scrollDirection: Axis.horizontal,
itemBuilder: (context, index) {
final event =
categorizedupcomingEvents[index];
return EventCard(event,
onTap: () => viewEventDetail(event));
},
),
),
),
],
),
// Paid
isLoading
? OnloadingCards()
: Column(
children: <Widget>[
Expanded(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: categorizedPaidupcomingEvents.isEmpty
? NoItems()
: ListView.builder(
itemCount:
categorizedPaidupcomingEvents.length,
shrinkWrap: true,
primary: false,
physics: BouncingScrollPhysics(),
// scrollDirection: Axis.horizontal,
itemBuilder: (context, index) {
final event =
categorizedPaidupcomingEvents[index];
return EventCard(event,
onTap: () => viewEventDetail(event));
},
),
),
),
],
),
// Free
isLoading
? OnloadingCards()
: Column(
children: <Widget>[
Expanded(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: categorizedFreeupcomingEvents.isEmpty
? NoItems()
: ListView.builder(
itemCount:
categorizedFreeupcomingEvents.length,
shrinkWrap: true,
primary: false,
physics: BouncingScrollPhysics(),
// scrollDirection: Axis.horizontal,
itemBuilder: (context, index) {
final event =
categorizedFreeupcomingEvents[index];
return EventCard(event,
onTap: () => viewEventDetail(event));
},
),
),
),
],
),
],
),
));
}
void showFilterByTimeDialog(BuildContext context) {
Dialog fancyDialog = Dialog(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12.0),
),
child: SingleChildScrollView(
child: Container(
width: double.infinity,
height: MediaQuery.of(context).size.height * 0.5,
// alignment: Alignment.bottomCenter,
decoration: BoxDecoration(
// color: Colors.greenAccent,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(12),
topRight: Radius.circular(12),
bottomLeft: Radius.circular(12),
bottomRight: Radius.circular(12),
),
),
child: Column(
children: <Widget>[
Container(
height: MediaQuery.of(context).size.height * 0.05,
child: Text(
"Time",
style: TextStyle(
color: Colors.deepPurple,
fontSize: 20,
fontWeight: FontWeight.w600),
),
),
Expanded(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
// color: Colors.red,
width: double.infinity,
child: ListView.builder(
shrinkWrap: true,
primary: false,
physics: BouncingScrollPhysics(),
itemCount: times.length,
itemBuilder: (context, int index) {
Time time = times[index];
return RaisedButton(
onPressed: () {
debugPrint('I am Awesome');
},
textColor: Colors.red,
// color: Colors.blueAccent,
disabledColor: Colors.grey,
disabledTextColor: Colors.white,
highlightColor: Colors.orangeAccent,
child: Text(time.name),
);
}),
),
),
),
],
),
),
),
);
showDialog(
context: context, builder: (BuildContext context) => fancyDialog);
}
}
Within the same page I have a dialog box as shown below
On the method showFilterByTimeDialog where I select an item and have to go back to the same page below the dialogue .Am still learning flutter and my issue is I need help when I select an item from the dialogue box,i refresh the same page and display a new filtered lst from the current list displayed on that page with a condition of the item selected from the dialogue box.
I want to add a popup to the middle icon of BottomNavigationBar. I tried to do it as in the code I showed. How can I add popupmenubutton when I just click the Add icon?
Position code block
RelativeRect buttonMenuPosition(BuildContext c) {
final RenderBox bar = c.findRenderObject();
final RenderBox overlay = Overlay.of(c).context.findRenderObject();
final RelativeRect position = RelativeRect.fromRect(
Rect.fromPoints(
bar.localToGlobal(bar.size.bottomRight(Offset.zero), ancestor: overlay),
bar.localToGlobal(bar.size.bottomCenter(Offset.zero), ancestor: overlay),
),
Offset.zero & overlay.size,
);
return position;
}`
body
body: _widgetOptions.elementAt(_selectedBottomNavBarIndex),
bottomNavigationBar: BottomNavigationBar(
showSelectedLabels: false,
showUnselectedLabels: false,
iconSize: 24,
selectedFontSize: 0,
unselectedFontSize: 0,
type: BottomNavigationBarType.fixed,
key: key,
items: [
BottomNavigationBarItem(
...
),`
onTap Section
if (index == 2) {
final result = await showMenu(
context: context,
position: position,
items: <PopupMenuItem<String>>[
new PopupMenuItem<String>(
child: GestureDetector(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => RecordScreenOrj()),
);
},
photo
Try this function,
child: Padding(
padding: EdgeInsets.only(left: parentWidth * .03),
child: Column(
children: <Widget>[
Padding(
padding: EdgeInsets.only(top: parentHeight * .01),
child: new Container(
height: parentHeight * .045,
width: parentHeight * .045,
child: FloatingActionButton(
backgroundColor: Colors.pinkAccent,
onPressed: () {
showGeneralDialog(
barrierColor: Colors.black.withOpacity(0.5),
transitionBuilder: (context, a1, a2, widget) {
final curvedValue =
Curves.easeInOutBack.transform(a1.value) -
1.0;
return Transform(
transform: Matrix4.translationValues(
0.0, curvedValue * 200, 0.0),
child: Opacity(
opacity: a1.value,
child: new DialogForAsk(_controller, this),
),
);
},
transitionDuration: Duration(milliseconds: 200),
barrierDismissible: true,
barrierLabel: '',
context: context,
pageBuilder: (context, animation2, animation1) {});
},
child: Icon(
Icons.add,
size: parentHeight * .04,
color: Colors.white,
),
),
),
),
So I wanted to make the sticking of BottomNavigationBar on the keyboard stop.
I have tried:
resizeToAvoidBottomPadding: false; (or true both not working),
The problem with the bottomnavigationbar sticking to my keyboard is when I try to type something, the suggestions are not clearly visible and also it has a nested app bar on another page, which in-turn make it very difficulty to type and see the suggestions.
Here is my code:
#override
void initState() {
super.initState();
getUser();
//PostController().getUser(widget.auth.getCurrentUser());
pages = [Home(), Search(), NewPostPage(), Notifications(), Profile()];
}
#override
Widget build(BuildContext context) {
return new Scaffold(
resizeToAvoidBottomPadding: true,
body: Home(context),
);
}
Widget Home(context) {
var bottomOptions = <BottomNavigationBarItem>[];
for (var i = 0; i < widget.bottomItems.length; i++) {
var d = widget.bottomItems[i];
bottomOptions.add(
new BottomNavigationBarItem(
icon: d.icon,
title: Padding(
padding: const EdgeInsets.fromLTRB(3, 3, 3, 0),
child: new Text(d.title, style: TextStyle(fontSize: 12.0)),
),
),
);
}
return Scaffold(
appBar: AppBar(
title: Text(title),
leading: Container(
alignment: Alignment.centerLeft,
child: IconButton(
icon: Icon(Icons.motorcycle),
onPressed: () {
Navigator.push(
context,
PageRouteBuilder(
pageBuilder: (context, anim1, anim2) => Finder(),
transitionsBuilder: (context, anim1, anim2, child) =>
FadeTransition(opacity: anim1, child: child),
transitionDuration: Duration(seconds: 0),
));
}),
),
body: isLoading
? CollectionScaleTransition(
children: <Widget>[
Padding(
padding: const EdgeInsets.all(2.0),
child: Icon(Icons.add_circle, size: 10, color: Colors.blue),
),
Padding(
padding: const EdgeInsets.all(2.0),
child: Icon(Icons.add_circle, size: 10, color: Colors.blue),
),
Padding(
padding: const EdgeInsets.all(2.0),
child: Icon(Icons.add_circle, size: 10, color: Colors.blue),
),
],
)
: PageView(
controller: pageController,
children: pages,
onPageChanged: onPageChanged,
physics: NeverScrollableScrollPhysics(),
),
bottomNavigationBar: BottomNavigationBar(
showUnselectedLabels: true,
items: bottomOptions,
currentIndex: currentIndex,
selectedFontSize: 9,
unselectedFontSize: 9,
type: BottomNavigationBarType.fixed,
onTap: (index) {
setState(() {
onTap(index);
currentIndex = index;
});
},
),
);
}
}
How to make it stop appearing when I try to type on my text-field?
Thank you in Advance!
resizeToAvoidBottomPadding property is deprecated. We need to use resizeToAvoidBottomInset instead. More details here.
Also, I tried to recreate your case but was unable to replicate the issue you mentioned. I took some of your code and used it my sample, as below:
return Scaffold(
resizeToAvoidBottomInset: false,
appBar: AppBar(
title: Text('test'),
leading: Container(
alignment: Alignment.centerLeft,
child: IconButton(
icon: Icon(Icons.motorcycle),
onPressed: () {}),
)),
bottomNavigationBar: BottomNavigationBar(
currentIndex: 0, // this will be set when a new tab is tapped
items: [
BottomNavigationBarItem(
icon: new Icon(Icons.home),
title: new Text('Home'),
),
BottomNavigationBarItem(
icon: new Icon(Icons.mail),
title: new Text('Messages'),
),
BottomNavigationBarItem(
icon: Icon(Icons.person),
title: Text('Profile')
)
],
),
body: Center(
child: TextField(
keyboardType: TextInputType.text,
decoration: InputDecoration(
border: InputBorder.none,
hintText: 'Enter a search term'
),
))
);
With above code, when I tap on textfield, the bottom nav didn't show and I was able to type in properly.
Hope this helps.
I want to use DraggableScrollableSheet widget on my application, when I use that like with below code, that can show without problem:
class HomePage extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('DraggableScrollableSheet'),
),
body: SizedBox.expand(
child: DraggableScrollableSheet(
builder: (BuildContext context, ScrollController scrollController) {
return Container(
color: Colors.blue[100],
child: ListView.builder(
controller: scrollController,
itemCount: 25,
itemBuilder: (BuildContext context, int index) {
return ListTile(title: Text('Item $index'));
},
),
);
},
),
),
);
}
}
but when i want to show that by pressing for example floatingActionButton that don't show
floatingActionButton: GestureDetector(
child: FloatingActionButton(
child: Icon(
Icons.add,
size: 35.0,
),
elevation: 5,
backgroundColor: Colors.deepOrange,
foregroundColor: Colors.white,
onPressed: (){
SizedBox.expand(child: DraggableScrollableSheet(
builder: (BuildContext context, ScrollController scrollController) {
return Container(
color: Colors.blue[100],
child: ListView.builder(
controller: scrollController,
itemCount: 25,
itemBuilder: (BuildContext context, int index) {
return ListTile(title: Text('Item $index'));
},
),
);
},
));
},
),
),
If you want to use DraggableScrollableSheet inside showModalBottomSheet, you can simply call this function.
void _showSheet() {
showModalBottomSheet(
context: context,
isScrollControlled: true, // set this to true
builder: (_) {
return DraggableScrollableSheet(
expand: false,
builder: (_, controller) {
return Container(
color: Colors.blue[500],
child: ListView.builder(
controller: controller, // set this too
itemBuilder: (_, i) => ListTile(title: Text('Item $i')),
),
);
},
);
},
);
}
If you want to do it with Animation, here is the solution.
class HomePage extends StatefulWidget {
#override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> with SingleTickerProviderStateMixin {
AnimationController _controller;
Duration _duration = Duration(milliseconds: 500);
Tween<Offset> _tween = Tween(begin: Offset(0, 1), end: Offset(0, 0));
#override
void initState() {
super.initState();
_controller = AnimationController(vsync: this, duration: _duration);
}
#override
Widget build(BuildContext context) {
return Scaffold(
floatingActionButton: GestureDetector(
child: FloatingActionButton(
child: AnimatedIcon(icon: AnimatedIcons.menu_close, progress: _controller),
elevation: 5,
backgroundColor: Colors.deepOrange,
foregroundColor: Colors.white,
onPressed: () async {
if (_controller.isDismissed)
_controller.forward();
else if (_controller.isCompleted)
_controller.reverse();
},
),
),
body: SizedBox.expand(
child: Stack(
children: <Widget>[
FlutterLogo(size: 500),
SizedBox.expand(
child: SlideTransition(
position: _tween.animate(_controller),
child: DraggableScrollableSheet(
builder: (BuildContext context, ScrollController scrollController) {
return Container(
color: Colors.blue[800],
child: ListView.builder(
controller: scrollController,
itemCount: 25,
itemBuilder: (BuildContext context, int index) {
return ListTile(title: Text('Item $index'));
},
),
);
},
),
),
),
],
),
),
);
}
}
If you want to show DraggableScrollableSheet as modal you can use material showModalBottomSheet method to wrap it. Your sheet will be shown as modal, and you do not have to include it in the widget tree. Please note that under the hood it's pushed as new Route to Navigator, with all its consequences.
onPressed: (){
showModalBottomSheet(
context: context,
isScrollControlled: true,
expand: false,
backgroundColor: Colors.transparent,
builder: (context) =>
DraggableScrollableSheet(
initialChildSize: 0.64,
minChildSize: 0.2,
maxChildSize: 1,
builder: (context, scrollController) {
return Container(
color: Colors.white,
child: ListView.builder(
controller: scrollController,
itemBuilder: (context, index) {
return ListTile(
title: Text('Item $index'),
);
},
itemCount: 20,
),
);
},
),
);
}