Problem: Drawer Icon doesnt show in connection with sliver app bar - flutter

So I have following problem. I dont seem to be able to show the drawer
Icon in connection with my code. Although its a Scaffold property, it just isnt depicted. Below is working code where you can reproduce the problem. I just dont understand why it isnt working & couldnt fix it. I tried to add the drawer in all parts of my Scaffold at the top, middle bottom, but nothing seems to work. Any suggestions?
import 'package:flutter/material.dart';
import 'package:flutter/rendering.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: HomeScreen(),
);
}
}
class HomeScreen extends StatefulWidget {
#override
_HomeScreenState createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> {
DateTime? lastPressed;
final HideNavbar hiding = HideNavbar();
int _selectedIndex = 1;
List<Widget> _widgetOptions = <Widget>[
Text("Favorites()"),
Text("BodyHomeScreen()"),
Text("Kontakt()"),
];
void _onItemTap(int index) {
setState(() {
_selectedIndex = index;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Color(0xFFF6F6F6),
body: WillPopScope(
onWillPop: () async {
final now = DateTime.now();
final maxDuration = Duration(seconds: 2);
final isWarning =
lastPressed == null || now.difference(lastPressed!) > maxDuration;
if (isWarning) {
lastPressed = DateTime.now();
final snackBar = SnackBar(
content: Container(
//color: Colors.white,
decoration: BoxDecoration(
color: Color(0xFF03DAC6),
borderRadius: BorderRadius.circular(20)),
margin: EdgeInsets.fromLTRB(0, 0, 0, 20),
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
'Doppelklick zum verlassen',
textAlign: TextAlign.center,
),
),
),
backgroundColor: Colors.transparent,
elevation: 1000,
behavior: SnackBarBehavior.floating,
duration: maxDuration,
);
ScaffoldMessenger.of(context)
..removeCurrentSnackBar()
..showSnackBar(snackBar);
return false;
} else {
return true;
}
},
child: CustomScrollView(
controller: hiding.controller,
slivers: [
SliverAppBar(
backgroundColor: Color(0xFF3FC1C9),
automaticallyImplyLeading: false,
elevation: 0,
title: Text(
"AutoTest",
style: TextStyle(color: Colors.white),
),
centerTitle: true,
expandedHeight: 120,
flexibleSpace: FlexibleSpaceBar(
title: _selectedIndex == 1
? Text("Marke auswählen")
: _selectedIndex == 2
? Text("Schreibe uns!")
: Text("Deine Modelle"),
centerTitle: true,
),
),
SliverToBoxAdapter(child: _widgetOptions.elementAt(_selectedIndex)),
],
),
),
bottomNavigationBar: ValueListenableBuilder(
valueListenable: hiding.visible,
builder: (context, bool value, child) => AnimatedContainer(
duration: Duration(milliseconds: 500),
height: value ? kBottomNavigationBarHeight : 0.0,
child: Wrap(
children: <Widget>[
Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.only(
topRight: Radius.circular(30),
topLeft: Radius.circular(30)),
boxShadow: [
BoxShadow(
color: Colors.black38, spreadRadius: 0, blurRadius: 10),
],
),
child: ClipRRect(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(30.0),
topRight: Radius.circular(30.0),
),
child: BottomNavigationBar(
type: BottomNavigationBarType.fixed,
iconSize: 30,
backgroundColor: Colors.white,
selectedItemColor: Color(0xFF3FC1C9),
unselectedItemColor: Color(0xff6B705C),
selectedFontSize: 15,
unselectedFontSize: 0,
items: const <BottomNavigationBarItem>[
BottomNavigationBarItem(
icon: Icon(Icons.favorite),
label: "Favorites",
),
BottomNavigationBarItem(
icon: Icon(Icons.home_rounded),
label: "Home",
),
BottomNavigationBarItem(
icon: Icon(Icons.contact_page_outlined),
label: "Contact",
),
],
currentIndex: _selectedIndex,
onTap: _onItemTap,
),
),
),
],
),
),
),
drawer: Drawer(
),
);
}
}
class HideNavbar {
final ScrollController controller = ScrollController();
final ValueNotifier<bool> visible = ValueNotifier<bool>(true);
HideNavbar() {
visible.value = true;
controller.addListener(
() {
if (controller.position.userScrollDirection ==
ScrollDirection.reverse) {
if (visible.value) {
visible.value = false;
}
}
if (controller.position.userScrollDirection ==
ScrollDirection.forward) {
if (!visible.value) {
visible.value = true;
}
}
},
);
}
void dispose() {
controller.dispose();
visible.dispose();
}
}

I added a icon at SliverAppBar so that you can open it from there, also it will open from left side of screen just by swapping . let me know is something else you needed to be modified.
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
class HomeScreen extends StatefulWidget {
#override
_HomeScreenState createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> {
DateTime? lastPressed;
final HideNavbar hiding = HideNavbar();
int _selectedIndex = 1;
List<Widget> _widgetOptions = <Widget>[
Text("Favorites()"),
Text("BodyHomeScreen()"),
Text("Kontakt()"),
];
void _onItemTap(int index) {
setState(() {
_selectedIndex = index;
});
}
final GlobalKey<ScaffoldState> _key = GlobalKey(); // Create a key
#override
Widget build(BuildContext context) {
return Scaffold(
key: _key,
backgroundColor: Color(0xFFF6F6F6),
drawer: Drawer(
child: Text("Drawer here"),
),
body: WillPopScope(
onWillPop: () async {
final now = DateTime.now();
final maxDuration = Duration(seconds: 2);
final isWarning =
lastPressed == null || now.difference(lastPressed!) > maxDuration;
if (isWarning) {
lastPressed = DateTime.now();
final snackBar = SnackBar(
content: Container(
//color: Colors.white,
decoration: BoxDecoration(
color: Color(0xFF03DAC6),
borderRadius: BorderRadius.circular(20)),
margin: EdgeInsets.fromLTRB(0, 0, 0, 20),
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
'Doppelklick zum verlassen',
textAlign: TextAlign.center,
),
),
),
backgroundColor: Colors.transparent,
elevation: 1000,
behavior: SnackBarBehavior.floating,
duration: maxDuration,
);
ScaffoldMessenger.of(context)
..removeCurrentSnackBar()
..showSnackBar(snackBar);
return false;
} else {
return true;
}
},
child: CustomScrollView(
controller: hiding.controller,
slivers: [
SliverAppBar(
backgroundColor: Color(0xFF3FC1C9),
automaticallyImplyLeading: false,
elevation: 0,
title: Text(
"AutoTest",
style: TextStyle(color: Colors.white),
),
leading: IconButton(
onPressed: () {
_key.currentState!.openDrawer();
// _key.currentState!.openEndDrawer();
},
icon: Icon(
Icons.home,
),
),
centerTitle: true,
expandedHeight: 120,
flexibleSpace: FlexibleSpaceBar(
title: _selectedIndex == 1
? Text("Marke auswählen")
: _selectedIndex == 2
? Text("Schreibe uns!")
: Text("Deine Modelle"),
centerTitle: true,
),
),
SliverToBoxAdapter(child: _widgetOptions.elementAt(_selectedIndex)),
],
),
),
bottomNavigationBar: ValueListenableBuilder(
valueListenable: hiding.visible,
builder: (context, bool value, child) => AnimatedContainer(
duration: Duration(milliseconds: 500),
height: value ? kBottomNavigationBarHeight : 0.0,
child: Wrap(
children: <Widget>[
Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.only(
topRight: Radius.circular(30),
topLeft: Radius.circular(30)),
boxShadow: [
BoxShadow(
color: Colors.black38, spreadRadius: 0, blurRadius: 10),
],
),
child: ClipRRect(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(30.0),
topRight: Radius.circular(30.0),
),
child: BottomNavigationBar(
type: BottomNavigationBarType.fixed,
iconSize: 30,
backgroundColor: Colors.white,
selectedItemColor: Color(0xFF3FC1C9),
unselectedItemColor: Color(0xff6B705C),
selectedFontSize: 15,
unselectedFontSize: 0,
items: const <BottomNavigationBarItem>[
BottomNavigationBarItem(
icon: Icon(Icons.favorite),
label: "Favorites",
),
BottomNavigationBarItem(
icon: Icon(Icons.home_rounded),
label: "Home",
),
BottomNavigationBarItem(
icon: Icon(Icons.contact_page_outlined),
label: "Contact",
),
],
currentIndex: _selectedIndex,
onTap: _onItemTap,
),
),
),
],
),
),
),
);
}
}
class HideNavbar {
final ScrollController controller = ScrollController();
final ValueNotifier<bool> visible = ValueNotifier<bool>(true);
HideNavbar() {
visible.value = true;
controller.addListener(
() {
if (controller.position.userScrollDirection ==
ScrollDirection.reverse) {
if (visible.value) {
visible.value = false;
}
}
if (controller.position.userScrollDirection ==
ScrollDirection.forward) {
if (!visible.value) {
visible.value = true;
}
}
},
);
}
void dispose() {
controller.dispose();
visible.dispose();
}
}

Related

My bottom navigation bar is not changing it's index while using will pop scope on it's children

I want that whenever I press back button of Android while on a page of nav bar, it should change it's index to 0, i.e. I should land on the first page of it. But it is not happening. My code -
import 'dart:math';
import '../colors.dart';
import '../providers.dart';
import 'home_tab/home_tab_screen.dart';
import 'manage_leads/mange_leads_screen.dart';
import 'profile/profile_screen.dart';
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:provider/provider.dart';
import '../main.dart';
import '../size_config.dart';
class HomeScreen extends StatefulWidget {
const HomeScreen({Key? key}) : super(key: key);
#override
State<HomeScreen> createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> {
List<Widget> screens = [
HomeTabScreen(),
WillPopScope(
onWillPop: () async {
Provider.of<MyAppData>(navigatorKey.currentContext!, listen: false)
.initializePage(0);
return false;
},
child: ManageLeadsScreen(),
),
Container(),
WillPopScope(
onWillPop: () async {
Provider.of<MyAppData>(navigatorKey.currentContext!, listen: false)
.initializePage(0);
print(Provider.of<MyAppData>(navigatorKey.currentContext!, listen: false).pageIndex);
return false;
},
child: ProfileScreen(),
),
];
void _onItemTapped(int index) {
setState(() {
Provider.of<MyAppData>(navigatorKey.currentContext!, listen: false).initializePage(index);
});
}
#override
Widget build(BuildContext context) {
SizeConfig().init(context);
return Scaffold(
backgroundColor: Colors.white,
extendBody: true,
body: screens[Provider.of<MyAppData>(navigatorKey.currentContext!, listen: true).pageIndex],
bottomNavigationBar: Container(
decoration: BoxDecoration(
boxShadow: [
BoxShadow(
color: Colors.grey.withOpacity(0.3),
spreadRadius: 1,
blurRadius: 20,
offset: Offset.fromDirection(-pi / 2, 10))
],
borderRadius: BorderRadius.only(
topLeft: Radius.circular(24),
topRight: Radius.circular(24),
),
),
child: ClipRRect(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(24),
topRight: Radius.circular(24),
),
child: BottomNavigationBar(
backgroundColor: Colors.white,
iconSize: getProportionateScreenWidth(32),
selectedFontSize: getProportionateScreenWidth(12),
selectedItemColor: primaryOrange,
unselectedIconTheme: IconThemeData(
size: getProportionateScreenWidth(24),
),
type: BottomNavigationBarType.fixed,
showUnselectedLabels: false,
items: <BottomNavigationBarItem>[
BottomNavigationBarItem(
icon: Icon(
Icons.home,
color: unselectedItemColor,
),
label: 'Home',
activeIcon: Icon(
Icons.home,
color: primaryOrange,
),
),
BottomNavigationBarItem(
icon: SvgPicture.asset(
"assets/icons/manage_leads_icon.svg",
color: unselectedItemColor,
),
label: 'Manage Leads',
activeIcon: SvgPicture.asset(
"assets/icons/manage_leads_icon.svg",
color: primaryOrange,
),
),
BottomNavigationBarItem(
icon: SvgPicture.asset(
"assets/icons/icon_3.svg",
color: unselectedItemColor,
),
label: 'Next',
activeIcon: SvgPicture.asset(
"assets/icons/icon_3.svg",
color: Colors.orange,
),
),
BottomNavigationBarItem(
icon: SvgPicture.asset(
"assets/icons/profile_icon.svg",
color: unselectedItemColor,
),
label: 'Home',
activeIcon: SvgPicture.asset(
"assets/icons/profile_icon.svg",
color: Colors.orange,
),
),
],
currentIndex: Provider.of<MyAppData>(navigatorKey.currentContext!, listen: true).pageIndex,
onTap: _onItemTapped,
),
),
),
);
}
}
Here is my initializePage function -
import 'package:flutter/cupertino.dart';
class MyAppData extends ChangeNotifier {
int pageIndex=0;
void initializePage(int num) {
pageIndex = num;
notifyListeners();
}
}
When I am changing it's value using onTap: _onItemTapped,, it is working fine, but when I am trying to change it using WillPopScope, it's not working. Using print statements, I can see that value of pageIndex is changing to 0, but my nav bar is not reponsive. Only after I hot reload, it goes back to the first screen.
I think this example may help you.
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
// This is the theme of your application.
//
// Try running your application with "flutter run". You'll see the
// application has a blue toolbar. Then, without quitting the app, try
// changing the primarySwatch below to Colors.green and then invoke
// "hot reload" (press "r" in the console where you ran "flutter run",
// or simply save your changes to "hot reload" in a Flutter IDE).
// Notice that the counter didn't reset back to zero; the application
// is not restarted.
primarySwatch: Colors.blue,
),
home: ChangeNotifierProvider(
create: (_) => MyAppData(), child: HomeScreen()),
);
}
}
class HomeScreen extends StatefulWidget {
const HomeScreen({Key? key}) : super(key: key);
#override
State<HomeScreen> createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> {
List<Widget> screens(BuildContext context) => [
WillPopScope(
onWillPop: () async {
_onItemTapped(0);
return false;
},
child: Container(
color: Colors.primaries[0],
child: Center(
child: Text("Page 0"),
),
),
),
WillPopScope(
onWillPop: () async {
_onItemTapped(0);
return false;
},
child: Container(
color: Colors.primaries[1],
child: Center(
child: Text("Page 1"),
),
),
),
WillPopScope(
onWillPop: () async {
_onItemTapped(0);
return false;
},
child: Container(
color: Colors.primaries[2],
child: Center(
child: Text("Page 2"),
),
),
),
WillPopScope(
onWillPop: () async {
_onItemTapped(0);
return false;
},
child: Container(
color: Colors.primaries[3],
child: Center(
child: Text("Page 3"),
),
),
),
];
void _onItemTapped(int index) {
context.read<MyAppData>().initializePage(index);
}
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
extendBody: true,
body: screens(context)[context.watch<MyAppData>().pageIndex],
bottomNavigationBar: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(24),
topRight: Radius.circular(24),
),
),
child: ClipRRect(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(24),
topRight: Radius.circular(24),
),
child: BottomNavigationBar(
backgroundColor: Colors.white,
iconSize: 30,
selectedFontSize: 20,
selectedItemColor: Colors.red,
unselectedIconTheme: IconThemeData(
size: 20,
),
type: BottomNavigationBarType.fixed,
showUnselectedLabels: false,
items: <BottomNavigationBarItem>[
BottomNavigationBarItem(
icon: Icon(
Icons.home,
),
label: 'page0',
activeIcon: Icon(
Icons.home,
),
),
BottomNavigationBarItem(
icon: Icon(
Icons.home,
),
label: 'page1',
activeIcon: Icon(
Icons.home,
),
),
BottomNavigationBarItem(
icon: Icon(
Icons.home,
),
label: 'page2',
activeIcon: Icon(
Icons.home,
),
),
BottomNavigationBarItem(
icon: Icon(
Icons.home,
),
label: 'page3',
activeIcon: Icon(
Icons.home,
),
),
],
currentIndex: context.watch<MyAppData>().pageIndex,
onTap: _onItemTapped,
),
),
),
);
}
}
class MyAppData extends ChangeNotifier {
int pageIndex = 0;
void initializePage(int num) {
pageIndex = num;
notifyListeners();
}
}

how to border radius to navigation bar flutter

I want circular borders on the top left and right in my navigation bar. below I have mentioned my bottom navigation bar code. how can I DO THAT? Appreciate your help on this. ............... ......................................... ..........................
import 'package:deltamax_health/Screens/welcome_screen.dart';
import 'package:flutter/material.dart';
import '../Constant/colors.dart';
import 'dashboard.dart';
class BottomNavigation extends StatefulWidget {
const BottomNavigation({ Key? key }) : super(key: key);
#override
State<BottomNavigation> createState() => _BottomNavigationState();
}
class _BottomNavigationState extends State<BottomNavigation> {
int _selectedindex = 0;
void _navigatePages(int index) {
setState(() {
_selectedindex = index;
});
}
final List<Widget> _Pages = [const Dashboard() ,const WelcomeScreen()];
#override
Widget build(BuildContext context) {
return Scaffold(
body: _Pages[_selectedindex],
bottomNavigationBar: BottomNavigationBar(
backgroundColor: Color.fromRGBO(115, 131, 163, 0.7490196078431373),
fixedColor: backgroundBlue,
currentIndex: _selectedindex,
onTap: _navigatePages,
type: BottomNavigationBarType.fixed,
items: const [
BottomNavigationBarItem(icon:Icon(
Icons.account_balance_wallet_outlined,
color: textblue,
size: 30,
), label: ""),
BottomNavigationBarItem(icon: Icon(
Icons.open_in_browser_outlined,
color: textblue,
size: 30,
), label: ""),
BottomNavigationBarItem(icon: Icon(
Icons.money_outlined,
color: textblue,
size: 30,
), label: "")
]),
);
}
}
Wrapping with Container and providing borderRadius seens solve the issue, but there will splash effect on corners. In this can use clipBehavior on Container.
bottomNavigationBar: Container(
clipBehavior: Clip.hardEdge, //or better look(and cost) using Clip.antiAlias,
decoration: BoxDecoration(
borderRadius: BorderRadius.only(
topRight: Radius.circular(24),
topLeft: Radius.circular(24),
),
),
child: BottomNavigationBar(
Or just use ClipRRect
body: _Pages[_selectedindex],
bottomNavigationBar: ClipRRect(
borderRadius: const BorderRadius.only(
topRight: Radius.circular(24),
topLeft: Radius.circular(24),
),
child: BottomNavigationBar(
Update 1
Use extendBody: true to extends the body to the bottom of the Scaffold. Or You can provide backgroundColor for simple case.
return Scaffold(
// backgroundColor: Colors.blue, //same as body color
extendBody: true,
body: _Pages[_selectedindex],
bottomNavigationBar:
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatefulWidget {
const MyApp({Key? key}) : super(key: key);
#override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> with TickerProviderStateMixin {
late TabController _tabController;
#override
void initState() {
super.initState();
_tabController = TabController(length: 4, vsync: this);
}
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
bottomNavigationBar: DefaultTabController(
length: 4,
initialIndex: 0,
child: Container(
margin: const EdgeInsets.only(bottom: .5),
padding: const EdgeInsets.only(top: 3),
height: 50,
decoration: BoxDecoration(
// color: Theme.of(context).backgroundColor,
color: Colors.white,
border: Border.all(
color: Colors.grey[700]!,
width: 0.5,
),
borderRadius: const BorderRadius.only(
topRight: Radius.circular(17),
topLeft: Radius.circular(17),
),
),
child: TabBar(
physics: const NeverScrollableScrollPhysics(),
isScrollable: false,
controller: _tabController,
indicatorWeight: 0,
// mouseCursor: MouseCursor.defer,
indicator: const UnderlineTabIndicator(
borderSide: BorderSide(
color: Colors.black,
width: 1,
),
// insets: EdgeInsets.symmetric(horizontal: 0),
),
tabs: [
kTabBarItemConstructor(
Icons.home,
'Home',
),
Container(
child: kTabBarItemConstructor(
Icons.home,
'Home',
),
),
Container(
child: kTabBarItemConstructor(
Icons.home,
'Profile',
),
),
// Tab(
// child: Container(
// child: Column(
// mainAxisAlignment: MainAxisAlignment.center,
// children: [
//
// Text(
// 'Корзина',
// style: TextStyle(
// fontSize: 9,
// color: Colors.grey[600],
// ),
// ),
// ],
// ),
// ),
// ),
kTabBarItemConstructor(
Icons.home,
'Profile',
),
],
),
),
),
));
}
}
Widget kTabBarItemConstructor(IconData icon, String text) {
return Tab(
child: Container(
height: 40,
width: 70,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(
icon,
color: Colors.black.withOpacity(.65),
size: 25,
),
Container(
// margin: EdgeInsets.symmetric(horizontal: 10),
child: Text(
text,
style: TextStyle(
fontSize: 9,
color: Colors.grey[600],
),
maxLines: 1,
overflow: TextOverflow.ellipsis,
),
),
],
),
),
);
}
Run on DartPad.

bottomNavigationBar OnTap does not trigger for navigate to another page

#override
void initState() {
super.initState();
}
int selectedPage = 0;
void changePage(int index) {
setState(() {
selectedPage = index;
});
}
bottomNavigationBar: BottomNavigationBar(
showUnselectedLabels: true,
currentIndex: selectedPage,
onTap: showPage,
items: const [
BottomNavigationBarItem(
icon: Icon(Icons.home),
label: 'Main',
backgroundColor: Colors.blue),
BottomNavigationBarItem(
icon: Icon(Icons.category_outlined),
label: 'Category',
backgroundColor: Colors.blue),
BottomNavigationBarItem(
icon: Icon(Icons.book_online),
label: 'Photos',
backgroundColor: Colors.blue),
BottomNavigationBarItem(
icon: Icon(Icons.video_call),
label: 'Video',
backgroundColor: Colors.blue),
],
Widget showPage(int selectedPage) {
if (selectedPage == 0) {
return NewsViewDetail(id: '0');
} else if (selectedPage == 1) {
return NewsLoading(text: 'load');
}
return NewsLoading(text: '1');
}
When I tap first or second item on the there is no reaction from UI. It seems onTap does not navigate to different pages.
Could you please help me why this code is not working?
Edit: I think the problem causing Scaffold body. Current Scaffold body is:
body: TabBarView(
children: [
for (final tab in filteredList)
NewsView(
id: tab.id!,
),
],
),
How can I integrate showPage(_selectedIndex), into Scaffold Body without hurt the TabbarView?
here is the TabBarController
return DefaultTabController(
// length: snapshot.data!.data!.length,
length: filteredList.length,
child: Scaffold(
appBar: AppBar(
backgroundColor: (Colors.white),
iconTheme: const IconThemeData(color: Colors.black),
title: Transform.translate(
offset: const Offset(-24.0, 0.0),
child: Image.asset("assets/images/lo.png",
fit: BoxFit.contain, height: 22),
),
bottom: PreferredSize(
preferredSize: const Size.fromHeight(30.00),
child: ColoredBox(
color: Colors.white,
child: TabBar(
labelColor: Colors.purple[100],
indicatorColor: Colors.purple,
isScrollable: true,
labelPadding:
const EdgeInsets.symmetric(horizontal: 8.0),
tabs: tabs),
),
),
),
```
Check it, it will be helped you to solve your solution
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: MyNavigationBar(),
);
}
}
class MyNavigationBar extends StatefulWidget {
MyNavigationBar({Key key}) : super(key: key);
#override
_MyNavigationBarState createState() => _MyNavigationBarState();
}
class _MyNavigationBarState extends State<MyNavigationBar>
with TickerProviderStateMixin {
int _selectedIndex = 0;
void changePage(int index) {
setState(() {
_selectedIndex = index;
});
}
Widget showPage(int selectedPage) {
if (selectedPage == 0) {
return Container(
child: Text('Main Page',
style: TextStyle(fontSize: 35, fontWeight: FontWeight.bold)),
);
} else if (selectedPage == 1) {
return Container(
child: Text('Category page',
style: TextStyle(fontSize: 35, fontWeight: FontWeight.bold)),
);
} else if (selectedPage == 2) {
return Container(
child: Text('Photo page',
style: TextStyle(fontSize: 35, fontWeight: FontWeight.bold)),
);
}
return Container(
child: Text('video Page',
style: TextStyle(fontSize: 35, fontWeight: FontWeight.bold)),
);
}
TabController tabController;
#override
void initState() {
// TODO: implement initState
super.initState();
tabController = TabController(initialIndex: 0, length: 2, vsync: this);
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Container(
decoration: BoxDecoration(
color: Colors.white.withOpacity(0.0),
//This is for bottom border that is needed
border:
Border(bottom: BorderSide(color: Colors.grey, width: 0.8))),
child: TabBar(
indicatorWeight: 2,
controller: tabController,
indicatorColor: Colors.purple,
labelColor: Colors.purple,
unselectedLabelColor: Color(0xff002540).withOpacity(0.7),
tabs: [
Tab(
child: Text(
"First",
),
),
Tab(
child: Text(
"Second",
),
),
],
),
),
backgroundColor: Colors.green,
),
body: SingleChildScrollView(
child: Column(
children: [
Container(
height: MediaQuery.of(context).size.height,
child: TabBarView(controller: tabController, children: [
Container(
child: Center(
child: showPage(_selectedIndex),
),
),
Container(
child: Center(
child: showPage(_selectedIndex),
),
),
]),
),
],
)),
bottomNavigationBar: BottomNavigationBar(
items: const <BottomNavigationBarItem>[
BottomNavigationBarItem(
icon: Icon(Icons.home),
label: 'Main',
backgroundColor: Colors.blue),
BottomNavigationBarItem(
icon: Icon(Icons.category_outlined),
label: 'Category',
backgroundColor: Colors.blue),
BottomNavigationBarItem(
icon: Icon(Icons.book_online),
label: 'Photos',
backgroundColor: Colors.blue),
BottomNavigationBarItem(
icon: Icon(Icons.video_call),
label: 'Video',
backgroundColor: Colors.blue),
],
type: BottomNavigationBarType.shifting,
currentIndex: _selectedIndex,
selectedItemColor: Colors.black,
iconSize: 40,
onTap: changePage,
elevation: 5),
);
}
}
Output:

how to repeat the same future function each time another function is called?

i am trying to display a typing indicator before showing a message, i have tried the code below but it only displays the typing indicator once (only for the first message), what i want is to display it each time i want to print a message.
this is after modification, the code still after the first message does not display the typing indicator again
import 'package:bubble/bubble.dart';
import 'package:flutter/material.dart';
import 'package:flutter_chat_bubble/bubble_type.dart';
import 'package:flutter_chat_bubble/chat_bubble.dart';
import 'package:flutter_chat_bubble/clippers/chat_bubble_clipper_2.dart';
import 'package:flutter_dialogflow/dialogflow_v2.dart';
import 'package:progress_indicators/progress_indicators.dart';
void main() {
runApp(Bot());
}
class Bot extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'bot',
theme: ThemeData(
primarySwatch: Colors.grey,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
debugShowCheckedModeBanner: false,
home: HomePage(title: 'bot'),
);
}
}
class HomePage extends StatefulWidget {
HomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
bool _nextWidget = false;
#override
void initState() {
super.initState();
}
void myMethod(){
Future.delayed(
const Duration(
seconds: 5,
milliseconds: 500,
),
() {
if (this.mounted) {
setState(() {
_nextWidget = true;
});
}
});
}
void response(query) async {
AuthGoogle authGoogle = await AuthGoogle(
fileJson: "assets/credentials.json").build();
Dialogflow dialogflow =
Dialogflow(authGoogle: authGoogle, language: Language.english);
AIResponse aiResponse = await dialogflow.detectIntent(query);
setState(() {
messsages.insert(0, {
"data": 0,
"message": aiResponse.getListMessage()[0]["text"]["text"][0].toString()
});
});
print(aiResponse.getListMessage()[0]["text"]["text"][0].toString());
}
final messageInsert = TextEditingController();
List<Map> messsages = List();
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.grey[850],
appBar: AppBar(
leading: IconButton(icon: Icon(Icons.menu, color: Colors.white, size: 45)),
backgroundColor: Colors.grey[800],
),
body: Container(
child: Column(
children: [
Flexible(
child: ListView.builder(
reverse: true,
itemCount: messsages.length,
itemBuilder: (context, index) => chat(
messsages[index]["message"].toString(),
messsages[index]["data"])
),
),
Container(
color: Colors.grey[850],
child: ListTile(
leading: IconButton(
icon: Icon(Icons.mic_off, color: Colors.white, size: 35),
),
title: Container(
height: 45,
decoration: BoxDecoration(
shape: BoxShape.rectangle,
borderRadius: BorderRadius.all(Radius.circular(10)),
color: Colors.white,
),
padding: EdgeInsets.only(left: 10),
child: TextFormField(
cursorColor: Colors.grey[850],
controller: messageInsert,
decoration: InputDecoration(
hintText: "Chat with me",
hintStyle: TextStyle(
color: Colors.black
),
),
style: TextStyle(
fontSize: 16,
color: Colors.black
),
onChanged: (value) {}
)
),
trailing:
IconButton(
icon: Icon(
Icons.send,
size: 30.0,
color: Colors.greenAccent,
),
onPressed: () {
if (messageInsert.text.isEmpty) {
print("empty message");
} else {
setState(() {
messsages.insert(0,
{"data": 1, "message": messageInsert.text});
});
response(messageInsert.text);
messageInsert.clear();
}
FocusScopeNode currentFocus = FocusScope.of(context);
if (!currentFocus.hasPrimaryFocus) {
currentFocus.unfocus();
}
})
)
),
SizedBox(height: 10.0)
]
),
)
);
}
Widget bot(String message) {
myMethod();
return _nextWidget ? botMessage(message) : botInd();
}
Widget botInd() {
return Container(
alignment: Alignment.bottomLeft,
margin: EdgeInsets.only(top: 20),
child: Container(
constraints: BoxConstraints(maxWidth: 75, maxHeight: 100),
child: JumpingDotsProgressIndicator(fontSize: 50.0, color: Colors.white)
)
);
}
Widget botMessage(String message) {
return ChatBubble(
clipper: ChatBubbleClipper2(type: BubbleType.receiverBubble),
alignment: Alignment.bottomLeft,
margin: EdgeInsets.only(top: 20),
backGroundColor: Colors.white,
child: Container(
constraints: BoxConstraints(maxWidth: MediaQuery.of(context).size.width * 0.7),
child: Text(
message,
style: TextStyle(color: Colors.black, fontWeight: FontWeight.bold)
)
)
);
}
Widget user(String message) {
return ChatBubble(
clipper: ChatBubbleClipper2(type: BubbleType.sendBubble),
alignment: Alignment.bottomRight,
margin: EdgeInsets.only(top: 20),
backGroundColor: Colors.white,
child: Container(
constraints: BoxConstraints(maxWidth: MediaQuery.of(context).size.width * 0.7),
child: Text(
message,
style: TextStyle(color: Colors.black, fontWeight: FontWeight.bold)
)
)
);
}
Widget chat(String message, int data) {
return data == 0 ? bot(message) : user(message);
}
}
The initState method runs 1 time just before your code appears on the screen. Therefore, I suggest you use the block of code you wrote in the initState method and want to run, by creating a new method other than initState like:
void myMethod(){
Future.delayed(
const Duration(
seconds: 7,
milliseconds: 500,
),
() {
if (this.mounted) {
setState(() {
_nextWidget = !_nextWidget;
});
}
});}
After doing that, try calling "myMethod".
Hope this works for you.

Bottom sheet is not displaying on the bottom

I want to show a bottom sheet when clicking on the floating button on the page. Page also includes bottom navigation bar. When clicking on the floating button, the bottom sheet appears above the navigation bar not on the bottom of the page. How can I achieve this?.
Code:
void main() {
runApp(App());
}
class App extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'app',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: AppNavigation(),
);
}
}
class AppNavigation extends StatefulWidget {
#override
_AppNavigationState createState() => _AppNavigationState();
}
class _AppNavigationState extends State<AppNavigation> {
int _currentIndex = 0;
final List<Widget> _children = [
HomeScreen(),
SettingsScreen(),
];
void onTappedBar(int index) {
setState(() {
_currentIndex = index;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: _children[_currentIndex],
bottomNavigationBar: BottomNavigationBar(
onTap: onTappedBar,
currentIndex: _currentIndex,
items: <BottomNavigationBarItem>[
BottomNavigationBarItem(
icon: Icon(Icons.home), title: Text('Home')),
BottomNavigationBarItem(
icon: Icon(Icons.settings), title: Text('Settings')),
]),
);
}
}
class HomeScreen extends StatelessWidget {
#override
Widget build(BuildContext context) {
var size = MediaQuery.of(context).size; // gives device width and height
return Scaffold(
floatingActionButton: FloatingActionButton(
onPressed: () {
showBottomSheet(
context: context,
builder: (context) => Container(
height: 320,
decoration: BoxDecoration(
boxShadow: [
BoxShadow(
color: Colors.grey.withOpacity(0.5),
spreadRadius: 5,
blurRadius: 20,
offset: Offset(0, 3),
),
],
color: Colors.white,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(25),
topRight: Radius.circular(25),
),
),
padding:
EdgeInsets.symmetric(horizontal: 20, vertical: 30),
child: Center(child: Text('Bottom action sheet')),
));
},
child: Icon(Icons.add),
backgroundColor: Colors.deepPurple),
body: Center(child: Text("home page")));
}
}
Below is the output of above code.The bottom action sheet appears above the bottom navigation bar. I expect the bottom action should be on bottom of the screen.
I believe what you are trying to achieve is done by using "showModalBottomSheet" like this:
return Scaffold(
resizeToAvoidBottomInset: false,
floatingActionButton: FloatingActionButton(
onPressed: () {
// what you asked for
showModalBottomSheet(
barrierColor: Colors.white.withOpacity(0),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.vertical(
top: Radius.circular(25),
),
),
context: context,
builder: (context) => Container(
height: 320,
decoration: BoxDecoration(
boxShadow: [
BoxShadow(
color: Colors.grey.withOpacity(0.5),
spreadRadius: 5,
blurRadius: 20,
offset: Offset(0, 3),
),
],
color: Colors.white,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(25),
topRight: Radius.circular(25),
),
),
padding:
EdgeInsets.symmetric(horizontal: 20, vertical: 30),
child: Center(child: Text('Bottom action sheet')),
));
},
child: Icon(Icons.add),
backgroundColor: Colors.deepPurple),
body: Center(child: Text("home page")));
edit: I have modified the code so that it has the same shadow effect like the one in the picture you've posted