I am trying to make the floating action button as the open and close button for the modal bottom sheet which requires the floating action button to be on top of the modal bottom sheet. Is there any possibility to achieve this with modal bottom sheet??
Here's my app:
What I am trying to achieve:
Prototype
import 'package:flutter/material.dart';
import '../screens/account_screen.dart';
import '../screens/activity_screen.dart';
import '../screens/planning_screen.dart';
import '../widgets/custom_bottom_app_bar.dart';
import '../widgets/custom_floating_action_button.dart';
class HomeScreen extends StatefulWidget {
const HomeScreen({super.key});
#override
State<HomeScreen> createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> {
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Text(
'Home Screen',
style: TextStyle(
fontWeight: FontWeight.w900,
fontStyle: FontStyle.italic,
),
),
),
floatingActionButton: CustomFloatingActionButton(),
floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,
bottomNavigationBar: CustomBottomAppBar(),
);
}
}
import 'package:flutter/material.dart';
import '../constants/constants.dart';
import '../screens/add_menu_screen.dart';
// [#] CustomFloatingActionButton
class CustomFloatingActionButton extends StatelessWidget {
const CustomFloatingActionButton({
super.key,
});
#override
Widget build(BuildContext context) {
return Theme(
data: Theme.of(context).copyWith(
useMaterial3: true,
highlightColor: Colors.black,
),
child: Transform.rotate(
angle: 22 / 28,
child: SizedBox(
width: 60,
height: 60,
child: FloatingActionButton(
heroTag: 'FAB',
clipBehavior: Clip.antiAlias,
splashColor: Colors.transparent,
highlightElevation: 0,
elevation: 0,
backgroundColor: color1,
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.all(
Radius.circular(16.0),
),
),
onPressed: () {
showModalBottomSheet(
elevation: 0,
enableDrag: false,
backgroundColor: color4,
barrierColor: darkBarrierColor,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(24),
topRight: Radius.circular(24),
),
),
context: context,
builder: (context) {
return CustomAddMenuScreen();
},
);
},
child: Transform.rotate(
angle: 22 / 28,
child: const Icon(
Icons.add,
),
),
),
),
),
);
}
}
Related
The first drawer should be on the appBar and the second one should be next to the testfield.
Here, when I used the second drawer next to the testfield, the right side drawer icon appeared in the appBar along with it.
I only want the left side drawer in the appBar and the second drawer next to the testfield in the right side.
this is my code
class MyApp extends StatefulWidget {
const MyApp({Key? key}) : super(key: key);
#override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
ApiManager apiManager = ApiManager();
#override
Widget build(BuildContext context) {
SystemChrome.setPreferredOrientations([
DeviceOrientation.portraitUp,
DeviceOrientation.portraitDown,
]);
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'CWC(Khushi)',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: DemoScreen(),
// home:VideoComponentPurple(),
);
}
}
final GlobalKey<ScaffoldState> _scaffoldkey = new GlobalKey();
class DemoScreen extends StatelessWidget {
const DemoScreen({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Scaffold(
key: _scaffoldkey,
endDrawer: Drawer(child: Drawer2()),
backgroundColor: Colors.white,
resizeToAvoidBottomInset: false,
appBar: AppBar(
leading: Builder(
builder: (BuildContext context) {
return IconButton(
icon: Icon(Icons.menu),
onPressed: () {
Scaffold.of(context).openDrawer();
},
tooltip: '',
);
},
),
automaticallyImplyLeading: true,
elevation: 0.5,
),
drawer: Drawer(
child: Drawer1(),
),
body: Padding(
padding: const EdgeInsets.only(top: 28.0),
child: Stack(
children: [
Container(
// padding: EdgeInsets.symmetric(vertical: 8),
height: 55,
child: TextField(
textAlignVertical: TextAlignVertical.center,
decoration: InputDecoration(
// contentPadding: EdgeInsets.only(top: 10.0,bottom: 0,left: 10,right: 10),
border: OutlineInputBorder(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(10),
bottomLeft: Radius.circular(10),
),
borderSide: BorderSide.none,
),
filled: true,
fillColor: const Color(0xFFFFFFFF),
hintText: 'Search for Wellness Tips & Tricks',
prefixIcon: const Icon(
Icons.search_outlined,
color: Color(0xFF444444),
),
),
),
),
Positioned(
right: 0,
child: Container(
decoration: BoxDecoration(
border: Border(
left: BorderSide(
color: Colors.grey,
width: 2.0,
),
)),
child: InkWell(
onTap: () {
_scaffoldkey.currentState!.openEndDrawer();
},
child: Container(
padding: EdgeInsets.all(15),
decoration: BoxDecoration(
color: Color(0xFFFFFFFF),
borderRadius: BorderRadius.only(
topRight: Radius.circular(10),
bottomRight: Radius.circular(10),
),
),
height: 55,
width: 60,
child: Image.asset(
'assets/right_side_hamburger.png',
height: 24,
width: 24,
),
),
),
),
),
],
),
),
);
}
}
class Drawer2 extends StatelessWidget {
const Drawer2({
Key? key,
}) : super(key: key);
#override
Widget build(BuildContext context) {
return Drawer(
// Custom widget must be return Drawer
child: ListTile(
//Implement any design on child property
title: Text("Demo tile2"),
),
);
}
}
class Drawer1 extends StatelessWidget {
const Drawer1({
Key? key,
}) : super(key: key);
#override
Widget build(BuildContext context) {
return Drawer(
// Custom widget must be return Drawer
child: ListTile(
//Implement any design on child property
title: Text("Demo tile1"),
),
);
}
}
I got the answer of this question.
answer is -->
AppBar(
automaticallyImplyLeading: false, // this will hide Drawer hamburger icon
actions: <Widget>[Container()], // this will hide endDrawer hamburger icon
... // other props
),
Here I am using introduction_screen plugin.
In this problem, I want the same Ui which is my first image, but my second image is being created as it is.
Here I want dots in middle after image and next text on bottom with arrow which should be work for next intro page
How to make it
This is my intro page code.
I am using introduction_screen plugin
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:introduction_screen/introduction_screen.dart';
class OnBoardingPage extends StatefulWidget {
#override
_OnBoardingPageState createState() => _OnBoardingPageState();
}
class _OnBoardingPageState extends State<OnBoardingPage> {
final introKey = GlobalKey<IntroductionScreenState>();
void _onIntroEnd(context) {
Navigator.of(context).push(
MaterialPageRoute(builder: (_) => HomePage()),
);
}
Widget _buildImage(String assetName, ) {
return Image.asset('assets/$assetName',);
}
#override
Widget build(BuildContext context) {
const bodyStyle = TextStyle(fontSize: 19.0);
const pageDecoration = PageDecoration(
titleTextStyle: TextStyle(fontSize: 28.0, fontWeight: FontWeight.w700),
bodyTextStyle: bodyStyle,
bodyPadding: EdgeInsets.fromLTRB(0.0, 0.0, 0.0, 16.0),
pageColor: Colors.white,
imagePadding: EdgeInsets.zero,
);
return Scaffold(
body: SafeArea(
child: IntroductionScreen(
key: introKey,
globalBackgroundColor: Colors.white,
pages: [
PageViewModel(
decoration: pageDecoration,
title: "Fractional shares",
body:
"Instead of having to buy an entire share, invest any amount you want.",
image: _buildImage('intro_s1.png'),
),
PageViewModel(
title: "Learn as you go",
body:
"Download the Stockpile app and master the market with our mini-lesson.",
image: _buildImage('intro_s1.png'),
decoration: pageDecoration,
),
PageViewModel(
title: "Kids and teens",
body:
"Kids and teens can track their stocks 24/7 and place trades that you approve.",
image: _buildImage('intro_s1.png'),
decoration: pageDecoration,
),
],
onDone: () => _onIntroEnd(context),
next: const Icon(Icons.arrow_forward),
done: const Icon(Icons.arrow_forward),
curve: Curves.fastLinearToSlowEaseIn,
controlsMargin: const EdgeInsets.all(16),
controlsPadding: kIsWeb
? const EdgeInsets.all(12.0)
: const EdgeInsets.fromLTRB(8.0, 4.0, 8.0, 4.0),
dotsDecorator: const DotsDecorator(
size: Size(10.0, 10.0),
color: Color(0xFFBDBDBD),
activeSize: Size(22.0, 10.0),
activeShape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(25.0)),
),
),
dotsContainerDecorator: const ShapeDecoration(
color: Colors.black87,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(8.0)),
),
),
),
),
);
}
}
class HomePage extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Home')),
body: const Center(child: Text("This is the screen after Introduction")),
);
}
}
I want looks like this
but it is becoming like this
change black87 to white in this section of your code.
dotsContainerDecorator: const ShapeDecoration(
color: Colors.black87,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(8.0))
I am trying to implement this modalBottomSheet
and I thought to use Stack with negative positioning
showModalBottomSheet(
context: context,
builder: (context) {
return Stack(
alignment: AlignmentDirectional.bottomStart,
children: [
Container(
width: double.infinity,
height: 200,
color: Colors.white,
child: Column(//here there will be the text)
),
Positioned(
top: -20,
left: 0,
right: 0,
child: CircleAvatar(
backgroundColor: Palette.white,
radius: 38,
child: CircleAvatar(
backgroundImage: NetworkImage(snapshot.data.image),
radius: 34,
backgroundColor: Palette.white),
),
)]);
However this cuts the top part of the CircleAvatar picture (as I kind of expected).
Any idea on how to implement this?
you need to change the clipBehavior to Clip.none on the Stack
Stack(
clipBehavior: Clip.none,
...)
Here is my tricky implementation.
Set bottom sheet's background color to transparent.
Add top margin as avatar's half height to base Container.
Set base container's background color to white
Change the avatar's top position value to 0
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
#override
void initState() {
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Container(),
floatingActionButton: FloatingActionButton(
onPressed: () {
show();
},
tooltip: 'Increment',
child: Icon(Icons.add),
),
);
}
void show() {
showModalBottomSheet(
backgroundColor: Colors.transparent,
context: context,
builder: (context) {
return Stack(
alignment: AlignmentDirectional.bottomStart,
children: [
Container(
width: double.infinity,
height: 200,
margin: EdgeInsets.only(top: 35),
color: Colors.transparent,
child: Container(
padding: EdgeInsets.only(top: 60),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(10),
topRight: Radius.circular(10),
),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Text(
'Alessandro Liparoti',
style: TextStyle(
color: Colors.black,
fontSize: 25,
fontWeight: FontWeight.bold,
),
),
SizedBox(height: 25),
Text(
'4 games palyed',
style: TextStyle(
color: Colors.grey,
fontSize: 20,
fontWeight: FontWeight.bold,
),
),
],
),
),
),
Positioned(
top: 0,
left: 0,
right: 0,
child: CircleAvatar(
backgroundColor: Colors.white,
radius: 38,
child: CircleAvatar(
backgroundImage: NetworkImage(
'https://image.flaticon.com/icons/png/512/147/147144.png'),
radius: 34,
backgroundColor: Colors.white),
),
),
],
);
});
}
}
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
I am trying to create something like the attached image. I got this far ...
Expanded(
child: Container(
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(32),
topRight: Radius.circular(32),
),
),
child: ButtonTheme(
child: ButtonBar(
alignment: MainAxisAlignment.center,
children: <Widget>[
RaisedButton(
onPressed: () => print('hi'),
child: Text('Referals'),
color: Color(0xff2FBBF0),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.only(
bottomLeft: Radius.circular(15.0),
topLeft: Radius.circular(15.0)),
),
),
RaisedButton(
onPressed: () => print('hii'),
child: Text('Stats'),
color: Color(0xff2FBBF0),
),
RaisedButton(
onPressed: () => print('hiii'),
child: Text('Edit Profile'),
color: Color(0xff2FBBF0),
// color: Colors.white,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.only(
bottomRight: Radius.circular(15.0),
topRight: Radius.circular(15.0)),
),
),
],
),
),
),
),
But I don't really feel like it will look like the image.
I would also like the button group to be at the top of the Container. Now they're in the absolute center. Just like they would be if wrapped in a Center widget.
Here's the complete code. I have just used Container and Row because I find it more suitable and easy to achieve without any headache. :P
If you want with RaisedButton, figure it out.
Source:
import 'package:flutter/material.dart';
class Demo extends StatefulWidget {
#override
_DemoState createState() => new _DemoState();
}
class _DemoState extends State<Demo> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("DEMO")),
body: Padding( // used padding just for demo purpose to separate from the appbar and the main content
padding: EdgeInsets.all(10),
child: Container(
alignment: Alignment.topCenter,
child: Container(
height: 60,
padding: EdgeInsets.all(3.5),
width: MediaQuery.of(context).size.width * 0.9,
decoration: BoxDecoration(
color: Colors.blue,
borderRadius: BorderRadius.all(Radius.circular(15)),
),
child: Row(
children: <Widget>[
Expanded(
child: InkWell(
onTap: () {},
child: Container(
alignment: Alignment.center,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.only(
bottomLeft: Radius.circular(12),
topLeft: Radius.circular(12))),
child: Text("Referrals",
style: TextStyle(
color: Colors.blue,
fontSize: 17,
)),
))),
Expanded(
child: InkWell(
onTap: () {},
child: Container(
alignment: Alignment.center,
child: Text("Stats",
style: TextStyle(
color: Colors.white, fontSize: 17)),
))),
Padding(
padding: EdgeInsets.symmetric(vertical: 5),
child: Container(color: Colors.white, width: 2)),
Expanded(
child: InkWell(
onTap: () {},
child: Container(
alignment: Alignment.center,
child: Text("Edit Profile",
style: TextStyle(
color: Colors.white, fontSize: 17)),
)))
],
)),
)));
}
}
Output Screenshot:
Check my ButtonGroup widget that I created
import 'package:flutter/material.dart';
class ButtonGroup extends StatelessWidget {
static const double _radius = 10.0;
static const double _outerPadding = 2.0;
final int current;
final List<String> titles;
final ValueChanged<int> onTab;
final Color color;
final Color secondaryColor;
const ButtonGroup({
Key key,
this.titles,
this.onTab,
int current,
Color color,
Color secondaryColor,
}) : assert(titles != null),
current = current ?? 0,
color = color ?? Colors.blue,
secondaryColor = secondaryColor ?? Colors.white,
super(key: key);
#override
Widget build(BuildContext context) {
return Material(
color: color,
borderRadius: BorderRadius.circular(_radius),
child: Padding(
padding: const EdgeInsets.all(_outerPadding),
child: ClipRRect(
borderRadius: BorderRadius.circular(_radius - _outerPadding),
child: IntrinsicHeight(
child: Row(
mainAxisSize: MainAxisSize.min,
children: _buttonList(),
),
),
),
),
);
}
List<Widget> _buttonList() {
final buttons = <Widget>[];
for (int i = 0; i < titles.length; i++) {
buttons.add(_button(titles[i], i));
buttons.add(
VerticalDivider(
width: 1.0,
color: (i == current || i + 1 == current) ? color : secondaryColor,
thickness: 1.5,
indent: 5.0,
endIndent: 5.0,
),
);
}
buttons.removeLast();
return buttons;
}
Widget _button(String title, int index) {
if (index == this.current)
return _activeButton(title);
else
return _inActiveButton(title, index);
}
Widget _activeButton(String title) => FlatButton(
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
disabledColor: secondaryColor,
disabledTextColor: color,
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.zero,
),
child: Text(title),
onPressed: null,
);
Widget _inActiveButton(String title, int index) => FlatButton(
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
color: Colors.transparent,
textColor: Colors.white,
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.zero,
),
child: Text(title),
onPressed: () {
if (onTab != null) onTab(index);
},
);
}
You can use it like this
ButtonGroup(
titles: ["Button1", "Button2", "Button3"],
current: index,
color: Colors.blue,
secondaryColor: Colors.white,
onTab: (selected) {
setState(() {
index = selected;
});
},
)
Example:
import 'package:flutter/material.dart';
import 'package:flutter_app_test2/btn_grp.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
home: MainPage(),
);
}
}
class MainPage extends StatefulWidget {
#override
_MainPageState createState() => _MainPageState();
}
class _MainPageState extends State<MainPage> {
int current = 0;
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: ButtonGroup(
titles: ["Button1", "Button2", "Button3", "Button3"],
current: current,
onTab: (selected) {
print(selected);
setState(() {
current = selected;
});
},
),
),
);
}
}
try adding following in all RaisedButton widgets:
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
and buttonPadding: EdgeInsets.all(1), in ButtonBar
Source: https://api.flutter.dev/flutter/material/MaterialTapTargetSize-class.html