Is there any way to make such design in Flutter - flutter-layout

As shown in the below Image.
I want an image at the bottom of the stack, a container above it and a transparent text widget above them. I'm unable to figure out any solution, please help!

Found a solution, works like a charm
import 'dart:typed_data';
import 'dart:ui' as ui;
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter/services.dart';
class Penumbra extends StatefulWidget {
Penumbra({Key key}) : super(key: key);
#override
_PenumbraState createState() => _PenumbraState();
}
class _PenumbraState extends State<Penumbra> {
#override
Widget build(BuildContext context) {
Size size = MediaQuery.of(context).size;
return Scaffold(
body: Stack(
children: [
Row(
children: [
Container(
width: size.width / 2,
height: double.maxFinite,
color: Color(0xff181818),
),
Container(
width: size.width / 2,
height: double.maxFinite,
color: Colors.white,
)
],
),
SingleChildScrollView(
child: Column(
children: [
Container(
height: size.height,
),
ImageShaderWidget(),
Container(
height: size.height,
),
],
),
),
],
));
}
}
class ImageShaderWidget extends StatelessWidget {
#override
Widget build(BuildContext context) => Container(
child: FutureBuilder<TextStyle>(
future: loadImage(
TextStyle(fontSize: 104.0, fontWeight: FontWeight.w900)),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return Center(child: CircularProgressIndicator());
} else {
return Text(
"Penumbra",
style: snapshot.data,
);
}
},
),
);
Future<TextStyle> loadImage(TextStyle textStyle) async {
final imageBytes = await rootBundle.load('../assets/images/background.jpg');
ui.Image img = await decodeImageFromList(imageBytes.buffer.asUint8List());
Float64List matrix4 = new Matrix4.identity().storage;
return textStyle.copyWith(
foreground: Paint()
..shader =
ImageShader(img, TileMode.mirror, TileMode.mirror, matrix4));
}
}

Related

What is the alternative of using setState() in flutter?

I am implementing Curved_Navigation_Bar in my Flutter poject and I am not using any class(i.e. Stateful / Stateless). I want to change the state of the icons that are in my curved_navigation_bar, means I want that animation effect on my navigation bar. Because the respective pages of those icons are navigating but not those items. No matter on which icon I click, it is still showing that first icon only. The animation/interpolation of icons is not happening.
As I am not using any Stateful/Stateless class, so I am not using Scaffold. Inside Scaffold we can change the state of the current object using setState(() { }).
So how can I change the state of my navigation bar?
Here is my code below:
navigation_bar.dart
import 'package:flutter/material.dart';
import 'package:curved_navigation_bar/curved_navigation_bar.dart';
import 'package:thehelpdesk/components/home/history.dart';
import 'package:thehelpdesk/components/home/home.dart';
import 'package:thehelpdesk/components/home/menu.dart';
import 'package:thehelpdesk/components/home/notification.dart';
import 'package:thehelpdesk/components/home/person.dart';
int currentIndex = 0 ;
Widget navBarSection(Color color, Color btnColor, BuildContext context) {
return CurvedNavigationBar(
index: 0,
items:
[
Icon(Icons.home, color: Colors.white),
Icon(Icons.notifications, color: Colors.white),
Icon(Icons.menu, color: Colors.white),
Icon(Icons.history, color: Colors.white),
Icon(Icons.person, color: Colors.white),
],
color: color,
buttonBackgroundColor: btnColor,
animationCurve: Curves.easeInCubic,
animationDuration: Duration(milliseconds: 600),
onTap: (index) {
if(currentIndex == 0){
Navigator.of(context).push(MaterialPageRoute(builder: (context) => HomePage()));
currentIndex = index ;
}
if(currentIndex == 1){
Navigator.of(context).push(MaterialPageRoute(builder: (context) => NotificationPage()));
currentIndex = index ;
}
if(currentIndex == 2){
Navigator.of(context).push(MaterialPageRoute(builder: (context) => MenuPage()));
currentIndex = index ;
}
if(currentIndex == 3){
Navigator.of(context).push(MaterialPageRoute(builder: (context) => HistoryPage()));
currentIndex = index ;
}
if(currentIndex == 4){
Navigator.of(context).push(MaterialPageRoute(builder: (context) => PersonPage()));
currentIndex = index ;
}
}
);
One of the pages I want to navigate on tapping a icon:
home.dart
import 'package:flutter/material.dart';
import 'package:thehelpdesk/widgets/appbar.dart';
import 'package:thehelpdesk/widgets/navigation_bar.dart';
class HomePage extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: aapBarSection('Home', Colors.blueAccent[700], context),
bottomNavigationBar: navBarSection(
Colors.blueAccent[700],
Colors.blueAccent[700],
context
),
);
}
}
Another page on tapping the 2nd icon:
notification.dart
import 'package:flutter/material.dart';
import 'package:thehelpdesk/widgets/appbar.dart';
import 'package:thehelpdesk/widgets/navigation_bar.dart';
class NotificationPage extends StatefulWidget {
#override
_NotificationPageState createState() => _NotificationPageState();
}
class _NotificationPageState extends State<NotificationPage> {
final message = [
'Hi Xyz,your invoice for It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged.',
'Hi Xyz, Agility Rehab Care wishing you a very happy birthday! for It has survived not only five centuries, but also the leap remaining essentially unchanged.',
'Hi Xyz, From our Agility Rehab Care you are being reminded that you have an appointment with us on this Friday.',
'Hi Xyz, This is a reminder for you from Agility Rehab Care It is a long established fact that a reader will be distracted by the readable content of a page when looking at its layout.',
];
final images = [
'assets/images/Invoice.png',
'assets/images/cake.png',
'assets/images/calender.png',
'assets/images/Reminder.png'
];
String date = '22/02/2021';
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: aapBarSection('Notification',Colors.blueAccent[700],context),
bottomNavigationBar: navBarSection(
Colors.blueAccent[700],
Colors.blueAccent[700],
context
),
body: ListView.builder(
itemCount: message.length,
itemBuilder: (context, index) {
return Padding(
padding: const EdgeInsets.fromLTRB(10, 10, 10, 10),
child: SizedBox(
height: 200,
child: Card(
elevation: 5.0,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10.0),
),
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
child: Column(
children: [
Flexible(
flex: 7,
child: Container(
child: Row(
children: [
Expanded(
flex: 2,
child: Container(
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage(
images[index]))),
),
),
Expanded(
flex: 8,
child: Container(
child: Text(message[index]),
),
),
],
),
),
),
Flexible(
flex: 3,
child: Padding(
padding: const EdgeInsets.fromLTRB(10, 10, 10, 10),
child: Container(
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [Text(date)],
),
),
),
),
],
),
),
)),
),
);
})
);
}
}
The short answer is that just add currentIndex as one of the parameter inside your navBarSection.
navigation_bar.dart
Widget navBarSection(
int currentIndex,
Color color,
Color btnColor,
BuildContext context,
) {
return CurvedNavigationBar(
index: currentIndex,
items: [
Icon(Icons.home, color: Colors.white),
Icon(Icons.notifications, color: Colors.white),
Icon(Icons.menu, color: Colors.white),
Icon(Icons.history, color: Colors.white),
Icon(Icons.person, color: Colors.white),
],
color: color,
buttonBackgroundColor: btnColor,
animationCurve: Curves.easeInCubic,
animationDuration: Duration(milliseconds: 600),
onTap: (index) {
if (currentIndex == 0) {
Navigator.of(context)
.push(MaterialPageRoute(builder: (context) => HomePage()));
currentIndex = index;
}
if (currentIndex == 1) {
Navigator.of(context).push(
MaterialPageRoute(builder: (context) => NotificationPage()));
currentIndex = index;
}
if (currentIndex == 2) {
Navigator.of(context)
.push(MaterialPageRoute(builder: (context) => MenuPage()));
currentIndex = index;
}
if (currentIndex == 3) {
Navigator.of(context)
.push(MaterialPageRoute(builder: (context) => HistoryPage()));
currentIndex = index;
}
if (currentIndex == 4) {
Navigator.of(context)
.push(MaterialPageRoute(builder: (context) => PersonPage()));
currentIndex = index;
}
});
}
Inside home.dart, just pass the currentIndex of the page.
home.dart
class HomePage extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: aapBarSection('Home', Colors.blueAccent[700], context),
bottomNavigationBar: navBarSection(
0,
Colors.blueAccent[700],
Colors.blueAccent[700],
context,
),
);
}
}
This should solve your problem but as you can see, this is not the best way to implement the bottomnavigationbar and widget due to:
You will lose the animation that the package provided.
It does not comply with the bottom navigation behavior since it will navigate to a new page instead of replacing it.
To solve this, create a new stateful widget,as for this example, I called it main_page.dart.
main_page.dart
class MainPage extends StatefulWidget {
#override
_MainPageState createState() => _MainPageState();
}
class _MainPageState extends State<MainPage> {
int _currentIndex = 0;
List<Widget> _pages = [
HomePage(),
NotificationPage(),
MenuPage(),
HistoryPage(),
PersonPage(),
];
#override
Widget build(BuildContext context) {
return Scaffold(
body: _pages.elementAt(_currentIndex),
bottomNavigationBar: CurvedNavigationBar(
backgroundColor: Colors.blueAccent,
items: [
Icon(Icons.home, color: Colors.white),
Icon(Icons.notifications, color: Colors.white),
Icon(Icons.menu, color: Colors.white),
Icon(Icons.history, color: Colors.white),
Icon(Icons.person, color: Colors.white),
],
color: Colors.blueAccent[700],
buttonBackgroundColor: Colors.blueAccent[700],
animationCurve: Curves.easeInCubic,
animationDuration: Duration(milliseconds: 600),
onTap: (index) {
setState(() {
_currentIndex = index;
});
},
),
);
}
}
Called the the main_page.dart inside your main.dart.
main.dart
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: MainPage(),
);
}
}
lastly, remove any bottomNavigationBar from home,history,menu,notification,and person page.
The result is

How to return flip cards to their original position from a widget in another dart file?

I'm relatively new to Flutter and have tried to find similar postings to help me but haven't had any luck in getting them to work for me unfortunately. I have an Android Studio program that's basically a game which involves a grid of flip cards. I have the flip cards in one dart file and the app bar in another. I have an iconbutton on the app bar which currently reduces the point count to zero, but I would also like for it to flip all of the flip cards back to their original positions when pressed. I have a global variable called resetBool that I've been trying to use, something like if resetBool == true then toggleCard() maybe. I think I might need to use a key but am having trouble implementing one properly.
Here is the code in the file which contains my appbar:
import 'package:flip_card/flip_card.dart';
import 'package:flutter/material.dart';
import 'gridone.dart' as gridone;
import 'globalVariables.dart';
import 'statenames.dart';
int count;
StateNames stateObject = new StateNames();
class Home extends StatefulWidget {
#override
_HomeState createState() => _HomeState();
}
class _HomeState extends State<Home>with SingleTickerProviderStateMixin {
TabController controller;
#override
void initState() {
controller = new TabController(length: 1, vsync: this);
super.initState();
}
#override
void dispose() {
controller.dispose();
super.dispose();
}
void changeCount() {
setState(() {
counter += 1;
});
}
void decreaseCount() {
setState(() {
counter -= 1;
});
}
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title:new Text("License plate game"),
backgroundColor: Colors.greenAccent,
actions: <Widget>[
IconButton(
icon: Icon(
Icons.autorenew,
color: Colors.white,
),
onPressed: () {
setState(() {
counter = 0;
resetBool = true;
});
},
),
Center(
child: Container(
padding: EdgeInsets.fromLTRB(20, 20, 20, 20),
child: Text('points: $counter', textAlign: TextAlign.center, style: TextStyle(fontSize: 15),
)
),
),
],
bottom: new TabBar(
controller: controller,
indicatorWeight: 5.0,
indicatorColor: Colors.green,
tabs: <Widget> [
new Tab(icon: new Icon(Icons.image),),
],
),
),
body: new TabBarView(
controller: controller,
children: <Widget>[
new gridone.GridOne(changeCount, decreaseCount),
],
)
);
}
}
And here is the code in the file which contains my flip cards:
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flip_card/flip_card.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'statenames.dart';
import 'globalVariables.dart';
import 'Home.dart';
import 'gridtwo.dart' as gridTwo;
StateNames stateObject = new StateNames();
Home homeObject = new Home();
class GridOne extends StatefulWidget {
final Function updateCounter;
final Function decreaseCount;
GridOne(this.updateCounter, this.decreaseCount);
#override
_GridOneState createState() => _GridOneState();
}
class _GridOneState extends State<GridOne>
with AutomaticKeepAliveClientMixin {
#override
bool get wantKeepAlive => true;
int points = 0;
#override
Widget build(BuildContext context) {
super.build(context);
return new Scaffold(
body: new Column(
children: <Widget> [
new Expanded(
child: GridView.count(
crossAxisCount: 5,
children: List.generate(52, (index){
return Card(
elevation: 0.0,
margin: EdgeInsets.only(left: 3.0, right: 3.0, top: 9.0, bottom: 0.0),
color: Color(0x00000000),
child: FlipCard(
direction: FlipDirection.HORIZONTAL,
speed: 1000,
//(resetBool == true) ? cardKey.currentState.toggleCard() : null,
onFlipDone: (status) {
setState(() {
(status)
? widget.decreaseCount()
: widget.updateCounter();
});
if (counter == 25) {
Fluttertoast.showToast(
msg: "You've got 25 states! Wow!",
toastLength: Toast.LENGTH_SHORT,
gravity: ToastGravity.BOTTOM_LEFT,
timeInSecForIosWeb: 1,
backgroundColor: Colors.red,
textColor: Colors.white,
fontSize: 16.0);
};
print(counter);
},
front: Container(
decoration: BoxDecoration(
color: Color(0xFF006666),
borderRadius: BorderRadius.all(Radius.circular(8.0)),
),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
FittedBox(fit:BoxFit.fitWidth,
child: Text(stateObject.stateNames[index], style: TextStyle(fontFamily: 'Architects Daughter', color: Colors.white), )
//Theme.of(context).textTheme.headline
),
Text('',
style: Theme.of(context).textTheme.body1),
],
),
),
back: Container(
decoration: BoxDecoration(
color: Color(0xFF006666),
borderRadius: BorderRadius.all(Radius.circular(8.0)),
),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Image(image: AssetImage(stateObject.licensePlatePaths[index])),
//Text('',
//style: Theme.of(context).textTheme.body1),
],
),
),
),
);
})
)
)
]
),
);
}
}
The solution is to use currentState.toggleCard(); for the cards that are facing Back when the IconButton is clicked.
Basically, what I did is I gave keys to each card at initState method.
List<GlobalKey<FlipCardState>> cardKeys = [];
#override
void initState() {
List.generate(52, (index) {
cardKeys.add(GlobalKey<FlipCardState>());
});
super.initState();
}
Don't forget to put the key to widget
FlipCard(key: cardKeys[index], ... )
Then, call resetCards method below when the button is clicked. If the card is facing back then toggle logic.
void resetCards() {
cardKeys.forEach((element) {
if (!element.currentState.isFront) {
element.currentState.toggleCard();
}
});
setState(() {});
}
You need to call a method on the parent widget, that would be triggered in the child widget. For that, please check this stackoverflow link
Full working code:
import 'package:flutter/material.dart';
import 'package:flip_card/flip_card.dart';
import 'package:fluttertoast/fluttertoast.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
// This is the theme of your application.
//
// Try running your application with "flutter run". You'll see the
// application has a blue toolbar. Then, without quitting the app, try
// changing the primarySwatch below to Colors.green and then invoke
// "hot reload" (press "r" in the console where you ran "flutter run",
// or simply save your changes to "hot reload" in a Flutter IDE).
// Notice that the counter didn't reset back to zero; the application
// is not restarted.
primarySwatch: Colors.blue,
// This makes the visual density adapt to the platform that you run
// the app on. For desktop platforms, the controls will be smaller and
// closer together (more dense) than on mobile platforms.
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: Home(),
);
}
}
class Home extends StatefulWidget {
#override
_HomeState createState() => _HomeState();
}
class _HomeState extends State<Home> with SingleTickerProviderStateMixin {
TabController controller;
int counter = 0;
final GridOneController myController = GridOneController();
#override
void initState() {
controller = new TabController(length: 1, vsync: this);
super.initState();
}
#override
void dispose() {
controller.dispose();
super.dispose();
}
void changeCount() {
setState(() {
counter += 1;
});
}
void decreaseCount() {
setState(() {
counter -= 1;
});
}
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text("License plate game"),
backgroundColor: Colors.greenAccent,
actions: <Widget>[
IconButton(
icon: Icon(
Icons.autorenew,
color: Colors.white,
),
onPressed: () {
setState(() {
counter = 0;
myController.resetCards();
});
},
),
Center(
child: Container(
padding: EdgeInsets.fromLTRB(20, 20, 20, 20),
child: Text(
'points: $counter',
textAlign: TextAlign.center,
style: TextStyle(fontSize: 15),
)),
),
],
bottom: new TabBar(
controller: controller,
indicatorWeight: 5.0,
indicatorColor: Colors.green,
tabs: <Widget>[
new Tab(
icon: new Icon(Icons.image),
),
],
),
),
body: new TabBarView(
controller: controller,
children: <Widget>[
new GridOne(counter, myController),
],
));
}
}
class GridOneController {
void Function() resetCards;
}
class GridOne extends StatefulWidget {
int counter;
final GridOneController controller;
GridOne(this.counter, this.controller);
#override
_GridOneState createState() => _GridOneState(controller);
}
class _GridOneState extends State<GridOne> {
_GridOneState(GridOneController _controller) {
_controller.resetCards = resetCards;
}
int points = 0;
void increaseCounter() {
widget.counter += 1;
}
void decreaseCounter() {
widget.counter -= 1;
}
void resetCards() {
cardKeys.forEach((element) {
if (!element.currentState.isFront) {
element.currentState.toggleCard();
}
});
setState(() {});
}
List<GlobalKey<FlipCardState>> cardKeys = [];
#override
void initState() {
List.generate(52, (index) {
cardKeys.add(GlobalKey<FlipCardState>());
});
super.initState();
}
#override
Widget build(BuildContext context) {
print(cardKeys.length);
return new Scaffold(
body: new Column(children: <Widget>[
new Expanded(
child: GridView.count(
crossAxisCount: 5,
children: List.generate(52, (index) {
return Card(
elevation: 0.0,
margin: EdgeInsets.only(
left: 3.0, right: 3.0, top: 9.0, bottom: 0.0),
color: Color(0x00000000),
child: new FlipCard(
key: cardKeys[index],
direction: FlipDirection.HORIZONTAL,
speed: 1000,
onFlipDone: (status) {
setState(() {
(status) ? decreaseCounter() : increaseCounter();
});
if (widget.counter == 25) {
Fluttertoast.showToast(
msg: "You've got 25 states! Wow!",
toastLength: Toast.LENGTH_SHORT,
gravity: ToastGravity.BOTTOM_LEFT,
timeInSecForIosWeb: 1,
backgroundColor: Colors.red,
textColor: Colors.white,
fontSize: 16.0);
}
;
print(widget.counter);
},
front: Container(
decoration: BoxDecoration(
color: Color(0xFF006666),
borderRadius: BorderRadius.all(Radius.circular(8.0)),
),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
FittedBox(
fit: BoxFit.fitWidth,
child: Text(
'FRONT',
style: TextStyle(color: Colors.white),
)
//Theme.of(context).textTheme.headline
),
Text(
'',
),
],
),
),
back: Container(
decoration: BoxDecoration(
color: Color(0xFF006666),
borderRadius: BorderRadius.all(Radius.circular(8.0)),
),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[Text('BACK')],
),
),
),
);
})))
]),
);
}
}

Reducing the number of considered missed Gc histogram windows from 101 to 100

I am attempting to build a weather app as part of a Flutter course I am taking, and a message stating:
Reducing the number of considered missed Gc histogram windows from 101 to 100
appears in my console, when I would expect weather data instead. Is anyone familiar with this message?
I am pasting the code from the screens involved below, for reference.
location_screen.dart
import 'package:flutter/material.dart';
import 'package:clima/utilities/constants.dart';
class LocationScreen extends StatefulWidget {
LocationScreen({this.locationWeather});
final locationWeather;
#override
_LocationScreenState createState() => _LocationScreenState();
}
class _LocationScreenState extends State<LocationScreen> {
#override
void initState() {
super.initState();
print(widget.locationWeather);
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage('images/location_background.jpg'),
fit: BoxFit.cover,
colorFilter: ColorFilter.mode(
Colors.white.withOpacity(0.8), BlendMode.dstATop),
),
),
constraints: BoxConstraints.expand(),
child: SafeArea(
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
FlatButton(
onPressed: () {},
child: Icon(
Icons.near_me,
size: 50.0,
),
),
FlatButton(
onPressed: () {},
child: Icon(
Icons.location_city,
size: 50.0,
),
),
],
),
Padding(
padding: EdgeInsets.only(left: 15.0),
child: Row(
children: <Widget>[
Text(
'32°',
style: kTempTextStyle,
),
Text(
'☀️',
style: kConditionTextStyle,
),
],
),
),
Padding(
padding: EdgeInsets.only(right: 15.0),
child: Text(
"It's 🍦 time in San Francisco!",
textAlign: TextAlign.right,
style: kMessageTextStyle,
),
),
],
),
),
),
);
}
}
/*
double temperature = decodedData['main']['temp'];
int condition = decodedData['weather'][0]['id'];
String cityName = decodedData['name'];
*/
loading_screen.dart
import 'package:clima/screens/location_screen.dart';
import 'package:clima/services/networking.dart';
import 'package:flutter/material.dart';
import 'package:clima/services/location.dart';
import 'package:clima/services/networking.dart';
import 'package:flutter_spinkit/flutter_spinkit.dart';
import 'location_screen.dart';
const apiKey = 'APIKEY';
class LoadingScreen extends StatefulWidget {
#override
State<StatefulWidget> createState() {
return _LoadingScreenState();
}
}
class _LoadingScreenState extends State<LoadingScreen> {
double latitude;
double longitude;
#override
void initState() {
super.initState();
getLocation();
}
void getLocationData() async {
Location location = Location();
await location.getCurrentLocation();
latitude = location.latitude;
longitude = location.longitude;
NetworkHelper networkHelper = NetworkHelper(
'https://api.openweathermap.org/data/2.5/weather?lat=$latitude&lon=$longitude&appid=$apiKey');
var weatherData = await networkHelper.getData();
Navigator.push(
context,
MaterialPageRoute(
builder: (context) {
return LocationScreen(
locationWeather: weatherData,
);
},
),
);
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: SpinKitDoubleBounce(
color: Colors.white,
size: 100.0,
),
),
);
}
}
networking.dart
import 'package:http/http.dart' as http;
import 'dart:convert';
class NetworkHelper {
NetworkHelper(this.url);
final String url;
Future getData() async {
http.Response response = await http.get(url);
if (response.statusCode == 200) {
String data = response.body;
return jsonDecode(data);
} else {
print(response.statusCode);
}
}
}
You should disconnect your app. Delete it from the device or emulator if you're using one, then cold restart your app again. It will work just fine.
It worked for me on my device.

How do I make it so that all filters don't change color when tapped on flutter

I'm trying to make a template for a filter that takes in one parameter (the tag name) and gets highlighted when tapped. But the problem with this is when one filter is tapped all of them change color because they all use the same boolean value. Sorry, I'm a beginner and I think I'm going about this the wrong way
class _HomeState extends State<Home> {
bool filterTap = true;
GestureDetector filterTemplate(String tag) {
return GestureDetector(
onTap: () {
setState(() {
filterTap = !filterTap;
});
},
child: Center(
child: Container(
margin: const EdgeInsets.only(right: 20.0),
padding: const EdgeInsets.symmetric(vertical: 5.0, horizontal: 10.0),
decoration: BoxDecoration(
border: Border.all(color: Colors.grey),
borderRadius: BorderRadius.all(Radius.circular(4.0)),
color: filterTap ? Colors.grey : Colors.transparent,
),
child: Text(
tag,
style: TextStyle(
color: filterTap ? Colors.grey[900] : Colors.grey,
letterSpacing: 2.0,
),
),
),
),
);
}
first of all define a StructFilter class with its properties, For example here is an option:
class StructFilter {
StructFilter(this.tag,this.filterTap);
String tag;
bool filterTap;
}
Then collect all of your filter information into a list of StructFilter(i.e List<StructFilter> filterList).
For example you can try:
Listview(
children: filterList.map((item){
return filterTemplate(item);
}).toList();
)
GestureDetector filterTemplate(StructFilter structFilter) {
return GestureDetector(
onTap: () {
setState(() {
structFilter.filterTap = !structFilter.filterTap;
});
},
),
);
}
Use List or Map or List<YourClass> to maintain status of each button.
And try ChoiceChip,
import 'package:flutter/material.dart';
void main() {
runApp(MaterialApp(home: Home()));
}
class Home extends StatefulWidget {
#override
_HomeState createState() => _HomeState();
}
class _HomeState extends State<Home> {
Map<String, bool> tagsList = {
"Tag1": false,
"Tag2": false,
"Tag3": false,
"Tag4": false,
};
#override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Row(
children: tagsList.entries.map((entry) {
return Padding(
padding: const EdgeInsets.all(8.0),
child: ChoiceChip(
label: Text(entry.key),
selected: entry.value,
onSelected: (value) {
setState(() {
tagsList[entry.key] = value;
});
},
),
);
}).toList(),
),
),
);
}
}

Flutter: How to make a Card overlap the AppBar?

How can I make a Card in Flutter that overlaps the AppBar? Negative margins are not possible as far as I know.
See the image for clarity.
For one card it could be easily done with Stack widget
E.g.
import 'package:flutter/material.dart';
class Home extends StatefulWidget {
Home({Key key}) : super(key: key);
#override
HomeState createState() {
return new HomeState();
}
}
class HomeState extends State<Home> {
bool _hasCard;
#override
void initState() {
super.initState();
_hasCard = false;
}
#override
Widget build(BuildContext context) {
List<Widget> children = new List();
children.add(_buildBackground());
if (_hasCard) children.add(_buildCard());
return MaterialApp(
home: Stack(
children: children,
),
);
}
void _showCard() {
setState(() => _hasCard = true);
}
void _hideCard() {
setState(() => _hasCard = false);
}
Widget _buildCard() => new Container(
child: new Center(
child: new Container(
height: 700.0,
width: 200.0,
color: Colors.lightBlue,
child: new Center(
child: new Text("Card"),
),
),
),
);
Widget _buildBackground() => new Scaffold(
appBar: new AppBar(
title: new Text("AppBar"),
),
body: new Container(
child: _hasCard
? new FlatButton(
onPressed: _hideCard, child: new Text("Hide card"))
: new FlatButton(
onPressed: _showCard, child: new Text("Show card")),
),
);
}
void main() {
runApp(
new Home(),
);
}
If there are many cards, you can wrap them into ListView.
class Sample2 extends StatelessWidget {
#override
Widget build(BuildContext context) {
return SafeArea(
child: Material(
child: CustomScrollView(
slivers: [
SliverPersistentHeader(
delegate: MySliverAppBar(expandedHeight: 200),
pinned: true,
),
SliverList(
delegate: SliverChildBuilderDelegate(
(_, index) => ListTile(
title: Text("Index: $index"),
),
),
)
],
),
),
);
}
}
class MySliverAppBar extends SliverPersistentHeaderDelegate {
final double expandedHeight;
MySliverAppBar({#required this.expandedHeight});
#override
Widget build(
BuildContext context, double shrinkOffset, bool overlapsContent) {
return Stack(
fit: StackFit.expand,
overflow: Overflow.visible,
children: [
Image.network(
"https://images.pexels.com/photos/396547/pexels-photo-396547.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500",
fit: BoxFit.cover,
),
Center(
child: Opacity(
opacity: shrinkOffset / expandedHeight,
child: Text(
"MySliverAppBar",
style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.w700,
fontSize: 23,
),
),
),
),
Positioned(
top: expandedHeight / 2 - shrinkOffset,
left: MediaQuery.of(context).size.width / 4,
child: Opacity(
opacity: (1 - shrinkOffset / expandedHeight),
child: Card(
elevation: 10,
child: SizedBox(
height: expandedHeight,
width: MediaQuery.of(context).size.width / 2,
child: FlutterLogo(),
),
),
),
),
],
);
}
#override
double get maxExtent => expandedHeight;
#override
double get minExtent => kToolbarHeight;
#override
bool shouldRebuild(SliverPersistentHeaderDelegate oldDelegate) => true;
}

Resources