I am developing a weather application with Flutter. And I am thinking of designing a background that will change according to the weather. But I don't know how. I saw similar questions, but I did not see any benefit.
Here is all of my code;
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'package:location/location.dart';
import 'package:flutter/services.dart';
import 'package:uygulama1/Weather.dart';
import 'package:uygulama1/WeatherItem.dart';
import 'package:uygulama1/WeatherData.dart';
import 'package:uygulama1/ForecastData.dart';
//PROJECT'S ROOT
void main() {
runApp(MaterialApp(
title: "WeatherApp",
home: MyApp(),
));
}
//PROJECTS MAIN CLASS
class MyApp extends StatefulWidget {
#override
State<StatefulWidget> createState() {
return new MyAppState();
}
}
class MyAppState extends State<MyApp> {
bool isLoading = false;
WeatherData weatherData;
ForecastData forecastData;
Location _location = new Location();
String error;
#override
void initState() {
super.initState();
loadWeather();
}
Future<LocationData> getLocationData() async {
return await _location.getLocation();
}
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Weather App',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: Scaffold(
backgroundColor: Colors.tealAccent,
appBar: AppBar(
title: Text('Flutter Weather App'),
),
body: Center(
child: Column(mainAxisSize: MainAxisSize.min, children: <Widget>[
//BACKGROUND IMAGE
Container(
decoration: BoxDecoration(
image: new DecorationImage(
image: new AssetImage("assets/rain.jpg"),fit: BoxFit.cover
),
),
),
//END
Expanded(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Padding(
padding: const EdgeInsets.all(8.0),
child: weatherData != null
? Weather(weather: weatherData)
: Container(),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: isLoading
? CircularProgressIndicator(
strokeWidth: 2.0,
valueColor:
new AlwaysStoppedAnimation(Colors.black),
)
: IconButton(
icon: new Icon(Icons.refresh),
tooltip: 'Refresh',
onPressed: loadWeather,
color: Colors.black,
),
),
],
),
),
SafeArea(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
height: 200.0,
child: forecastData != null
? ListView.builder(
itemCount: forecastData.list.length,
scrollDirection: Axis.horizontal,
itemBuilder: (context, index) => WeatherItem(
weather: forecastData.list.elementAt(index)))
: Container(),
),
),
)
]))),
);
}
loadWeather() async {
setState(() {
isLoading = true;
});
LocationData location;
try {
location = await getLocationData();
error = null;
} on PlatformException catch (e) {
if (e.code == 'PERMISSION_DENIED') {
error = 'Permission denied';
} else if (e.code == 'PERMISSION_DENIED_NEVER_ASK') {
error =
'Permission denied - please ask the user to enable it from the app settings';
}
location = null;
}
if (location != null) {
final lat = location.latitude;
final lon = location.longitude;
final weatherResponse = await http.get(
'https://api.openweathermap.org/data/2.5/weather?APPID=d89de3f0b2dedfe4f923f1e7f709953a&lat=${lat.toString()}&lon=${lon.toString()}');
final forecastResponse = await http.get(
'https://api.openweathermap.org/data/2.5/forecast?APPID=d89de3f0b2dedfe4f923f1e7f709953a&lat=${lat.toString()}&lon=${lon.toString()}');
if (weatherResponse.statusCode == 200 &&
forecastResponse.statusCode == 200) {
return setState(() {
weatherData =
new WeatherData.fromJson(jsonDecode(weatherResponse.body));
forecastData =
new ForecastData.fromJson(jsonDecode(forecastResponse.body));
isLoading = false;
});
}
}
setState(() {
isLoading = false;
});
}
}
Weather.dart
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
import 'package:uygulama1/WeatherData.dart';
class Weather extends StatelessWidget {
final WeatherData weather;
Weather({Key key, #required this.weather}) : super(key: key);
#override
Widget build(BuildContext context) {
var temperature = (weather.temp - 273.15).round();
return Column(
children: <Widget>[
Text(weather.name, style: new TextStyle(color: Colors.black)),
Text("\n" + weather.main,
style: new TextStyle(color: Colors.black, fontSize: 32.0)),
Text("Temp: " + '${temperature.toString()}°C',
style: new TextStyle(color: Colors.black)),
Image.network('https://openweathermap.org/img/w/${weather.icon}.png'),
Text("Date: " + new DateFormat.yMMMd().format(weather.date),
style: new TextStyle(color: Colors.black)),
Text("Hour: " + new DateFormat.Hm().format(weather.date),
style: new TextStyle(color: Colors.black)),
],
);
}
}
Other files actually not important.
Thanks for your helps.
You can have a map with keys of strings(type of weather) and values of AssetImages, e.g.
final Map<String, AssetImage> images = {"rain": AssetImage("assets/rain.jpg"),
"wind": AssetImage("assets/wind.jpg"),
"snow": AssetImage("assets/snow.jpg")};
For the background:
Container(
decoration: BoxDecoration(
image: new DecorationImage(
image: weatherData == null ? images["wind"] : images[weatherData.name],
fit: BoxFit.cover
),
),
),
Assumptions:
Default background before fetching the weatherData is AssetImage("assets/wind.jpg").
weatherData.name can be "wind", "snow", and "rain".
May be you can do like this if you have two condition:
Container(
decoration: BoxDecoration(
image: new DecorationImage(
image:
fit: BoxFit.cover,
(isRaining)? new AssetImage("assets/rain.jpg"):new AssetImage("assets/sunny.jpg")
),
),
If you have multiple conditions, you can do it like this:
Container(
decoration: BoxDecoration(
image: new DecorationImage(
image:
fit: BoxFit.cover,
if(isRaining)
new AssetImage("assets/rain.jpg")
else if(isSunny)
new AssetImage("assets/sunny.jpg")
else
new AssetImage("assets/cold.jpg")
),
),
Hope this helps! Happy Coding:)
Related
I am trying to build a image picker using flutter. I want the user to be able to select an image and upload it onto firebase storage so that it can be later retrieved. I am using an image picker to select the image from the gallery and I am then setting the image selected as a file. I am then creating a reference called firebaseStorageRef and using firebaseStorageRef.putFile(_selectedImage!) to upload the data.
However, I am getting the error:
Restarted application in 553ms.
[VERBOSE-2:dart_vm_initializer.cc(41)] Unhandled Exception: [firebase_storage/object-not-found] No object exists at the desired reference.
main.dart:
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/material.dart';
import 'package:flutter_blog/views/homePage.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
runApp(const MainApp());
}
class MainApp extends StatelessWidget {
const MainApp({super.key});
#override
Widget build(BuildContext context) {
return const MaterialApp(
title: "Blog App",
themeMode: ThemeMode.dark,
debugShowCheckedModeBanner: false,
home: homePage());
}
}
create_blog.dart code:
import 'dart:io';
import 'package:firebase_storage/firebase_storage.dart';
import 'package:flutter/material.dart';
import 'package:flutter_blog/services/crud.dart';
import 'package:image_picker/image_picker.dart';
import 'package:random_string/random_string.dart';
import 'package:firebase_core/firebase_core.dart';
class CreateBlog extends StatefulWidget {
const CreateBlog({super.key});
#override
State<CreateBlog> createState() => _CreateBlogState();
}
class _CreateBlogState extends State<CreateBlog> {
late String authorName, title, desc;
bool isloading = false;
CRUDMethods crudMethods = new CRUDMethods();
File? _selectedImage;
Future getImage() async {
var image = await ImagePicker().pickImage(source: ImageSource.gallery);
if (image == null) return;
final image_path = File(image.path);
setState(() {
_selectedImage = image_path;
});
}
uploadBlog() async {
if (_selectedImage != null) {
// Uploading image to Firestore
setState(() {
isloading = true;
});
var firebaseStorageRef = FirebaseStorage.instance
.ref()
.child("blogImages")
.child("${randomAlphaNumeric(9)}.jpg");
try {
var task = firebaseStorageRef
.putFile(_selectedImage!)
.whenComplete(() => Navigator.pop(context));
} catch (error) {
print(error);
}
} else {}
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title:
Row(mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[
Text(
"Flutter",
style: TextStyle(
fontSize: 22,
color: Colors.black,
),
),
Text(
"Blog",
style: TextStyle(fontSize: 22, color: Colors.blue),
)
]),
backgroundColor: Colors.transparent,
elevation: 0,
actions: <Widget>[
GestureDetector(
onTap: () {
uploadBlog();
},
child: Container(
padding: EdgeInsets.symmetric(horizontal: 16),
child: Icon(
Icons.file_upload,
color: Colors.black,
)))
],
),
backgroundColor: Colors.white,
body: isloading
? Container(
alignment: Alignment.center,
child: CircularProgressIndicator(color: Colors.teal),
)
: Container(
child: Column(
children: <Widget>[
SizedBox(
height: 10,
),
GestureDetector(
onTap: () {
getImage();
},
child: _selectedImage != null
? Container(
margin: EdgeInsets.symmetric(horizontal: 30),
height: 150,
width: MediaQuery.of(context).size.width,
child: Image.file(
_selectedImage!,
fit: BoxFit.cover,
),
)
: Container(
margin: EdgeInsets.symmetric(horizontal: 30),
height: 150,
width: MediaQuery.of(context).size.width,
child: Icon(Icons.add_a_photo),
decoration: BoxDecoration(
color: Colors.blueAccent,
borderRadius: BorderRadius.circular(6)),
),
),
SizedBox(
height: 8,
),
Container(
margin: EdgeInsets.symmetric(horizontal: 30),
child: Column(
children: <Widget>[
TextField(
decoration: InputDecoration(hintText: "Author Name"),
onChanged: (val) {
authorName = val;
},
),
TextField(
decoration: InputDecoration(hintText: "Title"),
onChanged: (val) {
title = val;
},
),
TextField(
decoration: InputDecoration(hintText: "Description"),
onChanged: (val) {
desc = val;
},
)
],
),
)
],
)),
);
}
}
crud.dart code:
import 'package:firebase_storage/firebase_storage.dart';
import 'package:flutter/material.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
class CRUDMethods {
Future<void> addData(blogData) async {
FirebaseFirestore.instance
.collection("blogs")
.add(blogData)
.catchError((e) {
print(e);
});
}
}
So i'm pretty lost trying to get my app to fetch not only the desired text from firestore but also the image i placed there. I know the error "Bad state: field does not exist within the DocumentSnapshotPlatform" implies that either I'm missing field or there's something wrong with at least one of those fields. There's only four things I'm trying to fetch from firestore "imgUrl, title, desc, organizer" i have checked for spelling and order and i can't figure it out. I have also checked firestore to see if the order and spelling was correct and i dont see what's the issue. Please help, Thank you so much in advanced.
////////////////////////////// News Class Starts\\\\\\\\\\\\\\
import 'package:myfuji/screens/CrudMethods.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';
import 'CrudMethods.dart';
import 'add_blog.dart';
class News extends StatefulWidget {
#override
_NewsState createState() => _NewsState();
}
class _NewsState extends State<News> {
CrudMethods crudMethods = CrudMethods();
late QuerySnapshot blogSnapshot;
#override
void initState() {
crudMethods.getData().then((result) {
blogSnapshot = result;
setState(() {});
});
super.initState();
}
Widget blogsList() {
return ListView.builder(
padding: const EdgeInsets.only(top: 24),
itemCount: blogSnapshot.docs.length,
itemBuilder: (context, index) {
return BlogTile(
organizer: blogSnapshot.docs[index].get('Organizer'),
desc: blogSnapshot.docs[index].get('desc'),
imgUrl: blogSnapshot.docs[index].get('imgUrl'),
title: blogSnapshot.docs[index].get('title'),
);
},
);
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text("Events"),
),
body: Container(
child: blogSnapshot != null
? blogsList()
: const Center(
child: CircularProgressIndicator(),
)),
floatingActionButton: FloatingActionButton(
child: const Icon(Icons.add),
onPressed: () {
Navigator.push(
context, MaterialPageRoute(builder: (context) => AddBlog()));
},
),
);
}
}
class BlogTile extends StatelessWidget {
final String imgUrl, title, desc, organizer;
const BlogTile(
{required this.organizer,
required this.desc,
required this.imgUrl,
required this.title});
#override
Widget build(BuildContext context) {
return Container(
margin: const EdgeInsets.only(bottom: 24, right: 16, left: 16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
child: ClipRRect(
borderRadius: const BorderRadius.all(Radius.circular(8)),
child: Image.network(
imgUrl,
width: MediaQuery.of(context).size.width,
fit: BoxFit.cover,
height: 200,
),
),
),
const SizedBox(height: 16),
Text(
title,
style: const TextStyle(fontSize: 17),
),
const SizedBox(height: 2),
Text(
'$desc - By $organizer',
style: const TextStyle(fontSize: 14),
)
],
),
);
}
}
///////////////////////////////////////////// class AddBlog begins here \\\\\\\\\\\
import 'dart:io';
import 'package:myfuji/screens/CrudMethods.dart';
import 'package:firebase_storage/firebase_storage.dart';
import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart';
import 'package:random_string/random_string.dart';
class AddBlog extends StatefulWidget {
#override
_AddBlogState createState() => _AddBlogState();
}
class _AddBlogState extends State<AddBlog> {
//
late File selectedImage;
final picker = ImagePicker();
bool isLoading = false;
CrudMethods crudMethods = new CrudMethods();
Future getImage() async {
final pickedFile = await picker.getImage(source: ImageSource.gallery);
setState(() {
if (pickedFile != null) {
selectedImage = File(pickedFile.path);
} else {
print('No image selected.');
}
});
}
Future<void> uploadBlog() async {
if (selectedImage != null) {
// upload the image
setState(() {
isLoading = true;
});
Reference firebaseStorageRef = FirebaseStorage.instance
.ref()
.child("events/")
.child("${randomAlphaNumeric(9)}.jpg");
final UploadTask task = firebaseStorageRef.putFile(selectedImage);
var imageUrl;
await task.whenComplete(() async {
try {
imageUrl = await firebaseStorageRef.getDownloadURL();
} catch (onError) {
print("Error");
}
print(imageUrl);
});
// print(downloadUrl);
Map<String, dynamic> blogData = {
"imgUrl": imageUrl,
"Organizer": authorTextEditingController.text,
"title": titleTextEditingController.text,
"desc": descTextEditingController.text
};
crudMethods.addData(blogData).then((value) {
setState(() {
isLoading = false;
});
Navigator.pop(context);
});
// upload the blog info
}
}
//
TextEditingController titleTextEditingController =
new TextEditingController();
TextEditingController descTextEditingController = new TextEditingController();
TextEditingController authorTextEditingController =
new TextEditingController();
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Create Blog"),
actions: [
GestureDetector(
onTap: () {
uploadBlog();
},
child: Padding(
padding: EdgeInsets.symmetric(horizontal: 16),
child: Icon(Icons.file_upload)),
)
],
),
body: isLoading
? Container(
child: Center(
child: CircularProgressIndicator(),
))
: SingleChildScrollView(
child: Container(
margin: EdgeInsets.symmetric(horizontal: 16),
child: Column(
children: [
GestureDetector(
onTap: () {
getImage();
},
child: selectedImage != null
? Container(
height: 150,
margin: EdgeInsets.symmetric(vertical: 24),
width: MediaQuery.of(context).size.width,
child: ClipRRect(
borderRadius:
BorderRadius.all(Radius.circular(8)),
child: Image.file(
selectedImage,
fit: BoxFit.cover,
),
),
)
: Container(
height: 150,
decoration: BoxDecoration(
color: Colors.grey,
borderRadius:
BorderRadius.all(Radius.circular(8))),
margin: EdgeInsets.symmetric(vertical: 24),
width: MediaQuery.of(context).size.width,
child: Icon(
Icons.camera_alt,
color: Colors.white,
),
),
),
TextField(
controller: titleTextEditingController,
decoration: InputDecoration(hintText: "enter title"),
),
TextField(
controller: descTextEditingController,
decoration: InputDecoration(hintText: "enter desc"),
),
TextField(
controller: authorTextEditingController,
decoration:
InputDecoration(hintText: "enter author name"),
),
],
)),
),
);
}
}
///////////////////////////////////////////// class CrudMethods begins here \\\\\\\\\\\
import 'package:cloud_firestore/cloud_firestore.dart';
class CrudMethods {
Future<void> addData(blogData) async {
print(blogData);
FirebaseFirestore.instance
.collection("events/")
.add(blogData)
.then((value) => print(value))
.catchError((e) {
print(e);
});
}
getData() async {
return await FirebaseFirestore.instance.collection("events/").get();
}
}
/////////////////////////////////////////////firestore\\\\\\\\\\\\\
This maybe related to having “/“ after collection name here:
.collection("events/")
Instead try this:
.collection("events")
Also it may be best to change child to collection here:
Reference firebaseStorageRef = FirebaseStorage.instance
.ref()
.child("events/")
Try to see if you get data back by running this:
itemCount: blogSnapshot.docs.length,
itemBuilder: (context, index) {
QuerySnapshot snap = blogSnapshot.data; // Snapshot
List<DocumentSnapshot> items = snap.documents; // List of Documents
DocumentSnapshot item = items[index]; Specific Document
return BlogTile(
organizer: item.data['Organizer'],
desc: item.data['desc'],
imgUrl: item.data['imgUrl'],
title: item.data['title'],
);
},
I think you need to utilize a QueryDocumentSnapshot to access the data in the document.
suddently from nowhere i came up with provider not re rendering my home page when it's updated. I've inspected it and it IS UPDATED. It has newer data when i change it in firebase but the UI won't re-render showing the new data. That's my code:
Main function
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/material.dart';
import 'package:my_event_app/pages/HomePage/home_page.dart';
import 'package:my_event_app/pages/Login/login_page.dart';
import 'package:my_event_app/providers/User/user.dart';
import 'package:provider/provider.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return MultiProvider(
providers: [
ChangeNotifierProvider(create: (_) => UserModel()),
],
child: MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Flutter Demo',
theme: ThemeData(
// is not restarted.
primarySwatch: Colors.blue,
),
home: const Wrapper(),
),
);
}
}
class Wrapper extends StatelessWidget {
const Wrapper({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return StreamBuilder<User?>(
stream: FirebaseAuth.instance.userChanges(),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.active) {
User? user = snapshot.data;
if (user == null) {
return const LoginPage();
}
return StreamBuilder<DocumentSnapshot>(
stream: FirebaseFirestore.instance
.collection('users')
.doc(FirebaseAuth.instance.currentUser!.uid)
.snapshots(),
builder: (context, userSnapshot) {
if (userSnapshot.hasData) {
Provider.of<UserModel>(context, listen: true)
.fromJson(userSnapshot.data!.data());
return const HomePage();
}
return const Scaffold(
body: Center(
child: CircularProgressIndicator(),
),
);
});
} else {
return const Scaffold(
body: Center(
child: CircularProgressIndicator(),
),
);
}
},
);
}
}
And this is the home page:
import 'package:flutter/material.dart';
import 'package:my_event_app/http/auth/user/sign_out.dart';
import 'package:my_event_app/pages/Create_Event/create_event_page.dart';
import 'package:my_event_app/pages/Onboarding/onboarding_page.dart';
import 'package:my_event_app/providers/User/user.dart';
import 'package:my_event_app/widgets/event_card_widget.dart';
import 'package:provider/provider.dart';
class HomePage extends StatefulWidget {
const HomePage({Key? key}) : super(key: key);
#override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
#override
Widget build(BuildContext context) {
return Consumer<UserModel>(builder: (context, user, child) {
return Scaffold(
appBar: AppBar(
leading: IconButton(
icon: const Icon(Icons.help_outline, color: Colors.black, size: 30),
onPressed: () {
Navigator.push(context, MaterialPageRoute(builder: (context) {
return const OnboardingPage();
}));
},
),
actions: [
IconButton(
icon: const Icon(
Icons.arrow_forward_ios_sharp,
color: Colors.black,
),
onPressed: () {
signOut();
},
),
],
elevation: 0,
backgroundColor: Colors.white,
),
backgroundColor: Colors.white,
body: SingleChildScrollView(
child: Container(
color: Colors.white,
padding: const EdgeInsets.all(16),
child: Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
const CircleAvatar(
radius: 25,
backgroundImage: NetworkImage(
"https://cdnnmundo1.img.sputniknews.com/img/07e5/09/13/1116212032_100:0:1273:1173_1920x0_80_0_0_efb734331af13dfe11ff6d43293c60e2.png"),
),
Container(
height: 50,
width: 50,
decoration: BoxDecoration(
color: Colors.orange[400],
borderRadius: BorderRadius.circular(10),
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.1),
spreadRadius: 1,
blurRadius: 5,
offset: const Offset(0, 3),
),
],
),
child: Center(
child: IconButton(
color: Colors.white,
onPressed: () {
// Navigate to add event widget
Navigator.push(context,
MaterialPageRoute(builder: (context) {
return const CreateEventPage();
}));
},
icon: const Icon(Icons.add),
),
),
),
],
),
const SizedBox(height: 32),
SizedBox(
width: double.infinity,
child: Text('Welcome, ${user.name}',
style: const TextStyle(
fontSize: 28,
fontWeight: FontWeight.bold,
fontFamily: "Roboto")),
),
const SizedBox(height: 32),
Container(
padding: const EdgeInsets.all(16),
height: 100,
width: double.infinity,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(10),
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.1),
spreadRadius: 1,
blurRadius: 5,
offset: const Offset(0, 3),
),
],
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Stack(alignment: Alignment.center, children: [
SizedBox(
height: 45,
width: 45,
child: CircularProgressIndicator(
valueColor:
AlwaysStoppedAnimation(Colors.orange[400]),
value: 14 / 20,
semanticsValue: "14/20",
color: Colors.black,
),
),
const Text("78%",
style: TextStyle(
fontSize: 14,
fontWeight: FontWeight.bold,
fontFamily: "Roboto")),
]),
Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
crossAxisAlignment: CrossAxisAlignment.start,
children: const [
Text("Weekly progress",
style: TextStyle(
fontSize: 14,
fontWeight: FontWeight.w600,
)),
Text("14/20 tasks completed"),
],
),
const Icon(Icons.bar_chart),
],
),
),
Container(
margin: const EdgeInsets.symmetric(vertical: 16),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: const [
Text("You have 5 tasks for today",
style: TextStyle(
fontSize: 14,
fontWeight: FontWeight.w600,
)),
Icon(Icons.calendar_today_outlined)
],
),
),
_renderEvents(user),
],
),
),
),
);
});
}
}
Column _renderEvents(UserModel user) {
return Column(
children: [
for (var event in user.events)
EventCard(
eventId: event,
),
],
);
}
And here's the provider:
import 'package:flutter/material.dart';
class UserModel extends ChangeNotifier {
String _name = '';
String _surnames = '';
String _uid = '';
String _email = '';
List<dynamic> _events = [];
String get name => _name;
String get surnames => _surnames;
String get uid => _uid;
String get email => _email;
List<dynamic> get events => _events;
UserModel();
set name(String value) {
_name = value;
notifyListeners();
}
set surnames(String value) {
_surnames = value;
notifyListeners();
}
set uid(String value) {
_uid = value;
notifyListeners();
}
set email(String value) {
_email = value;
notifyListeners();
}
set events(List<dynamic> value) {
_events = value;
notifyListeners();
}
void addEvent(String event) {
_events.add(event);
notifyListeners();
}
void removeEvent(String event) {
_events.remove(event);
notifyListeners();
}
void updateUser(String name, String uid) {
name = name;
uid = uid;
notifyListeners();
}
void clearUser() {
_name = '';
_uid = '';
notifyListeners();
}
Map<String, dynamic> toJson() {
return {
'name': _name,
'surnames': _surnames,
'uid': _uid,
'email': _email,
'events': _events
};
}
fromJson(Object? json) {
try {
Map<dynamic, dynamic> map = json as Map<dynamic, dynamic>;
_name = map['name'];
_surnames = map['surnames'];
_uid = map['uid'];
_email = map['email'];
_events = map['events'];
} catch (e) {
print(e);
}
}
}
```
As you can see i use Consumer in order to read data and i have a change notifier in the begginig, but it won't re render and show for example new name if i change it in fireabase.
Thank you so much!
You are using fromJson method to update values in UserModel, but it does not call notifyListeners. Add notifyListeners(); to the end of this method:
fromJson(Object? json) {
try {
Map<dynamic, dynamic> map = json as Map<dynamic, dynamic>;
_name = map['name'];
_surnames = map['surnames'];
_uid = map['uid'];
_email = map['email'];
_events = map['events'];
notifyListeners(); // add this
} catch (e) {
print(e);
}
}
Also some other things:
Consider declaring class UserModel with ChangeNotifier instead of class UserModel extends ChangeNotifier.
fromJson methods usually are acting as factory methods, meaning these return a new instance, and don't set members in an existing instance.
Instead of Provider.of<UserModel>(context, listen: true).fromJson(userSnapshot.data!.data()); you can try: context.read<UserModel>().fromJson(userSnapshot.data!.data());. Here you don't really need listening, you just want to find the provider and call fromJson. Your Consumer is the one which is listening to the changes accordingly.
Im doing an integration test in Flutter and in the application I open the camera, but I don't know how to tap on the button to do the photo, anyone know how can I search for this button?
Here is the code if the app where you can choose between pic a photo with the camera or choose one picture of your gallery
import 'dart:io';
import 'package:permission_handler/permission_handler.dart';
import 'package:random_string/random_string.dart';
import 'package:cached_network_image/cached_network_image.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'package:image_cropper/image_cropper.dart';
import 'package:image_picker/image_picker.dart';
import 'package:modal_progress_hud/modal_progress_hud.dart';
import 'package:rosita/language/firebase_remote.dart';
import 'package:rosita/api/api_provider.dart';
import 'package:rosita/constants/common.dart';
import 'package:rosita/model/image_object.dart';
import 'package:rosita/model/senior_user.dart';
import 'package:rosita/modules/widgets/button_ui.dart';
import 'package:rosita/rosita.dart';
class AddProfileImageScreen extends StatefulWidget {
const AddProfileImageScreen({Key key, this.seniorUser}) : super(key: key);
final SeniorUser seniorUser;
#override
_AddProfileImageScreenState createState() => _AddProfileImageScreenState();
}
class _AddProfileImageScreenState extends State<AddProfileImageScreen> {
bool _isProcessing = false;
File _image;
bool _enableButton = false;
#override
void initState() {
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Theme.of(context).scaffoldBackgroundColor,
body: ModalProgressHUD(
inAsyncCall: _isProcessing,
color: Colors.transparent,
progressIndicator: const CircularProgressIndicator(
strokeWidth: 2.0,
),
child: Container(
padding: EdgeInsets.only(top: MediaQuery.of(context).padding.top),
constraints: BoxConstraints(
minHeight: MediaQuery.of(context).size.height,
minWidth: MediaQuery.of(context).size.width),
child: Padding(
padding: const EdgeInsets.all(24),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
darkSubtitleText('choose_profile_picture', context),
Expanded(
child: Center(
child: SizedBox(
width: 100,
height: 100,
child: Card(
shape: RoundedRectangleBorder(
side: const BorderSide(
color: AppTheme.purpleColor,
width: 4,
),
borderRadius: BorderRadius.circular(60.0),
),
elevation: 0,
color: Theme.of(context).dividerColor,
child: _image == null
? (widget.seniorUser != null &&
widget.seniorUser.profileImage != null &&
widget.seniorUser.profileImage.imageUrl !=
'')
? CachedNetworkImage(
imageUrl:
widget.seniorUser.profileImage.imageUrl,
placeholder:
(BuildContext context, String url) =>
Image.asset(ConstantsData.appIcon),
errorWidget: (BuildContext context,
String url, error) =>
const Icon(Icons.error),
fit: BoxFit.cover,
)
: Image.asset(ConstantsData.appIcon)
: Image.file(_image),
),
),
),
),
ButtonUI(
buttonName: 'ProfilePhotoFromCameraButton',
key: const Key(Keys.cameraButton),
isTrack: true,
color: AppTheme.primaryColor,
body: Center(
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Text(
FireText.of('take_a_photo_with_your_camera'),
textAlign: TextAlign.center,
style: Theme.of(context)
.primaryTextTheme
.subtitle2
.copyWith(
color: Theme.of(context).backgroundColor,
),
),
),
),
onTap: () {
getImage(isGallery: false);
},
),
verticalSpacer(),
ButtonUI(
buttonName: 'ProfilePhotoFromGalleryButton',
key: const Key(Keys.galleryButton),
isTrack: true,
color: AppTheme.primaryColor,
body: Center(
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Text(
FireText.of('choose_from_gallery'),
textAlign: TextAlign.center,
style: Theme.of(context)
.primaryTextTheme
.subtitle2
.copyWith(
color: Theme.of(context).backgroundColor,
),
),
),
),
onTap: () {
getImage(isGallery: true);
},
),
verticalSpacer(),
if (_image != null || _enableButton)
ButtonUI(
buttonName: 'ProfilePhotoUploadButton',
key: const Key(Keys.uploadButton),
isTrack: true,
color: AppTheme.purpleColor,
body: Center(
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Text(
FireText.of('continue_txt'),
style: Theme.of(context)
.primaryTextTheme
.subtitle2
.copyWith(
color: Theme.of(context).backgroundColor,
),
),
),
),
onTap: () {
_uploadAllInformation();
},
),
],
),
),
),
),
);
}
Future<void> getImage({bool isGallery = true}) async {
await <Permission>[Permission.camera, Permission.storage].request();
if (await Permission.storage.status != PermissionStatus.granted) {
setState(() {
_enableButton = true;
});
return;
}
if (!isGallery &&
await Permission.camera.status != PermissionStatus.granted) {
setState(() {
_enableButton = true;
});
return;
}
final image = await ImagePicker.pickImage(
source: isGallery ? ImageSource.gallery : ImageSource.camera);
if (image == null) return;
final cropimage = await cropImage(image);
if (cropimage == null) return;
setState(() {
_image = cropimage;
});
}
Future<File> cropImage(File imageFile) async {
final croppedFile = await ImageCropper.cropImage(
androidUiSettings: AndroidUiSettings(
statusBarColor: Theme.of(context).primaryColor,
toolbarColor: Theme.of(context).primaryColor,
toolbarWidgetColor: Theme.of(context).backgroundColor,
),
sourcePath: imageFile.path,
cropStyle: CropStyle.circle,
aspectRatio: const CropAspectRatio(ratioX: 1, ratioY: 1),
maxWidth: 420,
maxHeight: 420,
);
return croppedFile;
}
Future<void> _uploadAllInformation() async {
setState(() {
_isProcessing = true;
});
widget.seniorUser.documentId =
(await FirebaseAuth.instance.currentUser()).uid;
widget.seniorUser.referralCode =
'RO-' + randomAlphaNumeric(8).toUpperCase();
widget.seniorUser.enterReferralCode = deepLinkReferralCode;
await ApiProvider().createSeniorUserProfile(widget.seniorUser);
endRegister = true;
if (!_enableButton) {
final imageData = await updateProfilePic(widget.seniorUser);
await ApiProvider()
.updateRositaProfileImage(imageData, widget.seniorUser.documentId);
}
setState(() {
_isProcessing = false;
});
Rosita.restartApp(context);
}
Future<ImageObject> updateProfilePic(SeniorUser user) async {
final imagename = DateTime.now().millisecondsSinceEpoch.toString() + '.jpg';
final url = await ApiProvider()
.updateProfilePic('rositapics/${user.documentId}/' + imagename, _image);
final profileImage = ImageObject();
profileImage.imageUrl = url.toString();
profileImage.firebaseStoregPath =
'rositapics/${user.documentId}/' + imagename;
profileImage.imageName = imagename;
return profileImage;
}
}
Am trying to load a blog on flutter using API. for some reasons, the file is not loading on the emulator, and the code not showing any errors or suggestions. Once i click run, after the connection, it stops abruptly... Please, if anyone can preview the code and and help me out.. The error log is saying something about immutable, which i don't really follow.. Please help.
Main.dart
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'dart:convert';
import 'package:html/parser.dart';
import 'pages/post_view.dart';
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'Flutter Demo',
theme: new ThemeData(
primarySwatch: Colors.blue,
),
home: new MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
var _isLoading = true; //For progress bar
var posts;
var imgUrl;
//initialization
void initState() {
super.initState();
_fetchData();
}
//Function to fetch data from JSON
_fetchData() async {
print("attempting");
final url =
"https://www.googleapis.com/blogger/v3/blogs/MY BLOG ID HERE/posts/?key= API KEY HERE";
final response = await http.get(url);
print(response);
if (response.statusCode == 200) {
//HTTP OK is 200
final Map items = json.decode(response.body);
var post = items['items'];
setState(() {
_isLoading = false;
this.posts = post;
});
}
}
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text("Blogger"),
actions: <Widget>[
new IconButton(
icon: new Icon(Icons.refresh),
onPressed: () {
setState(() {
_isLoading = true;
});
_fetchData();
})
],
),
body: new Center(
child: _isLoading
? new CircularProgressIndicator()
: new ListView.builder(
itemCount: this.posts != null ? this.posts.length : 0,
itemBuilder: (context, i) {
final Post = this.posts[i];
final postDesc = Post["content"];
//All the below code is to fetch the image
var document = parse(postDesc);
//Regular expression
RegExp regExp = new RegExp(
r"(https?:\/\/.*\.(?:png|jpg|gif))",
caseSensitive: false,
multiLine: false,
);
final match = regExp
.stringMatch(document.outerHtml.toString())
.toString();
//print(document.outerHtml);
//print("firstMatch : " + match);
//Converting the regex output to image (Slashing) , since the output from regex was not perfect for me
if (match.length > 5) {
if (match.contains(".jpg")) {
imgUrl = match.substring(0, match.indexOf(".jpg"));
print(imgUrl);
} else {
imgUrl =
"https://pbs.twimg.com/profile_images/916384996092448768/PF1TSFOE_400x400.jpg";
}
}
String description = document.body.text.trim();
//print(description);
return new Container(
padding:
const EdgeInsets.fromLTRB(16.0, 16.0, 16.0, 8.0),
child: new Column(
mainAxisAlignment: MainAxisAlignment.spaceAround,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
new Container(
width: 500.0,
height: 180.0,
decoration: new BoxDecoration(
shape: BoxShape.rectangle,
image: new DecorationImage(
fit: BoxFit.fill,
//check if the image is not null (length > 5) only then check imgUrl else display default img
image: new NetworkImage(imgUrl
.toString()
.length >
10
? imgUrl.toString()
: "https://pbs.twimg.com/profile_images/916384996092448768/PF1TSFOE_400x400.jpg")),
),
),
new Padding(
padding:
const EdgeInsets.symmetric(vertical: 10.0),
child: new Text(
Post["title"],
maxLines: 3,
style: new TextStyle(
fontSize: 18.0,
fontWeight: FontWeight.bold,
),
),
),
new Text(
description.replaceAll("\n", ", "),
maxLines: 2,
overflow: TextOverflow.ellipsis,
style: new TextStyle(fontSize: 15.0),
),
new Padding(
padding:
const EdgeInsets.symmetric(vertical: 16.0),
child: new RaisedButton(
child: new Text("READ MORE",style: new TextStyle(color: Colors.white),),
color: Colors.blue,
onPressed: () {
//We will pass description to postview through an argument
Navigator
.of(context)
.push(new MaterialPageRoute<Null>(
builder: (BuildContext context) {
return PostView(Post['title'],description,imgUrl);
},
));
},
),
),
Divider(),
],
),
);
},
)));
}
}
Post_view.dart
import 'package:flutter/material.dart';
class PostView extends StatelessWidget {
var desc, title, image;
PostView(String title, String desc, String image) {
this.desc = desc;
this.title = title;
this.image = image;
}
#override
Widget build(BuildContext context) {
if (desc.toString().contains("\n\n\n\n")) {
desc = desc.toString().replaceAll("\n\n\n\n", "\n\n");
}
if (desc.toString().contains("\n\n\n")) {
desc = desc.toString().replaceAll("\n\n\n", "\n");
}
return new Scaffold(
appBar: new AppBar(
title: new Text("Blogger"),
),
body: new Container(
child: new SingleChildScrollView(
child: new Column(
children: <Widget>[
new Padding(
padding:
const EdgeInsets.symmetric(vertical: 16.0, horizontal: 16.0),
child: new Text(
title,
style: new TextStyle(
fontSize: 22.0,
fontWeight: FontWeight.bold,
),
),
),
new Padding(
padding:
const EdgeInsets.symmetric(vertical: 16.0, horizontal: 16.0),
child: new Container(
width: 500.0,
height: 180.0,
decoration: new BoxDecoration(
shape: BoxShape.rectangle,
image: new DecorationImage(
fit: BoxFit.fill,
//check if the image is not null (length > 5) only then check imgUrl else display default img
image: new NetworkImage(image.toString().length > 10
? image.toString()
: "https://pbs.twimg.com/profile_images/916384996092448768/PF1TSFOE_400x400.jpg")),
),
),
),
new Padding(
padding:
const EdgeInsets.symmetric(vertical: 16.0, horizontal: 16.0),
child: new Text(
desc,
style: new TextStyle(
fontSize: 18.0,
),
),
),
],
))),
);
}
}
The problem log reads:
main.dart: Name non-constant identifiers using lowerCamelCase.
post_view.dart: This class (or a class which this class inherits from) is marked as '#immutable', but one or more of its instance fields are not final: PostView.desc, PostView.title, PostView.image
my editor marks class post on the post_view.dart as immutable.. how do i fix that.
final url =
"https://www.googleapis.com/blogger/v3/blogs/MY_BLOG_ID_HERE/posts/?key=API_KEY_HERE";
get your blog ID and put it into the required space and also get an API key for the blog from blogger
it should look like this
final url = "https://www.googleapis.com/blogger/v3/blogs/409370562475495748/posts/?key=AIzaSyA3_4OfkfLc10vy5Q2WeUhfirGUUY4J78F8bk";
also try to make these final PostView.desc, PostView.title, PostView.image and see if it works