Flutter App: Background doesn't change from black to teal - android-studio

I created a small application with two dice. It works perfectly like I wanted to do it. For the first time, I have a problem with changing the background color of this page. As you can see in my Code below, I chose the backgroundcolor "teal". I have no idea, why this Background doesn't change to "teal". On all the other pages of my App, the Backgroundcolor is "teal"
Can someone help me with this problem.
Here's the complete code of this page:
import 'package:flutter/material.dart';
import 'dart:math';
void main() {
return runApp(
MaterialApp(
home: Scaffold(
backgroundColor: Colors.teal,
body: DicePage(),
),
),
);
}
class DicePage extends StatefulWidget {
#override
_DicePageState createState() => _DicePageState();
}
class _DicePageState extends State<DicePage> {
int leftDiceNumber = 1;
int rightDiceNumber = 1;
void changeDiceFace() {
setState(() {
leftDiceNumber = Random().nextInt(6) + 1;
rightDiceNumber = Random().nextInt(6) + 1;
});
}
#override
Widget build(BuildContext context) {
return Center(
child: Column(
children: <Widget>[
Expanded(
child: Padding(
padding: const EdgeInsets.all(40.0),
child: FlatButton(
onPressed: () {
setState(() {
leftDiceNumber = Random().nextInt(6) + 1;
});
},
child: Image.asset('images/dice$leftDiceNumber.png'),
),
),
),
Expanded(
child: Padding(
padding: const EdgeInsets.all(40.0),
child: FlatButton(
onPressed: () {
changeDiceFace();
},
child: Image.asset('images/dice$rightDiceNumber.png'),
),
),
),
],
),
);
}
}

If you are using same background color for all screens would consider changing it via theme:
MaterialApp(
theme:ThemeData(scaffoldBackgroundColor: Colors.teal),
home: Scaffold(...

In your MaterialApp there is one method name ThemeData. You can set theme of your app through this. You can follow below code
void main() {
return runApp(
MaterialApp(
theme: ThemeData(
primarySwatch: Colors.teal,
),
home: Scaffold(
body: DicePage(),
),
),
);
}

I ran your codes except the images part and the background color shows correctly. I think you can check your images but not the codes.

Related

How to achieve coplanar card layout in flutter

I'm trying to achieve a coplanar/disallined card collection layout in flutter. This is on Card layout on material Design documentation https://imgur.com/miHhpFs
I''ve tried with a GridView.count layout, but can't figure out how to disalline items. I also found out that there are user created libraries like this https://pub.dev/packages/flutter_staggered_grid_view that can help with what I want to do, but I'd prefer an official solution since this layout is on the material design documentation.
I don't know what the "official solution" for creating this is, but I believe it would be something along the lines of "Create three list views with three scroll controllers, one of which is offset from the other two, and then sync up their scroll controllers, accounting for the offset."
I didn't know if this would work or not, so I created this dartpad in order to test it:
https://dartpad.dev/f9c8f00b78899d3c8c4a426d3466a8a3
Just in case the dartpad doesn't work, here is the code that I used:
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
debugShowCheckedModeBanner: false,
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: ScrollSync(),
);
}
}
class ScrollSync extends StatefulWidget {
#override
_ScrollSyncState createState() => _ScrollSyncState();
}
class _ScrollSyncState extends State<ScrollSync> {
CustomScrollController _controller1 =
CustomScrollController(keepScrollOffset: true);
CustomScrollController _controller2 = CustomScrollController(
initialScrollOffset: 150.0, keepScrollOffset: true);
CustomScrollController _controller3 =
CustomScrollController(keepScrollOffset: true);
#override
void initState() {
_controller1.addListener(() =>
_controller2.jumpToWithoutGoingIdleAndKeepingBallistic(
_controller1.offset, "1 listen 2"));
_controller1.addListener(() =>
_controller3.jumpToWithoutGoingIdleAndKeepingBallistic(
_controller1.offset, "1 listen 3"));
_controller2.addListener(() =>
_controller1.jumpToWithoutGoingIdleAndKeepingBallistic(
_controller2.offset, "2 listen 1"));
_controller2.addListener(() =>
_controller3.jumpToWithoutGoingIdleAndKeepingBallistic(
_controller2.offset, "2 listen 3"));
_controller3.addListener(() =>
_controller1.jumpToWithoutGoingIdleAndKeepingBallistic(
_controller3.offset, "3 listen 1"));
_controller3.addListener(() =>
_controller2.jumpToWithoutGoingIdleAndKeepingBallistic(
_controller3.offset, "3 listen 2"));
super.initState();
}
#override
void dispose() {
_controller1.dispose();
_controller2.dispose();
_controller3.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Scroll Sync"),
),
body: Row(
children: [
Flexible(
flex: 1,
child: ListView.builder(
controller: _controller1,
scrollDirection: Axis.vertical,
itemBuilder: (_, index) => Container(
color: Colors.blueGrey,
width: 150,
height: 300,
margin: EdgeInsets.all(10.0),
child: Center(
child: Text(
"$index",
textAlign: TextAlign.center,
style: Theme.of(context).textTheme.display2,
),
),
),
),
),
Flexible(
flex: 1,
child: ListView.builder(
controller: _controller2,
itemBuilder: (_, index) => Container(
height: 300,
color: Colors.blueGrey,
margin: EdgeInsets.all(10.0),
child: Center(
child: Text(
"$index",
style: Theme.of(context)
.textTheme
.display2
.copyWith(color: Colors.white),
),
),
),
),
),
Flexible(
flex: 1,
child: ListView.builder(
controller: _controller3,
itemBuilder: (_, index) => Container(
height: 300,
color: Colors.blueGrey,
margin: EdgeInsets.all(10.0),
child: Center(
child: Text(
"$index",
style: Theme.of(context)
.textTheme
.display2
.copyWith(color: Colors.black),
),
),
),
),
),
],
),
);
}
}
class CustomScrollController extends ScrollController {
CustomScrollController(
{double initialScrollOffset = 0.0,
keepScrollOffset = true,
debugLabel,
String controller})
: super(
initialScrollOffset: initialScrollOffset,
keepScrollOffset: keepScrollOffset,
debugLabel: debugLabel,
);
#override
_SilentScrollPosition createScrollPosition(
ScrollPhysics physics,
ScrollContext context,
ScrollPosition oldPosition,
) {
return _SilentScrollPosition(
physics: physics,
context: context,
oldPosition: oldPosition,
initialPixels: initialScrollOffset,
);
}
void jumpToWithoutGoingIdleAndKeepingBallistic(
double value, String controller) {
assert(positions.isNotEmpty, 'ScrollController not attached.');
for (_SilentScrollPosition position
in new List<ScrollPosition>.from(positions))
position.jumpToWithoutGoingIdleAndKeepingBallistic(value, controller);
}
}
class _SilentScrollPosition extends ScrollPositionWithSingleContext {
_SilentScrollPosition({
ScrollPhysics physics,
ScrollContext context,
ScrollPosition oldPosition,
double initialPixels,
}) : super(
physics: physics,
context: context,
oldPosition: oldPosition,
initialPixels: initialPixels,
);
void jumpToWithoutGoingIdleAndKeepingBallistic(
double value, String controller) {
print(controller);
print(value);
print(pixels);
if (controller[0] == "2") {
if (pixels + 150.0 != value) {
forcePixels(value - 150.0);
}
} else if (controller[9] == "2") {
if (pixels - 150.0 != value) {
forcePixels(value + 150.0);
}
} else if (pixels != value) {
forcePixels(value);
}
}
}

Visibility won't toggle in flutter?

I've got a gridView where each grid has a FlatButton inside it. The button is supposed to trigger the visibility for another button I have outside the GridView. I've set the state in onPressed to change the bool showCard for everytime the GridView button is pressed. In my print statement, it's saying that it's working, producing true and false each time the button is pressed, but it's not changing the visibility of the other button called 'CheckoutCard()'. Can anyone help me?
import 'package:flutter/material.dart';
import 'package:flutter/painting.dart';
import 'package:bee/Cards/Items%20Card.dart';
import 'package:bee/Constants/Constants.dart';
import 'package:bee/MerchantCategories/My Categories.dart';
import 'package:bee/MenuButtons/Color Changer.dart';
import 'package:bee/Cards/Checkout Card.dart';
import 'package:bee/main.dart';
import 'Basket Menu.dart';
class MyMenu extends StatefulWidget {
#override
_MyMenuState createState() => _MyMenuState();
}
class _MyMenuState extends State<MyMenu> {
// bool showCard = _MyButtonState().showCard;
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
brightness: Brightness.light,
leading: new IconButton(
icon: new Icon(Icons.arrow_back, color: Colors.black),
onPressed: () { Navigator.of(context).pop();},
),
backgroundColor: Colors.white,
title: Padding(
padding: const EdgeInsets.all(6.0),
child: Image(image: AssetImage('images/Merchants/My_Image.png'),),
),
elevation: 1.0,
centerTitle: true,
actions: <Widget>[
Padding(
padding: const EdgeInsets.only(right: 15.0),
child: IconButton(icon: Icon(Icons.shopping_basket, color: Colors.blue[800],),
onPressed: (){ Navigator.push(context, MaterialPageRoute(builder: (context){return BasketMenu();})); }
),
),
],
),
body: Stack(
children: <Widget>[
Flex(
direction: Axis.vertical,
children: <Widget>[
Expanded(
flex: 1,
child: Padding(
padding: const EdgeInsets.all(5.0),
child: Container(
child: ListView(children: <Widget>[
MyCategories(categoryText: Text('Restaurants', style: categoryTextStyle),),
MyCategories(categoryText: Text('Bars', style: categoryTextStyle),),
MyCategories(categoryText: Text('Games', style: categoryTextStyle),),
],
scrollDirection: Axis.horizontal,
),
),
),
),
Expanded(
flex: 10,
child: Container(
child: GridView.count(
crossAxisCount: 2,
children: <Widget>[
ItemsCard(
categoryName: Text('Fast Food', style: secondCategoryTextStyle,),
itemText: FastFoodText,
priceText: Text('£21.67', style: priceTextStyle,),
gridOutline: MyButton(
tile: GridTile(
child: FastFoodImage,
),
),
),
ItemsCard(
itemText: SnubbText,
priceText: Text('£44.95', style: priceTextStyle,),
gridOutline: MyButton(
tile: GridTile(
child: SnubbImage,
),
),
),
ItemsCard(
itemText: FreshText,
priceText: Text('£41.23', style: priceTextStyle,),
gridOutline: MyButton(
tile: GridTile(
child: FreshImage,
),
),
),
Container(),
],
),
),
),
],
),
Visibility(visible: _MyButtonState().showCard ? _MyButtonState().showCard : !_MyButtonState().showCard, child: CheckoutCard()),
],
),
);
}
}
class MyButton extends StatefulWidget {
#override
State<StatefulWidget> createState(){
return _MyButtonState();
}
MyButton({this.tile});
final GridTile tile;
bool isVisible = false;
int itemNumber = 0;
bool showCheckoutCard(){
return isVisible = !isVisible;
}
int itemCounter(){
return itemNumber++;
}
}
class _MyButtonState extends State<MyButton> {
bool changeColor = false;
static var myNewButtonClass = MyButton();
bool showCard = myNewButtonClass.isVisible;
#override
Widget build(BuildContext context) {
return FlatButton(
shape: Border(bottom: BorderSide(color: changeColor ? Colors.blue[800] : Colors.transparent, width: 3.0)),
child: widget.tile,
onPressed: (){
setState(() {
changeColor = !changeColor;
myNewButtonClass.itemCounter();
print(myNewButtonClass.itemCounter());
setState(() {
showCard = !showCard;
print(showCard);
});
});
},
);
}
}
You are calling the setState method inside your Button. I don't think it will change the state of your MyMenu widget. I would suggest you to change your Button as following:
class MyButton extends StatelessWidget {
final Color color;
final GridTile tile;
final VoidCallback onPressed;
const MyButton({Key key, this.color, this.tile, this.onPressed})
: super(key: key);
#override
Widget build(BuildContext context) {
return FlatButton(
shape: Border(bottom: BorderSide(color: color)),
child: tile,
onPressed: onPressed,
);
}
}
After that, you need to declare two variable in your MyMenu widget as follows:
class _MyMenuState extends State<MyMenu> {
bool changeColor = false;
bool showCard = false;
#override
Widget build(BuildContext context) {
yourBuildMethod()
In your MyMenu widget you can call button like this:
MyButton(
tile: GridTile(child: SnubbImage),
color: changeColor
? Colors.blue[800]
: Colors.transparent,
onPressed: () {
setState(() {
changeColor = !changeColor;
showCard = !showCard;
});
},
),
And now check your Visibility like this:
Visibility(
visible: showCard,
child: CheckoutCard(),
)
Now your variables are in your MyMenu widget and you are calling setState function in MyMenu widget. So it will be able to update the state of your widget. I hope this will be helpful for you.
To trigger a rebuild of your view based when changing the value of a variable you need to use setState.
Where you are are changing the value of the isVisible variable, you need to surround it with a setState:
setState(() {
isVisible = !isVisible;
});

How to create a simple google maps address search with autocomplete in flutter and get latitude and longitude?

I'm new at Flutter and I'm trying to build a simple google maps app. I've already implemented google maps to the app and it is running perfect.
But now I want to add google maps autocomplete and I can't find a simple tutorial or example that is focused on it.
I have a TextField and I want to show places and addresses below it according to what the user types.
After showing the results, I need to get its latitude and longitude to mark on the map. The code below represents my BottomSheet, that contains my TexField and need to implement some list below it after some written text.
void _settingModalBottomSheet(context) {
double statusBarHeight = MediaQuery.of(context).padding.top;
showModalBottomSheet(
context: context,
builder: (builder) {
return Container(
padding: EdgeInsets.only(top: statusBarHeight),
color: Colors.transparent,
child: Container(
height: MediaQuery.of(context).size.height,
decoration: BoxDecoration(
color: Colors.blueAccent,
borderRadius: BorderRadius.only(
topLeft: const Radius.circular(10.0), topRight: const Radius.circular(10.0))),
child: Column(
children: <Widget>[
Padding(
padding: const EdgeInsets.only(top: 8.0, left: 8.0, right: 8.0),
child: Container(
height: 50.0,
width: double.infinity,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10.0),
color: Colors.white
),
child: TextField(
textInputAction: TextInputAction.search,
decoration: InputDecoration(
hintText: "Para onde vamos?",
border: InputBorder.none,
contentPadding: EdgeInsets.only(left: 15.0, top: 15.0),
suffixIcon: IconButton(
icon: Icon(Icons.search),
onPressed: searchAndNavigate,
iconSize: 30.0,
)
),
onChanged: (val) {
setState(() {
searchAddr = val;
}
);
},
onSubmitted: (term) {
searchAndNavigate();
},
),
),
),
],
)
),
);
}
);
}
You can use flutter_google_places plugin which shows the places in the autocomplete list as you type it and also returns lat and long of the place/address selected.
===== Working code =======
Add flutter_google_places plugin and import it in your dart file.
Add geo_coder plugin and import it in same dart file. (Required to access geocoding services)
Generate google api key for your project.
main.dart:
void main() => runApp(MyApp());
const kGoogleApiKey = "Api_key";
GoogleMapsPlaces _places = GoogleMapsPlaces(apiKey: kGoogleApiKey);
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: demo(),
),
);
}
}
class demo extends StatefulWidget {
#override
demoState createState() => new demoState();
}
class demoState extends State<demo> {
#override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
alignment: Alignment.center,
child: RaisedButton(
onPressed: () async {
// show input autocomplete with selected mode
// then get the Prediction selected
Prediction p = await PlacesAutocomplete.show(
context: context, apiKey: kGoogleApiKey);
displayPrediction(p);
},
child: Text('Find address'),
)
)
);
}
Future<Null> displayPrediction(Prediction p) async {
if (p != null) {
PlacesDetailsResponse detail =
await _places.getDetailsByPlaceId(p.placeId);
var placeId = p.placeId;
double lat = detail.result.geometry.location.lat;
double lng = detail.result.geometry.location.lng;
var address = await Geocoder.local.findAddressesFromQuery(p.description);
print(lat);
print(lng);
}
}
}
Result:
When you tap on Find Address button, it opens new screen with built-in search app bar in which you can type address / place you are looking for which shows corresponding results in autocomplete list and prints lat and long of the place you selected.
lat: 52.3679843
lng: 4.9035614

Always show scrollbar - Flutter

I have a long text and I need to show the scrollbar by default when the user enters my page.
Currently, the bars not shown until the user click over the text and this, not good behavior because the user could leave the page without notice that there is some unread text.
My code:
return Scaffold(
body: Padding(
padding: const EdgeInsets.all(15.0),
child: Center(
child: Column(
children: <Widget>[
Image.asset(
"assets/images/logo.png",
height: 200.0,
),
SizedBox(
height: 40,
),
Expanded(
child: Scrollbar(
child: SingleChildScrollView(
child: Text("Long Text Here ...",
textDirection: TextDirection.rtl,
style: TextStyle(fontSize: 17.2),
),
),
),
),
SizedBox(
height: 50,
),
Row(
children: <Widget>[
Expanded(
child: RaisedButton(
child: Text("Continue"),
onPressed: () {
MaterialPageRoute route = MaterialPageRoute(
builder: (BuildContext context) => MainPage());
Navigator.of(context).push(route);
},
),
),
SizedBox(
width: 20.0,
),
RaisedButton(
child: Text("Close"),
onPressed: () {
exit(0);
},
),
],
)
],
),
),
),
);
}```
As of Flutter version 1.17, on Scrollbar you can set isAlwaysShown to true, but you must set the same controller for your Scrollbar and your SingleChildScrollView (and that applies to any other scrollable Widget as well).
Have in mind that, for the Scrollbar to be visible, there must be enough items to scroll. If there are not, the Scrollbar won't be shown.
Full working example:
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: MyWidget(),
),
);
}
}
class MyWidget extends StatefulWidget {
#override
_MyWidgetState createState() => _MyWidgetState();
}
class _MyWidgetState extends State<MyWidget> {
final _scrollController = ScrollController();
#override
Widget build(BuildContext context) {
return Scaffold(
body: Padding(
padding: const EdgeInsets.all(15.0),
child: Center(
child: Column(
children: <Widget>[
// ...
Expanded(
child: Scrollbar(
controller: _scrollController, // <---- Here, the controller
isAlwaysShown: true, // <---- Required
child: SingleChildScrollView(
controller: _scrollController, // <---- Same as the Scrollbar controller
child: Text(
"Long Text Here ...",
textDirection: TextDirection.rtl,
style: TextStyle(fontSize: 17.2),
),
),
),
),
// ...
],
),
),
),
);
}
}
As of v2.9.0-1.0, thumbVisiblity is the proper field to set.
Note you can set this globally for your app (or a certain subtree) using ScrollbarTheme:
return MaterialApp(
...
theme: ThemeData(
...
scrollbarTheme: ScrollbarThemeData(
thumbVisibility: MaterialStateProperty.all<bool>(true),
)
)
)
It's good to prefer themes for styling like this, so avoid doing more than once.
You'll still need to add a Scrollbar and Controller as described in other answers though.
Use draggable_scrollbar package. It provides a dragable scrollbar with option to make the scrollbar always visible. For example, you can use the following code
DraggableScrollbar.arrows(
alwaysVisibleScrollThumb: true, //use this to make scroll thumb always visible
labelTextBuilder: (double offset) => Text("${offset ~/ 100}"),
controller: myScrollController,
child: ListView.builder(
controller: myScrollController,
itemCount: 1000,
itemExtent: 100.0,
itemBuilder: (context, index) {
return Container(
padding: EdgeInsets.all(8.0),
child: Material(
elevation: 4.0,
borderRadius: BorderRadius.circular(4.0),
color: Colors.purple[index % 9 * 100],
child: Center(
child: Text(index.toString()),
),
),
);
},
),
);
'isAlwaysShown' is deprecated and shouldn't be used. Use thumbVisibility instead.
Example:
Scrollbar(
controller: ScrollController(),
thumbVisibility: true,
child: SingleChildScrollView(
child: Column(
thumbVisibility make true for show always scroll bar for list in scrollbar widget
Scrollbar(thumbVisibility: true,)
You can change the scrollbartheme to set flag isAlwaysShown true
scrollbarTheme: const ScrollbarThemeData(isAlwaysShown: true)

FittedBox and Text whitespace issue

I'm trying to make all Text(length varies) in a fixed width box to fit and I want them to look at the same size as the longest word's size when FittedBox applied. So What I'm doing to achieve that is filling the rest of the word with empty space to match the length to the longest word. But that doesn't quite work as you see in the following image:
Here is the code:
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,
),
routes: {
'/': (context) => HomePage(),
},
);
}
}
class HomePage extends StatelessWidget {
final String padding = " " * 5;
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Home'),
),
body: Center(
child: Container(
color: Colors.red,
height: 100.0,
width: 100.0,
padding: const EdgeInsets.all(8.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Center(
child: FittedBox(
fit: BoxFit.scaleDown,
child: Text(
"${padding}Demo$padding",
textAlign: TextAlign.center,
style: TextStyle(color: Colors.black),
),
),
),
Icon(Icons.mic, size: 24.0),
],
),
),
),
);
}
}
Do you have any idea what is the issue here?
It's really strange, but it seems to work correctly if you remove alignment or set it to start. (What cause this bug - I still don't know)
child: Text('${padding}Demo$padding',
style: TextStyle(color: Colors.black, decoration: TextDecoration.underline),)
I've added decoration to see these spaces

Resources