Multiple buttons/Texts in a circle in flutter - flutter

I'm trying to create a circle in the flutter. I want to add multiple buttons and bound them in a circle like this.
The marked fields are supposed to be buttons and Course 1 is just the text.
I am able to create something like this but it is only string splitted in the button.
Here is my code for this. I'm not getting any idea about how to do this task. I'm new to flutter.
import 'package:flutter/material.dart';
void main(){runApp(MyApp());}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: new AppBar(
title: Text("Student home"),
),
body:Center(
child: Container(
margin: EdgeInsets.all(10),
padding: EdgeInsets.all(10),
width: 200,
height: 200,
child: Center(
child: Text("Course 1 \n Course 2",
style: TextStyle(fontSize: 12.0,
fontStyle: FontStyle.italic,
),
textAlign: TextAlign.center,
),
),
decoration: BoxDecoration(
border:Border.all(width:3),
borderRadius: BorderRadius.all(
Radius.circular(50),
),
color: Colors.yellow,
),
),
)
),
);
}
}

try shape: BoxShape.circle,,
Container(
width: 100,
height: 100,
decoration: BoxDecoration(
border: Border.all(width: 2),
shape: BoxShape.circle,
// You can use like this way or like the below line
//borderRadius: new BorderRadius.circular(30.0),
color: Colors.amber,
),
child:Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text('ABC'),
Text('XYZ'),
Text('LOL'),
],
),
),
Output

is this design that you want?
it contain two button and one text widget
body: Center(
child: Container(
margin: EdgeInsets.all(10),
padding: EdgeInsets.all(10),
width: 200,
height: 200,
child: Center(
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
"Course 1",
style: TextStyle(
fontSize: 12.0,
fontStyle: FontStyle.italic,
),
textAlign: TextAlign.center,
),
MaterialButton(
onPressed: () {
//do whatever you want
},
child: Text("Mark Attendance"),
),
MaterialButton(
onPressed: () {
//do whatever you want
},
child: Text("Mark Attendance"),
),
],
),
),
decoration: BoxDecoration(
border: Border.all(width: 3),
borderRadius: BorderRadius.all(
Radius.circular(200),
),
color: Colors.yellow,
),
),
),

There are multiple ways to make the border round. As of now you are using fixed height and width always use greater number for border-radius.
For eg.
when your heigh is 200X200 use 150-200 number for border-radius.
here is the code which works fine when you have fixed height and width of the container.
Note: This works only fine when your heigh and width is fixed for the container because the padding in the code is static.If you want dynamic then please use the screen calculation techniques to make if responsive
Making any widget clickable in the Flutter.
There are a couple of Widgets available to make any widget clickable
Gesture Detector
This widget has many methods including onTap() which means you can attach a callback when the user clicks on the widget. For eg (this is used in your code)
GestureDetector(
onTap: (){}, //this is call back on tap
child: Text("Mark Attendance")
)
InkWell Widget (Note: This widget will only work when it is a child of the Material widget)
Material(
child: InkWell(
onTap: (){},
child: Text("Mark Attendance"),
),
)
Here is the working code.
import 'package:flutter/material.dart';
void main(){runApp(MyApp());}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: new AppBar(
title: Text("Student home"),
),
body:Center(
child: Container(
margin: EdgeInsets.all(10),
padding: EdgeInsets.all(10),
width: 200,
height: 200,
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Padding(
padding: const EdgeInsets.only(bottom:40.0,top: 20.0),
child: Text("Course 1"),
),
Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
Padding(
padding: const EdgeInsets.all(8.0),
child: GestureDetector(
onTap: (){},
child: Text("Mark Attendance")),
),
Padding(
padding: const EdgeInsets.all(8.0),
child:Material(
child: InkWell(
onTap: (){},
child: Text("Mark Attendance"),
),
)
),
],)
],
),
decoration: BoxDecoration(
border:Border.all(width:3),
borderRadius: BorderRadius.all(
Radius.circular(150),
),
color: Colors.yellow,
),
),
)
),
);
} }
Note: Material widget always set the background as white for the text
widget
Thanks, I hope is information was helpfull

Related

How to reposition a fixed widget in flutter

I'm building an AR app with Flutter and using the ar_flutter_plugin.
The position of the AR widget seems to be fixed to the top left and it doesn't move anywhere else. Whatever the other widgets in the tree, doesn't change anything. It's always at top left corner (see image).
It works with a dummy widget just fine (compare second img).
Child Ar widget
Widget build(BuildContext context) {
return SizedBox(
width: widget.width,
height: widget.height,
child: Column(
children: [
Expanded(
child: Column(children: [
Expanded(
child: ARView(
onARViewCreated: onARViewCreated,
planeDetectionConfig:
PlaneDetectionConfig.horizontalAndVertical,
),
),
Align(
alignment: Alignment(1, 1),
child: FloatingActionButton(onPressed: takePicture))
]),
),
],
));
}
Parent Widget
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Title'),
),
key: scaffoldKey,
backgroundColor: FlutterFlowTheme.of(context).primaryBackground,
body: SafeArea(
child: GestureDetector(
onTap: () => FocusScope.of(context).unfocus(),
child: Stack(
children: [
Container(
width: 350,
height: 350,
child: ObjectsOnPlanesWidget(
// child: custom_widgets.ArPlaceholder(
width: double.infinity,
height: double.infinity,
modelUrl: widget.modelUrl,
),
),
Align(
alignment: AlignmentDirectional(-0.23, -0.92),
child: Padding(
padding: EdgeInsetsDirectional.fromSTEB(8, 24, 8, 24),
child: Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Container(
width: 30,
height: 30,
decoration: BoxDecoration(
color:
FlutterFlowTheme.of(context).secondaryBackground,
borderRadius: BorderRadius.circular(12),
),
child: InkWell(
onTap: () async {
Navigator.pop(context);
},
child: Icon(
Icons.chevron_left,
color: Colors.black,
size: 24,
),
),
),
Text(
'Try On',
style: FlutterFlowTheme.of(context).bodyText1,
),
Container(
width: 30,
height: 30,
decoration: BoxDecoration(
color:
FlutterFlowTheme.of(context).secondaryBackground,
borderRadius: BorderRadius.circular(12),
),
child: Icon(
Icons.share_outlined,
color: Colors.black,
size: 24,
),
),
],
),
),
),
Align(
alignment: AlignmentDirectional(0, 0.95),
child: Container(
width: 50,
height: 50,
decoration: BoxDecoration(
color: FlutterFlowTheme.of(context).secondaryBackground,
borderRadius: BorderRadius.circular(12),
),
child: Icon(
Icons.photo_camera,
color: Colors.black,
size: 24,
),
),
),
],
),
),
),
);
}
I want to put the camera in the background and put other widgets (such as photo-taking-button) on top of it.
How do I reposition it into a container? At least under the App Bar?
Logically this should have worked, what i would suggest you try would be to first have a SafeArea widget.
SafeArea(
child: build(buildContext),
),
I had a similar issue in the past and using this solved it.
Also, there seems to be an open issue which seems related to this with the following possible solution :
With Flutter 2.10.5. it works without problems. This seems to be a Flutter 3 problem.
The way platforms views are rendered was changed in the 3.0 release.
probably same issue:
flutter/flutter#106246
explained here:
flutter/flutter#103630
I hope this will be fixed in new Flutter 3 releases soon.
And also this
I try the master channel Flutter v3.1.0-0.0.pre.1372 and the issue is fixed there.
Fixed will come to a stable channel soon with Flutter v3.1.0.
Also, I am not sure why are you using SizedBox as your parent widget.
Why not try a basic Container instead?
Good luck, Let me know if I can help with anything else

How to make ExpansionTile scrollable when end of screen is reached?

In the project I'm currently working on, I have a Scaffold that contains a SinlgeChildScrollView. Within this SingleChildScrollView the actual content is being displayed, allowing for the possibility of scrolling if the content leaves the screen.
While this makes sense for ~90% of my screens, however I have one screen in which I display 2 ExpansionTiles. Both of these could possibly contain many entries, making them very big when expanded.
The problem right now is, that I'd like the ExpansionTile to stop expanding at latest when it reaches the bottom of the screen and make the content within the ExpansionTile (i.e. the ListTiles) scrollable.
Currently the screen looks like this when there are too many entries:
As you can clearly see, the ExpansionTile leaves the screen, forcing the user to scroll the actual screen, which would lead to the headers of both ExpansionTiles disappearing out of the screen given there are enought entries in the list. Even removing the SingleChildScrollView from the Scaffold doesn't solve the problem but just leads to a RenderOverflow.
The code used for generating the Scaffold and its contents is the following:
class MembershipScreen extends StatefulWidget {
#override
State<StatefulWidget> createState() => _MembershipScreenState();
}
class _MembershipScreenState extends State<MembershipScreen> {
String _fontFamily = 'OpenSans';
Widget _buildMyClubs() {
return Container(
decoration: BoxDecoration(
color: Colors.white,
border: Border.all(
color: Color(0xFFD2D2D2),
width: 2
),
borderRadius: BorderRadius.circular(25)
),
child: Theme(
data: ThemeData().copyWith(dividerColor: Colors.transparent),
child: ExpansionTile(
title: Text("My Clubs"),
trailing: Icon(Icons.add),
children: getSearchResults(),
),
)
);
}
Widget _buildAllClubs() {
return Container(
decoration: BoxDecoration(
color: Colors.white,
border: Border.all(
color: Color(0xFFD2D2D2),
width: 2
),
borderRadius: BorderRadius.circular(25)
),
child: Theme(
data: ThemeData().copyWith(dividerColor: Colors.transparent),
child: SingleChildScrollView(
child: ExpansionTile(
title: Text("All Clubs"),
trailing: Row(
mainAxisSize: MainAxisSize.min,
children: [
Icon(Icons.add)
],
),
children: getSearchResults(),
),
)
)
);
}
#override
Widget build(BuildContext context) {
return Scaffold(
extendBody: true,
body: AnnotatedRegion<SystemUiOverlayStyle>(
value: SystemUiOverlayStyle.light,
child: GestureDetector(
onTap: () => FocusScope.of(context).unfocus(),
child: Stack(
children: <Widget>[
Container(
height: double.infinity,
width: double.infinity,
decoration: BoxDecoration(
gradient: kGradient //just some gradient
),
),
Center(
child: Container(
height: double.infinity,
constraints: BoxConstraints(maxWidth: 500),
child: SingleChildScrollView(
physics: AlwaysScrollableScrollPhysics(),
padding: EdgeInsets.symmetric(horizontal: 40.0, vertical: 20.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'Clubs',
style: TextStyle(
fontSize: 30.0,
color: Colors.white,
fontFamily: _fontFamily,
fontWeight: FontWeight.bold),
),
SizedBox(
height: 20,
),
_buildMyClubs(),
SizedBox(height: 20,),
_buildAllClubs()
],
),
),
),
),
],
),
)
),
);
}
List<Widget> getSearchResults() {
return [
ListTile(
title: Text("Test1"),
onTap: () => print("Test1"),
),
ListTile(
title: Text("Test2"),
onTap: () => print("Test2"),
), //etc..
];
}
}
I hope I didn't break the code by removing irrelevant parts of it in order to reduce size before posting it here. Hopefully, there is someone who knows how to achieve what I intend to do here and who can help me with the solution for this.
EDIT
As it might not be easy to understand what I try to achieve, I tried to come up with a visualization for the desired behaviour:
Thereby, the items that are surrounded with dashed lines are contained with the list, however cannot be displayed because they would exceed the viewport's boundaries. Hence the ExpansionTile that is containing the item needs to provide a scroll bar for the user to scroll down WITHIN the list. Thereby, both ExpansionTiles are visible at all times.
Try below code hope its help to you. Add your ExpansionTile() Widget inside Column() and Column() wrap in SingleChildScrollView()
Refer SingleChildScrollView here
Refer Column here
You can refer my answer here also for ExpansionPanel
Refer Lists here
Refer ListView.builder() here
your List:
List<Widget> getSearchResults = [
ListTile(
title: Text("Test1"),
onTap: () => print("Test1"),
),
ListTile(
title: Text("Test2"),
onTap: () => print("Test2"),
), //etc..
];
Your Widget using ListView.builder():
SingleChildScrollView(
padding: EdgeInsets.all(20),
child: Column(
children: [
Card(
child: ExpansionTile(
title: Text(
"My Clubs",
),
trailing: Icon(
Icons.add,
),
children: [
ListView.builder(
shrinkWrap: true,
itemBuilder: (BuildContext context, int index) {
return Column(
children: getSearchResults,
);
},
itemCount: getSearchResults.length, // try 50 length just testing
),
],
),
),
],
),
),
Your Simple Widget :
SingleChildScrollView(
padding: EdgeInsets.all(20),
child: Column(
children: [
Card(
child: ExpansionTile(
title: Text(
"My Clubs",
),
trailing: Icon(
Icons.add,
),
children:getSearchResults
),
),
],
),
),
Your result screen ->

Flutter: How can i put the text widget center in screen

I need to put the title' in the center even to fit any screen, I know can I sized box to move the title in the center, but when using the different device the dimensions surely will change and become the title the different places.
this is code :
class NotificationDoctor extends StatelessWidget {
TextStyles textStyles = TextStyles.HEADING;
Texts texts;
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: Container(
decoration: BoxDecoration(
color: Theme.of(context).primaryColorDark,
borderRadius: BorderRadius.only(bottomLeft: Radius.circular(15.0))),
height: 130.h,
child: Padding(
padding: EdgeInsets.only(top: 40.h),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Padding(
padding: EdgeInsets.only(
right: 15.w,
top: 15.h,
),
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.start,
children: [
FlatButton(
child: ArrowIcon(
arrowColor: Color(0xFFEEF4F9),
backgroundColor:
Theme.of(context).primaryColor.withOpacity(.9),
),
onPressed: () {
Navigator.pop(context);
},
),
// SizedBox(
// width: 55,
// ),
Center(
child: Texts(
'Notifications',
style: TextStyles.HEADING,
color: Color(0xFFEEF4F9),
),
),
],
),
),
],
),
),
),
));
}
}
use the padding like this
Padding(
padding: EdgeInsets.symmetric(vertical: 5.h, horizontal: 3.h),
child: Container(),
);
read more at https://pub.dev/packages/sizer

Flutter - center button

I'm creating a UI with 5 buttons. One of them should be center and its width should be 50% of the screen. The height should be the same size (it should be a circle). I tried with MediaQuery.of(context).size.width but it doesn't work.
This is the closest I got:
The code is:
Widget _playButton() {
return FractionallySizedBox(
widthFactor: 0.5,
heightFactor: 0.5, // I know this is wrong
child: Container(
alignment: new FractionalOffset(0.0, 0.0),
color: Colors.red,
/*decoration: new BoxDecoration(
color: hexToColor('#E8532E'),
shape: BoxShape.circle,
),*/
child: Center(
child: Text(
"PLAY",
style: TextStyle(fontSize: 20.0, color: Colors.white),
),
),
),
);
}
The container where I have this button:
Widget build(BuildContext context) {
return new MaterialApp(
debugShowCheckedModeBanner: false,
home: new Scaffold(
body: new Stack(
alignment: AlignmentDirectional.center,
children: <Widget>[_myScreenOptions(), _playButton()],
),
),
);
}
Obviously, the rest of the buttons should be clickable.
If you wanna create a circular button, you don't have to worry about width & height, giving only one size is enough... or you can use FractionallySizedBox, as you already did.
Code output:
Sample code:
import 'package:flutter/material.dart';
class SampleCenterButton extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
width: double.infinity,
height: double.infinity,
child: Stack(
alignment: Alignment.center,
children: <Widget>[
_myScreenOptions(),
_playButton(),
],
),
),
);
}
_playButton() {
return GestureDetector(
onTap: () {
print("Play game");
},
child: FractionallySizedBox(
widthFactor: 0.5,
child: Container(
// defining one dimension works as well, as Flutter knows how to render a circle.
// width: MediaQuery.of(context).size.width/2,
decoration: BoxDecoration(
color: Colors.red,
shape: BoxShape.circle,
),
child: Center(
child: Text(
"PLAY",
style: TextStyle(fontSize: 30, color: Colors.white),
),
),
),
),
);
}
_myScreenOptions() {
return Column(
children: <Widget>[
buildRow([
buildOption(Color(0xff1D4554), Icons.person, "Teams"),
buildOption(Color(0xff229B8D), Icons.folder_open, "Pets"),
]),
buildRow([
buildOption(Color(0xffE7C16A), Icons.videogame_asset, "Modes"),
buildOption(Color(0xffF2A061), Icons.settings, "Options"),
]),
],
);
}
Widget buildOption(Color bgColor, IconData iconData, String title) {
return Expanded(
child: Container(
color: bgColor,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Icon(
iconData,
size: 80,
),
Text(
title,
style: TextStyle(fontSize: 30),
),
],
),
),
);
}
buildRow(List<Widget> buttons) {
return Expanded(
child: Row(
mainAxisSize: MainAxisSize.max,
crossAxisAlignment: CrossAxisAlignment.start,
children: buttons,
),
);
}
}

How to put scroll view inside stack widget in flutter

I am making a flutter application in which i uses body as a stack and in this stack i have two child.One is main body and other is back button which is at top of screen.The first child of stack is scrollview.Here is my build method.
Widget build(BuildContext context) {
return Scaffold(
//debugShowCheckedModeBanner: false,
key: scaffoldKey,
backgroundColor: Color(0xFF5E68A6),
body: Stack(
children: <Widget>[
Container(
margin: const EdgeInsets.fromLTRB(0.0, 10.0 , 0.0 , 0.0 ),
height: double.infinity,
child:CustomScrollView(
slivers: <Widget>[
new Container(
margin: EdgeInsets.all(15.0),
child:Text(getTitle(),
style: TextStyle(fontSize: 20.0,fontWeight: FontWeight.bold,color: Colors.white),
),
),
//middle section
_isLoading == false ?
new Expanded(child: GridView.builder(
itemCount: sub_categories_list.length,
physics: const NeverScrollableScrollPhysics(),
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 2),
itemBuilder: (context, position){
return InkWell(
child: new Container(
//color: Colors.white,
padding: EdgeInsets.all(20),
margin: EdgeInsets.all(10),
height: 130,
width: 130,
child: new Center(
child :
Text(sub_categories_list[position].name,
style: TextStyle(fontSize: 18.0,fontWeight: FontWeight.bold),
)
),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.all(Radius.circular(16)),
// border: Border.all(color: Colors.black, width: 3),
),
),
onTap: () {
//write here
// Fluttertoast.showToast(msg: "You clicked id :"+sub_categories_list[position].cat_id.toString());
Navigator.pushNamed(context, '/advicemyself');
},
);
}
))
:
CircularProgressIndicator(),
Container(
margin: EdgeInsets.all(18.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
mainAxisSize: MainAxisSize.max,
children: <Widget>[
new Column(
children: <Widget>[
Image.asset('assets/bt1.png'),
Container(
margin: EdgeInsets.all(10.0),
child: Text("FIND HELP",
style: TextStyle(fontSize: 18.0,color: Colors.white),
),
)
],
),
new Column(
children: <Widget>[
Image.asset('assets/bt2.png'),
Container(
margin: EdgeInsets.all(10.0),
child: Text("HOME",
style: TextStyle(fontSize: 18.0,color: Colors.white),
),
)
],
),
new Column(
mainAxisAlignment:MainAxisAlignment.spaceEvenly,
children: <Widget>[
Image.asset('assets/bt3.png'),
Container(
margin: EdgeInsets.all(10.0),
child: Text("CALL 999",
style: TextStyle(fontSize: 18.0,color: Colors.white),
),
)
],
),
],
),
),
],
),
),
Positioned(
left: 10,
top: 30,
child: IconButton(
icon: Icon(Icons.arrow_back),
onPressed: () => {
//go back
},
color: Colors.white,
iconSize: 30,
),
),
// makeview()
],
),
// This trailing comma makes auto-formatting nicer for build methods.
);
}
I have also tried using SingleChildScrollView but that also does not works.What i am doing wrong here ?
Here is link to the design which i want to make.
https://imgur.com/a/w7nLmKC
The back should be above scroll view so i used stack widget.
Running your sample code, there doesn't seem to be a need for overlapping widgets. Using Stack seems to be unnecessary. One way you could do is by using Column widget, and using Expanded as you see fit.
Widget build(BuildContext context) {
return Scaffold(
body: Column(
children: [
Widget(), // back button goes here
CustomScrollView(...),
],
),
);
}
Otherwise, if you really need to use Stack, the scroll function should work fine. I've tried this locally and the Stack widget doesn't interfere with scrolling of Slivers, ListView, and GridView.
Stack(
children: [
/// Can be GridView, Slivers
ListView.builder(),
/// Back button
Container(),
],
),