Related
I'm a beginner at app dev and I'm trying out flutter. I'm currently having a problem with positioning my background on the project that I am currently testing out.I'm following a UI kit that I am trying to copy for the purpose of practicing, but I am having problem with the UI.
I tried using stack but the whole screen is wrapped with its children and not taking up space. it looks like this:
and this is what I wanted to do:
This is the background that I wanted to put in my app, it is not literally a background or wallpaper because of its size. I just needed this to be placed at the bottom of the screen or background:
this is the code that I currently have:
import 'package:audit_finance_app/constant/theme.dart';
import 'package:audit_finance_app/widgets/widgets.dart';
import 'package:audit_finance_app/screens/homescreen.dart';
import 'package:flutter/material.dart';
import 'dart:math' as math;
class SignInPage extends StatefulWidget {
const SignInPage({super.key});
#override
State<SignInPage> createState() => _SignInPageState();
}
class _SignInPageState extends State<SignInPage> {
late List<String> inputPass;
String defaultPass = '1234';
#override
void initState() {
inputPass = [];
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Stack(
fit: StackFit.expand,
children: <Widget>[
const SizedBox(
width: double.maxFinite,
height: double.maxFinite,
child: Image(
image: AssetImage('assets/background.png'),
),
),
CustomScrollView(
slivers: <Widget>[
SliverAppBar(
pinned: true,
flexibleSpace: Container(
decoration: const BoxDecoration(
gradient: LinearGradient(
colors: [
AuditTheme.primaryColor,
AuditTheme.secondaryColor,
],
),
),
),
leadingWidth: 100,
leading: Padding(
padding: const EdgeInsets.fromLTRB(10, 0, 0, 0),
child: Row(
children: const [
Expanded(
child: ImageIcon(
AssetImage('assets/logo/white_logo.png'),
),
),
Text(
'Audit',
style: TextStyle(fontSize: 20),
),
],
),
),
title: const Text('Sign In'),
centerTitle: true,
actions: [
Transform(
alignment: Alignment.center,
transform: Matrix4.rotationY(math.pi),
child: IconButton(
onPressed: () {},
icon: const Icon(Icons.sort),
),
),
],
),
SliverList(
delegate: SliverChildListDelegate(
[
Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Widgets().sixedBoxHeight(50),
Column(
children: [
const CircleAvatar(
radius: 35,
backgroundImage:
AssetImage('assets/logo/audit_logo.png'),
),
Widgets().sixedBoxHeight(10),
const Text(
'Ledjoric Vermont',
style: TextStyle(fontSize: 20),
),
],
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
pinIconTest(inputPass.isNotEmpty
? Colors.black
: Colors.grey),
pinIconTest(inputPass.length >= 2
? Colors.black
: Colors.grey),
pinIconTest(inputPass.length >= 3
? Colors.black
: Colors.grey),
pinIconTest(inputPass.length == 4
? Colors.black
: Colors.grey),
],
),
Card(
child: Column(
children: [
Row(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
children: [
numPad(const Text('1'), () => inputPin('1')),
numPad(const Text('2'), () => inputPin('2')),
numPad(const Text('3'), () => inputPin('3')),
],
),
Row(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
children: [
numPad(const Text('4'), () => inputPin('4')),
numPad(const Text('5'), () => inputPin('5')),
numPad(const Text('6'), () => inputPin('6')),
],
),
Row(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
children: [
numPad(const Text('7'), () => inputPin('7')),
numPad(const Text('8'), () => inputPin('8')),
numPad(const Text('9'), () => inputPin('9')),
],
),
Row(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.end,
children: [
const SizedBox(
width: 100,
height: 100,
),
numPad(const Text('0'), () => inputPin('0')),
numPad(
const Icon(Icons.backspace_sharp),
() => deletePin(),
),
],
),
],
),
),
],
),
],
),
),
],
),
],
),
);
}
Widget pinIconTest(Color color) {
return Padding(
padding: const EdgeInsets.all(5.0),
child: Icon(
Icons.circle,
size: 35,
color: color,
),
);
}
Widget numPad(Widget widget, void Function() function) {
return SizedBox(
width: 100,
height: 100,
child: TextButton(
style: TextButton.styleFrom(
foregroundColor: Colors.grey,
textStyle: const TextStyle(
fontSize: 30,
),
),
onPressed: function,
child: widget,
),
);
}
void inputPin(String value) {
setState(() {
inputPass.length != 4 ? inputPass.add(value) : null;
inputPass.length == 4 ? checkPass() : null;
});
print(inputPass);
}
void checkPass() {
var stringList = inputPass.join('');
if (stringList == defaultPass) {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => const HomeScreen(),
),
);
}
print(stringList);
}
void deletePin() {
setState(() {
inputPass.isNotEmpty ? inputPass.removeLast() : null;
});
print(inputPass);
}
}
I was missing the fact you want to place at the bottom that background, however to achieve that you can do it as the code below shows:
class SignInPage extends StatefulWidget {
const SignInPage({super.key});
#override
State<SignInPage> createState() => _SignInPageState();
}
class _SignInPageState extends State<SignInPage> {
#override
void initState() {
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Stack(
fit: StackFit.expand,
children: <Widget>[
const Align(
alignment: Alignment.bottomCenter,
child: Image(
image: AssetImage('assets/background.png'),
),
),
//Other child here
],
),
);
}
}
And this is the result:
You can use the example below for the status bar. I don't know about the real problem.
You can try using this way for gradient color
SystemUiOverlayStyle systemUiOverlayStyle = SystemUiOverlayStyle(
statusBarColor: Colors.transparent,
statusBarIconBrightness: Brightness.light,
statusBarBrightness: Brightness.dark,
statusBarGradient: LinearGradient(
colors: [Colors.red, Colors.blue],
begin: Alignment.topLeft,
end: Alignment.bottomRight,
),
);
You need to wrap your image in a Positioned Widget.
Positioned(bottom: 0.0,
child: const SizedBox(
width: double.maxFinite,
height: double.maxFinite,
child: Image(
image: AssetImage('assets/background.png'),
),
),
Or you can use the alignment property of the Stack to stick everything onto the bottom. I'm not sure this is exactly what you want though.
body: Stack(
alignment: Alignment.bottomCenter,
fit: StackFit.expand,
children: <Widget>[
const SizedBox(
width: double.maxFinite,
height: double.maxFinite,
child: Image(
image: AssetImage('assets/background.png'),
),
),
How can I achieve something like this in Flutter? Is it possible in
I have tried these codes and it gave me an error which said no DefaultTabController. I was confused where I should put it in. Example in internet wrote I have to put it in Scaffold body. But my code required some widgets to display image using Stack before using TabBar.
import 'package:felix_idn/library/widget/components/enums.dart';
import 'package:felix_idn/library/widget/components/path.dart';
import 'package:felix_idn/library/widget/ui/button.dart';
import 'package:felix_idn/library/widget/ui/text.dart';
import 'package:felix_idn/menu/music/music_therapy.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
class MusicAmbient extends StatelessWidget {
const MusicAmbient({super.key});
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
bottom: const TabBar(
tabs: [
Tab(icon: Icon(Icons.directions_car)),
Tab(icon: Icon(Icons.directions_transit)),
],
),
title: Text('Flutter Tabs Example'),
),
body: Container(
color: Colors.black,
child: SafeArea(
child: Container(
color: const Color.fromARGB(115, 55, 55, 55),
child: Stack(
children: [
//Icon back
Align(
alignment: Alignment.topLeft,
child: IconButton(
icon: const Icon(Icons.arrow_back_sharp),
iconSize: 32.0,
constraints: const BoxConstraints(),
padding: const EdgeInsets.all(3.0),
onPressed: () => Get.off(() => const MusicTherapy()),
color: Colors.white,
),
),
//Piano Background & Tabs
Align(
alignment: Alignment.topCenter,
child: Column(
children: [
const SizedBox(height: 40.0),
ImageButton(path: bgamb, callback: () => Get.back(), type: IconType.NONE),
const TabBarView(
children: [
MusicTherapy(),
MusicTherapy(),
],
),
],
),
),
//Title
Align(
alignment: Alignment.topCenter,
child: Column(
children: const [
SizedBox(height: 6.0),
Titles("Ambient", color: Colors.white, size: 20.0),
],
),
),
],
),
),
),
),
);
}
}
You need to create and use TabController.
class MusicAmbient extends StatefulWidget {
const MusicAmbient({super.key});
#override
State<MusicAmbient> createState() => _MusicAmbientState();
}
class _MusicAmbientState extends State<MusicAmbient>
with SingleTickerProviderStateMixin {
late final TabController controller = TabController(length: 2, vsync: this);
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
bottom: TabBar(
controller: controller, //here
tabs: [
Tab(icon: Icon(Icons.directions_car)),
Tab(icon: Icon(Icons.directions_transit)),
],
),
title: Text('Flutter Tabs Example'),
),
body: Container(
color: Colors.black,
child: SafeArea(
child: Container(
color: const Color.fromARGB(115, 55, 55, 55),
child: Stack(
children: [
//Icon back
Align(
alignment: Alignment.topLeft,
child: IconButton(
icon: const Icon(Icons.arrow_back_sharp),
iconSize: 32.0,
constraints: const BoxConstraints(),
padding: const EdgeInsets.all(3.0),
onPressed: null,
color: Colors.white,
),
),
//Piano Background & Tabs
Align(
alignment: Alignment.topCenter,
child: Column(
children: [
const SizedBox(height: 40.0),
// ImageButton(
// path: bgamb,
// callback: () => Get.back(),
// type: IconType.NONE),
Expanded(
child: TabBarView(
controller: controller,//here
children: [
// MusicTherapy(),
// MusicTherapy(),
Text("A"),
Text("B"),
],
),
),
],
),
),
//Title
Align(
alignment: Alignment.topCenter,
child: Column(
children: const [
SizedBox(height: 6.0),
// Titles("Ambient", color: Colors.white, size: 20.0),
],
),
),
],
),
),
),
),
);
}
}
Also you can try using flexibleSpace on AppBar for the image.
More about using TabBar
Please create customTabar it's very easy to create with provider.
How can I create a row w/2 buttons that, together, take up the space of their parent (the row)? I want to place this row immediately above the bottom navigation bar at times and then at other times I want it to take the place of the bottom navigation bar. Can I do it just using Row? I've tried persistentFooterButtons with a child of Row and children of FractionallySizedBox but it results in an overflow error and the buttons don't take up the height of of the persistentFooterButtons. There's got to be a better, more straight-forward, approach. Just learning Flutter.
This is a rough example of what I want placed at the bottom of the screen (buttons should be of equal height), where the bottom nav bar would be... and/or immediately above.
[![horizontallyAlignedButtonsWithWidthOfRow][1]][1]
Some of the many (unsuccessful attempts) below:
Wrap Buttons in Expand Attempt:
return Row(
children: <Widget>[
Expanded(
child: ElevatedButton(
onPressed: () {},
style: TextButton.styleFrom(backgroundColor: Colors.blue),
child: Text(
"Some Text #1",
style: TextStyle(color: Colors.white),
))),
Expanded(
child: ElevatedButton(
onPressed: () {},
style: TextButton.styleFrom(backgroundColor: Colors.green),
child: Text("Some Text #2"),
),
),
],
Wrap Buttons in Expand Attempt Result:
[![Result][2]][2]
As you can see, there is white space that shouldn't be there and the buttons are evenly spaced. I have also tried using ColoredBoxes instead of buttons as I read that buttons have margins that cannot be changed?
UPDATE
Finally figured it out, with the help of #lava solutions. Just made a few tweaks to it to remove white space, etc.
return Container(
padding: EdgeInsets.all(0.0),
height: 50,
child: Row(
children: [
Container(
height: 50,
child: ElevatedButton(
style: ElevatedButton.styleFrom(
primary: Colors.blue, // background
onPrimary: Colors.white,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.zero),
),
onPressed: () {},
child: Text("Button1"),
),
),
Expanded(
child: Container(
height: 100,
child: ElevatedButton(
style: ElevatedButton.styleFrom(
primary: Colors.green, // background
onPrimary: Colors.white,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.zero)),
onPressed: () {},
child: Text("Button2"),
),
),
)
],
),
);
}
}```
[1]: https://i.stack.imgur.com/CydR4.png
[2]: https://i.stack.imgur.com/1JifM.png
Container(
padding: EdgeInsets.all(8.0),
height: 100,
child: Row(
children: [
Expanded(
child: Container(
height: 100,
child: ElevatedButton(
onPressed: () {},
child: Text("Button1"),
),
)),
Container(
padding: EdgeInsets.only(left: 8.0),
height: 100,
child:
ElevatedButton(onPressed: () {}, child: Text("Button2")))
],
),
)
Container(
padding: EdgeInsets.all(8.0),
height: 100,
child: Row(
children: [
Expanded(
child: Container(
height: 100,
child: ElevatedButton(
onPressed: () {},
child: Text("Button1"),
),
),
),
Expanded(
child: Container(
padding: EdgeInsets.only(left: 8.0),
height: 100,
child: ElevatedButton(
onPressed: () {},
child: Text("Button2"),
),
),
)
],
),
)
FullCode
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
void main() {
WidgetsFlutterBinding.ensureInitialized();
runApp(MaterialApp(home: Mainwidget()));
}
class Mainwidget extends StatefulWidget {
const Mainwidget({Key? key}) : super(key: key);
#override
_MainwidgetState createState() => _MainwidgetState();
}
class _MainwidgetState extends State<Mainwidget> {
#override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Container(
padding: EdgeInsets.all(8.0),
height: 100,
child: Row(
children: [
Expanded(
child: Container(
height: 100,
child: ElevatedButton(
onPressed: () {},
child: Text("Button1"),
),
),
),
Expanded(
child: Container(
padding: EdgeInsets.only(left: 8.0),
height: 100,
child: ElevatedButton(
onPressed: () {},
child: Text("Button2"),
),
),
)
],
),
),
),
);
}
List<Widget> children() {
return [
Expanded(
child: Container(
height: 100,
child: ElevatedButton(
onPressed: () {},
child: Text("Button1"),
),
)),
Container(
padding: EdgeInsets.only(left: 8.0),
height: 100,
child:
ElevatedButton(onPressed: () {}, child: Text("Button2")))
];
}
}
You can either add persistentFooterButtons to the Scaffold like
Scaffold(
persistentFooterButtons: [
TextButton(),
TextButton()
]
)
Or in the view:
Column(
children: [
Expanded(child: yourContent), // To use max height space
Row(
children: [
Expanded(child: TextButton()),
Expanded(child: TextButton()),,
]
),
]
),
To give a different width you can add flex to the Expanded or use Flexible and add flex
Wrap both your buttons with Expanded so that they take same amount of width and fill the row.
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,
),
);
}
}
I am creating the tutorial screen in which the two views like:- one is should be in the center of the screen and another should at the bottom of the screen.
But my both view is not proper, please check the below images.
I have done some lines of the code to do it but the not getting the proper solution, please check below code once
import 'package:flutter/material.dart';
import 'package:page_indicator/page_indicator.dart';
import 'login_screen.dart';
class Tutorial extends StatefulWidget {
#override
State<StatefulWidget> createState() {
// TODO: implement createState
return _TutorialScreen();
}
}
class _TutorialScreen extends State<Tutorial> {
#override
Widget build(BuildContext context) {
return Container(
color: Colors.white,
child: Align(
alignment: Alignment.center,
child:Column(
children: <Widget>[
Container(
height: 250.0,
margin: EdgeInsets.only(left: 10.0,top: 40.0,right: 10.0),
child: PageIndicatorContainer(
pageView: PageView(
children: <Widget>[
Container(
color: Colors.red,
),
Container(
color: Colors.yellow,
),
Container(
color: Colors.blueAccent,
)
],
),
length: 3,
align: IndicatorAlign.bottom,
indicatorSpace: 5.0,
padding: EdgeInsets.all(10.0),
),
),
Container(
height: 80.0,
color: Colors.purple,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Container(
child: OutlineButton(
onPressed: () {
Navigator.of(context)
.push(MaterialPageRoute(builder: (context) => LoginScreen()));
},
textColor: Colors.white,
child: Text(
"Login",
style: TextStyle(color: Colors.white),
),
),
),
Container(
margin: EdgeInsets.only(left: 10.0),
child: RaisedButton(
onPressed: () {},
color: Colors.black54,
child:
Text("SignUp", style: TextStyle(color: Colors.white)),
),
),
],
),
)
],
)
),
);
}
}
Please check above code once and let me know once.
Use this to get required view
Stack(children: <Widget>[
Align(alignment: Alignment.center,
child: Container(width: 100, height: 100, color: Colors.redAccent,),),
Align(alignment: Alignment.bottomCenter,
child: Container(height: 100, color: Colors.purpleAccent,),)
],)
Put the bottom Container inside Align widget and use alignment: Alignment.bottomCenter .:
Align(
alignment: Alignment.bottomCenter,
child: Container(
height: 80.0,
color: Colors.purple,
child: Row(
... .... ... // other code
Thanks #Zulfiqar But It is not necessary to put the whole view inside the Stack widget and use the Align property with it.
We can also use the Expanded or flexible widget to come out from the problem.
We can also use the MediaQuery for it like below
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:page_indicator/page_indicator.dart';
class HomeScreen extends StatefulWidget {
#override
State<StatefulWidget> createState() {
// TODO: implement createState
return _HomeScreen();
}
}
class _HomeScreen extends State<HomeScreen> {
#override
void initState() {
// TODO: implement initState
super.initState();
}
#override
Widget build(BuildContext context) {
// TODO: implement build
return Material(
child:Align(
alignment: Alignment.center,
child:Column(
children: <Widget>[
Container(
height: MediaQuery.of(context).size.height*0.90, /////HERE I USED MEDIAQUERY FOR IT
child: PageIndicatorContainer(
child: PageView(
children: <Widget>[
Container(
color: Colors.red,
),
Container(
color: Colors.yellow,
),
Container(
color: Colors.blueAccent,
)
],
),
length: 3,
align: IndicatorAlign.bottom,
indicatorSpace: 5.0,
padding: EdgeInsets.all(10.0),
),
),
Container(
height: MediaQuery.of(context).size.height*0.10, ////HERE I USED MEDIAQUERY FOR IT
color: Colors.purple,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Container(
child: OutlineButton(
onPressed: () {
},
textColor: Colors.white,
child: Text(
"Login",
style: TextStyle(color: Colors.white),
),
),
),
Container(
margin: EdgeInsets.only(left: 10.0),
child: RaisedButton(
onPressed: () {},
color: Colors.black54,
child:
Text("SignUp", style: TextStyle(color: Colors.white)),
),
),
],
),
)
],
)
),
);
}
}
And for the pageView i have used this library page_indicator: ^0.3.0
And output from above code is as follow