Related
I was Trying to Have 3 Widgets in Single page using Column, but for some reason the alignment is not working...
#override
Widget build(BuildContext context) {
return Container(
height: double.infinity,
child: SwipeDetector(
onSwipeUp: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => CreditScreen()));
},
onSwipeDown: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => ManualScreen()));
},
child: Scaffold(
backgroundColor: DarkBlue,
resizeToAvoidBottomInset: false,
body: new Container(
height: double.infinity,
alignment: Alignment.center,
child: Column(
//mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
new Align(
alignment: Alignment.topCenter,
child: Image.asset('assets/swipe_down.gif',
scale: 5,
),
),
new Align(
alignment: Alignment.center,
child: Text("Menu Screen",
style: TextStyle(
color: Colors.white,
fontSize: 30.0,
fontWeight: FontWeight.bold,
),
//textAlign: TextAlign.center,
),
),
new Align(
alignment: Alignment.bottomCenter,
child: Image.asset('assets/swipe_up.gif',
scale: 5,
),
),
],
),
),
),
),
);
}
}
According to the above image, I want the swipe up widget at bottom and swipe down at the top while the text in center, I Tried Many wrapping of Widgets, but nothing seems to work...
Any Help...
try this:
Column(
//mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Image.asset('assets/swipe_down.gif',
scale: 5,
),
Expanded(
child: Text("Menu Screen",
style: TextStyle(
color: Colors.white,
fontSize: 30.0,
fontWeight: FontWeight.bold,
),
//textAlign: TextAlign.center,
),
),
Image.asset('assets/swipe_up.gif',
scale: 5,
),
],
),
You can use Center widget for aligning widgets in center along with padding widget for giving spaces between the widgets.
Scaffold(
backgroundColor: Colors.black,
resizeToAvoidBottomInset: false,
body: new Container(
height: double.infinity,
alignment: Alignment.center,
child:
Center(
child: Column(
children: <Widget>[
Padding(
padding: EdgeInsets.only(top:30),
child: Image.asset('assets/swipe_down.gif'),
),
Padding(
padding: EdgeInsets.only(top:80),
child:
Text("Menu Screen",
style: TextStyle(
color: Colors.white,
fontSize: 30.0,
fontWeight: FontWeight.bold
),
),
),
Padding(
padding: EdgeInsets.only(top:80),
child: Image.asset('assets/swipe_up.gif'),
),
],
),
),
),
),
i'm working on project for my university project and i'm having a problem.
First, i wanna add a back to my onboarding screen but i already use align for "next" on the bottom right while i want the back in the bottom left
Second, i wanna make the title (welcome,purpose,creator) in the middle, but i cannot put it in the center because i'm using a sizedbox
Third, i want the onboarding screen to only appear once, so when a user who have open it won't see it again (basically the first time opening, onboardingscreen but the second time straight to homepage)
sorry for my english
photo if you wanna visualize:
Photo
Here are the code:
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import '../home_screen.dart';
class Onboarding extends StatefulWidget {
#override
_OnboardingScreen createState() => _OnboardingScreen();
}
class _OnboardingScreen extends State<Onboarding> {
final int _numPages = 3;
final PageController _pageController = PageController(initialPage: 0);
int _currentPage = 0;
List<Widget> _buildPageIndicator() {
List<Widget> list = [];
for (int i = 0; i < _numPages; i++) {
list.add(i == _currentPage ? _indicator(true) : _indicator(false));
}
return list;
}
Widget _indicator(bool isActive) {
return AnimatedContainer(
duration: Duration(milliseconds: 150),
margin: EdgeInsets.symmetric(horizontal: 8.0),
height: 8.0,
width: isActive ? 24.0 : 16.0,
decoration: BoxDecoration(
color: isActive ? Colors.white : Color(0xFF7B51D3),
borderRadius: BorderRadius.all(Radius.circular(12)),
),
);
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: AnnotatedRegion<SystemUiOverlayStyle>(
value: SystemUiOverlayStyle.light,
child: Container(
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
stops: [0.1, 0.4, 0.7, 0.9],
colors: [
Colors.black,
Color(0xff112339),
Color(0xff112339),
Colors.black,
],
),
),
child: Padding(
padding: EdgeInsets.symmetric(vertical: 40.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
Container(
alignment: Alignment.centerRight,
child: FlatButton(
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => HomePage()),
);
},
child: Text(
'Skip',
style: TextStyle(
color: Colors.white,
fontSize: 20.0,
),
),
),
),
Container(
height: 600.0,
child: PageView(
physics: ClampingScrollPhysics(),
controller: _pageController,
onPageChanged: (int page) {
setState(() {
_currentPage = page;
});
},
children: <Widget>[
Padding(
padding: EdgeInsets.only(top:70.0,left: 40.0,right: 40.0,),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Center(
child: Image(
image: AssetImage(
'assets/images/Logo.png',
),
height: 120.0,
width: 120.0,
),
),
SizedBox(height: 50.0),
Text(
'Welcome',
style: TextStyle(
color: Colors.white,
fontSize: 21.0,
height: 1.5,
),
),
SizedBox(height: 30.0),
Text(
'Welcome to Moviez, the place where you will spend your time magically',
style: TextStyle(
color: Colors.white,
fontSize: 16.0,
height: 1.2,
fontFamily: 'Raleway',
),
),
],
),
),
Padding(
padding: EdgeInsets.only(top:70.0,left: 40.0,right: 40.0,),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Center(
child: Image(
image: AssetImage(
'assets/images/Logo.png',
),
height: 120.0,
width: 120.0,
),
),
SizedBox(height: 50.0),
Text(
'Purpose',
style: TextStyle(
color: Colors.white,
fontSize: 21.0,
height: 1.5,
),
),
SizedBox(height: 30.0),
Text(
'This App is for educational purposes only',
style: TextStyle(
color: Colors.white,
fontSize: 16.0,
height: 1.2,
),
),
],
),
),
Padding(
padding: EdgeInsets.only(top:70.0,left: 40.0,right: 40.0,),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Center(
child: Image(
image: AssetImage(
'assets/images/Logo.png',
),
height: 120.0,
width: 120.0,
),
),
SizedBox(height: 50.0),
Text(
'Creator',
style: TextStyle(
color: Colors.white,
fontSize: 21.0,
height: 1.5
),
),
SizedBox(height: 30.0),
Text(
'Adela, Caroline, Cordellya, David, Valentino',
style: TextStyle(
color: Colors.white,
fontSize: 16.0,
height: 1.2,
),
),
],
),
),
],
),
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: _buildPageIndicator(),
),
_currentPage != _numPages - 1
? Expanded(
child: Align(
alignment: FractionalOffset.bottomRight,
child: FlatButton(
onPressed: () {
_pageController.nextPage(
duration: Duration(milliseconds: 500),
curve: Curves.ease,
);
},
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Text(
'Next',
style: TextStyle(
color: Colors.white,
fontSize: 22.0,
),
),
SizedBox(width: 10.0),
Icon(
Icons.arrow_forward,
color: Colors.white,
size: 30.0,
),
],
),
),
),
)
: Text(''),
],
),
),
),
),
bottomSheet: _currentPage == _numPages - 1
? Container(
height: 100.0,
width: double.infinity,
color: Colors.white,
child: GestureDetector(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => HomePage()),
);
},
child: Center(
child: Padding(
padding: EdgeInsets.only(bottom: 30.0),
child: Text(
'Get started',
style: TextStyle(
color: Color(0xFF5B16D0),
fontSize: 20.0,
fontWeight: FontWeight.bold,
),
),
),
),
),
)
: Text(''),
);
}
}
here is my main.dart
import 'package:flutter/material.dart';
import 'package:movie_app/screens/home_screen/widgets/onboard.dart';
import 'screens/home_screen/home_screen.dart';
void main() {
runApp(MyApp());
Paint.enableDithering = true;
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Movie App',
theme: ThemeData(
primarySwatch: Colors.blue,
iconTheme: IconThemeData(
color: Colors.white,
),
textTheme: ThemeData.light().textTheme.copyWith(
bodyText1: TextStyle(
// fontFamily: 'OpenSans',
// fontWeight: FontWeight.bold,
fontSize: 22,
color: Colors.white,
),
button: TextStyle(
color: Colors.white,
),
),
appBarTheme: AppBarTheme(
iconTheme: IconThemeData(color: Colors.white),
actionsIconTheme: IconThemeData(size: 30),
)),
home: Onboarding(),
);
}
}
Answering your first point:
Assuming that you want the "back" button on the same row as the "next" one, I would suggest you edit your Row widget as follows.
Row(children: [
Icon(Icons.arrow_back),
Text('Back'),
Spacer(),
Text('Next'),
Icon(Icons.arrow_forward),
])
I've used two Text widgets just to show you how it would look. In your app, you can use two different buttons with different text and different onTap or onPressed methods. You can check the Button section of this page to learn more about the different buttons available in Flutter.
Second: I think that all you have to do to have your titles centered on the screen is to change the crossAxisAlignment property of the related Column form CrossAxisAlignment.start to CrossAxisAlignment.center
I want to add a button in the right side of the card,by default the button's color should be green and while tapping on it, there should be a popup box opened and the color of the button would turn to red.
1-The button's color should be green while the listView willed be plotted.
2-Then when I am tapping on the button, a dialog box should be opened with a input textField.
3-After I am inserting any text and pressing the submit button of the popup box, the entered text will be printed on the console.
4-Then the color of the button would turn to red from green.
As I am new to flutter, please help me to get this.
Here is my Code:
body: ListView.builder(
itemCount: patients.length,
itemBuilder: (context, index) {
return Padding(
padding: const EdgeInsets.all(9.0),
child: SizedBox(
height: 120,
child: Card(
elevation: 5.0,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
child: Row(
children: [
Expanded(
flex: 3,
child: Container(
child: CircleAvatar(
backgroundImage: NetworkImage(patients[index].imgPath),
radius: 50.0,
),
),
),
Expanded(
flex: 5,
child: Container(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(patients[index].name, style: TextStyle(
fontSize: 23.0,
fontWeight: FontWeight.bold,
color: Colors.black87
),),
SizedBox(
height: 20,
),
Text(patients[index].completedSession.toString() +'/'+ patients[index].totalSession.toString(),
style: TextStyle(
fontSize: 18.0,
fontWeight: FontWeight.bold,
color: Colors.black54
),),
],
),
),
),
Expanded(
flex: 2,
child: Container(
child: RaisedButton(
),
),
),
],
),
),
),
),
),
);
},
),
You should use CrossAxisAlignment.stretch for your Row:
import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
void main() {
runApp(
MaterialApp(
title: 'Flutter Demo',
home: Scaffold(
body: MyWidget(),
),
),
);
}
class MyWidget extends HookWidget {
#override
Widget build(BuildContext context) {
final pushed = useState(false);
return AspectRatio(
aspectRatio: 3,
child: Card(
elevation: 5.0,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
CircleAvatar(
backgroundImage: NetworkImage(
'https://upload.wikimedia.org/wikipedia/commons/5/54/RowanAtkinsonMar07.jpg',
),
radius: 50.0,
),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Mister B.',
style: TextStyle(
fontSize: 23.0,
fontWeight: FontWeight.bold,
color: Colors.black87),
),
SizedBox(
height: 20,
),
Text(
'0/42',
style: TextStyle(
fontSize: 18.0,
fontWeight: FontWeight.bold,
color: Colors.black54),
),
],
),
),
RaisedButton(
onPressed: () {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(
pushed.value ? 'Button unpushed' : 'Button pushed'),
),
);
pushed.value = !pushed.value;
},
color: pushed.value ? Colors.red : Colors.green,
child: Text('OK'),
),
],
),
),
),
);
}
}
So I am trying to learn BLoC pattern and apply it to my weather app. The thing is the UI is kinda big, there are a lot of Columns and Rows. So I'm confused about where to put BlocBuilder.
Or maybe this whole Container should be returned by one BLoC event? This is basically the main and only screen of the app for now.
class WeatherMainScreen extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Container(
color: kBackgroundColor,
child: SafeArea(
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Container(
margin: EdgeInsets.only(
bottom: 30,
top: 15,
left: 30,
right: 30,
),
child: Column(
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Text(
'Today 28. apr',
style: TextStyle(
color: kAccentColor,
fontSize: 18,
fontWeight: FontWeight.w400,
),
),
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
MenuSearchButton(
boxSize: 60,
onPressed: () => print('search pressed'),
content: Icon(
Icons.search,
color: Colors.white,
size: 30,
),
),
MenuSearchButton(
boxSize: 60,
onPressed: () => print('menu pressed'),
content: Icon(
Icons.menu,
color: Colors.white,
size: 30,
),
),
],
),
],
),
Container(
padding: EdgeInsets.symmetric(vertical: 20.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
'16',
style: TextStyle(
color: Colors.white,
fontSize: 100,
),
),
Container(
padding: EdgeInsets.only(left: 10.0),
child: Row(
children: <Widget>[
Icon(
Icons.cloud,
color: Colors.white,
size: 25.0,
),
SizedBox(width: 15.0),
Text(
'Raining',
style: TextStyle(
color: Colors.white,
fontSize: 18,
),
),
],
),
),
],
),
),
],
),
),
Column(
children: <Widget>[
Container(
margin: EdgeInsets.only(
bottom: 30,
top: 15,
left: 60,
right: 60,
),
child: Text(
'Put on your coat, and don\'t forget the umbrella.',
textAlign: TextAlign.center,
style: TextStyle(
color: Colors.white,
fontSize: 25,
),
),
),
Divider(
color: kAccentColor,
),
Container(
margin: EdgeInsets.only(
bottom: 30,
top: 15,
left: 30,
right: 30,
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
DetailedCard(
header: 'HUMIDITY',
headerColor: kAccentColor,
text: '87%',
textColor: Colors.white,
),
DetailedCard(
header: 'WIND M/S',
headerColor: kAccentColor,
text: '4,1',
textColor: Colors.white,
),
DetailedCard(
header: 'FEELS LIKE',
headerColor: kAccentColor,
text: '18',
textColor: Colors.white,
),
],
),
),
],
),
],
),
),
);
}
}
Just separate your UI based on different possible states. Then use BlocBuilder and check states. Finally render UI for respective state.
You can check this video
You can definitely have multiple BlocBuilder. To make it simpler, let's take a look at this Counter example app.
I put this one wrapping a Column with 2 Text Widgets even though the only one supposed to be changing is the second Text Widget. (Not a good thing)
class CounterPage extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Counter')),
body: BlocBuilder<CounterBloc, int>(
builder: (context, count) {
return Center(
child: Column(
children: <Widget>[
Text(
'You have pressed this many',
style: TextStyle(fontSize: 24.0),
),
Text(
'$count',
style: TextStyle(fontSize: 24.0),
),
],
),
);
},
),
);
}
}
In this snippet, I put the BlocBuilder pricisely wrapping the only Widget that is changing on state changes. And if you ask Where in my code should I put BLoC builder? This approach is better because there won't be unnecessary Widget rebuilds happen.
class CounterPage extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Counter')),
body: Center(
child: Column(
children: <Widget>[
Text(
'You have pressed this many',
style: TextStyle(fontSize: 24.0),
),
BlocBuilder<CounterBloc, int>(
builder: (context, count) {
return Text(
'$count',
style: TextStyle(fontSize: 24.0),
);
},
),
],
),
),
);
}
}
And for can I have more of them?, absolutely.
class CounterPage extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: BlocBuilder<CounterBloc, int>(
builder: (context, count) {
return AppBar(title: Text('$count'));
},
),
body: Center(
child: Column(
children: <Widget>[
Text(
'You have pressed this many',
style: TextStyle(fontSize: 24.0),
),
BlocBuilder<CounterBloc, int>(
builder: (context, count) {
return Text(
'$count',
style: TextStyle(fontSize: 24.0),
);
},
),
],
),
),
);
}
}
Current output:
Expected output:
Code:
SizedBox(
width: 380,
height: 180,
child: Swiper(
itemCount: items.length,
itemBuilder: (context, index) {
return Column(
children: <Widget>[
Expanded(
child: Card(
child: ListTile(
title: Text(
'${items[index].title}',
),
subtitle: Text(
'${items[index].body}',
),
trailing: Column(
children: <Widget>[
CircleAvatar(
backgroundColor: HexColor("#0087a8"),
child: IconButton(
icon: Icon(Icons.add),
],
),
),
),
)
],
);
},
viewportFraction: 0.8,
scale: 0.9,
control: SwiperControl(color: Colors.white),
),
);
I am unable to create the icon button to be that way. As when i put in padding, it says that the pixels overflowed. I need to get the add button on the bottom right hand side.
As already pointed out, you shouldn't use a ListTile for this, as you want to use more than just a title, subtitle for your content.
The reason I've picked a Stack over a Column here, is that it allows you to safely use it in different size screens whilst assuring the view won't overflow. With Column, it would use the button diameter as the whole space to use (vertically), even though it is restrict to the right side of the box.
I believe this is what you're looking for.
class MyListTile extends StatelessWidget {
const MyListTile({
Key key,
}) : super(key: key);
#override
Widget build(BuildContext context) {
return Container(
height: 180.0,
color: const Color(0xff0087a8),
child: Container(
padding: const EdgeInsets.all(20.0),
margin: const EdgeInsets.all(10.0),
decoration: BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(10.0)),
color: const Color.fromRGBO(19, 12, 117, 1.0),
),
child: Stack(
children: <Widget>[
Text(
'EUR - USD',
style: Theme.of(context).textTheme.display2.copyWith(
color: Colors.white,
fontWeight: FontWeight.bold,
),
),
Align(
alignment: Alignment.centerLeft,
child: Text(
'Forex',
style: TextStyle(color: Colors.white, fontSize: 20.0),
),
),
Align(
alignment: Alignment.bottomRight,
child: FloatingActionButton(
backgroundColor: const Color(0xff0087a8),
onPressed: () {},
child: Icon(
Icons.add,
color: Colors.white,
size: 50.0,
),
),
)
],
),
),
);
}
}
Try this code
Container(
height: 180,
width: double.infinity,
child: Card(
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
'EUR/USD',
style: TextStyle(fontSize: 40),
),
Text('FOREX', style: TextStyle(fontSize: 20)),
],
),
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
CircleAvatar(
backgroundColor: Colors.blueAccent,
child: IconButton(
onPressed: () {
print('On Pressed');
},
icon: Icon(Icons.add),
)),
],
)
],
),
),
),
)
Use custom widget for list item OR column from below code for single view. To align left and right you have to put your view in 'Align' as in below -
class _ItemsState extends State<Items> {
#override
Widget build(BuildContext context) {
// TODO: implement build
return Scaffold(
body: SizedBox(
width: 380,
height: 160,
child: Card(
child: ListView.builder(
itemCount: 1,
itemBuilder: (context, index) {
return
Padding(padding: EdgeInsets.all(10.0),child: Column(children: <Widget>[
Align(
alignment: Alignment.centerLeft,
child: Column(children: <Widget>[
Text(
'title',
style: TextStyle(fontSize: 20.0 , fontWeight: FontWeight.bold,),
),
Text(
'body',
style: TextStyle(fontSize: 14.0), )
]),
),
Align(
alignment: Alignment.centerRight,
child: CircleAvatar(
maxRadius: 20.0,
backgroundColor: Colors.blueGrey,
child: IconButton(
icon: Icon(Icons.add,
color: Colors.white,),
))
)
]));
}))));
}
}