Change Notifier Provider to add widget to Favourite Screen - flutter

I've made screen with details of movies and with favourite movies. Also I've got a list of movies. In Detail Screen, there is favourite icon. I want to make that when you tap on this Icon, I want to add this movie to Favourite Screen.
There is a list of movies.
class Movie {
String imgUrl;
String title;
String categories;
int year;
String country;
int length;
String description;
List<String> screenshots;
Movie({
required this.imgUrl,
required this.title,
required this.categories,
required this.year,
required this.country,
required this.length,
required this.description,
required this.screenshots,
});
}
final List<Movie> movies = [
Movie(
imgUrl:
'https://static.posters.cz/image/1300/plakaty/james-bond-no-time-to-die-profile-i114389.jpg',
title: 'No time to die',
categories: 'Adventure',
year: 2021,
country: 'USA/England',
length: 183,
description:
'James Bond has left active service. His peace is short-lived when Felix Leiter, an old friend from the CIA, turns up asking for help, leading Bond onto the trail of a mysterious villain armed with dangerous new technology.',
screenshots: [
'https://i.pinimg.com/originals/fd/5e/1d/fd5e1d8878c402aaba2fb6373e880b1f.webp',
'https://cdn.mos.cms.futurecdn.net/dNmCDjJT5G76aDKiYphTkF.jpg',
'https://i.imgur.com/Zm9X4lT.jpg',
'https://images.complex.com/complex/images/c_fill,f_auto,g_center,w_1200/fl_lossy,pg_1/knie3z7uwe3inyua5kft/no-time-to-die-04'
]),
]
There I've got Detail Screen.
class MovieScreen extends StatefulWidget {
final String photo, title, categories, country, description;
final int year, length;
final List<String> screenshots;
const MovieScreen(
{Key? key,
required this.photo,
required this.title,
required this.categories,
required this.year,
required this.country,
required this.description,
required this.length,
required this.screenshots})
: super(key: key);
#override
_MovieScreenState createState() => _MovieScreenState();
}
class _MovieScreenState extends State<MovieScreen> {
#override
Widget build(BuildContext context) {
final filmData = Provider.of<MovieProvider>(context);
final films = filmData.items;
return Scaffold(
backgroundColor: Colors.white,
body: ListView(
children: [
Stack(
children: [
Container(
transform: Matrix4.translationValues(0, -50, 0),
width: double.infinity,
child: Hero(
tag: widget.photo,
child: ClipShadowPath(
clipper: CircularClipper(),
shadow: Shadow(blurRadius: 20),
child: Image(
height: 400,
image: NetworkImage(widget.photo),
fit: BoxFit.cover,
),
),
),
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
IconButton(
padding: EdgeInsets.only(left: 20),
onPressed: () => Navigator.pop(context),
icon: Icon(Icons.arrow_back),
iconSize: 40,
),
IconButton(
padding: EdgeInsets.only(right: 20),
onPressed: () {},
icon: Icon(Icons.favorite_outline),
iconSize: 30,
color: Colors.red,
),
],
),
],
),
],
),
);
}
}
There is Favourite Screen.
class MyList extends StatefulWidget {
#override
_MyListState createState() => _MyListState();
}
class _MyListState extends State<MyList> {
#override
Widget build(BuildContext context) {
return Scaffold(
body: Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Navbar1(),
Container(
width: MediaQuery.of(context).size.width - 60,
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 10),
child: ListView(
children: <Widget>[
SizedBox(
height: 50,
),
HeadMenuMylist(),
SizedBox(
height: 20,
),
GridView.count(
shrinkWrap: true,
physics: NeverScrollableScrollPhysics(),
mainAxisSpacing: 10,
crossAxisSpacing: 10,
crossAxisCount: 2,
childAspectRatio: 1 / 2,
children: [
Stack(
children: [
Positioned.fill(
child: Container(
height: 200,
foregroundDecoration: BoxDecoration(
borderRadius: BorderRadius.circular(10),
gradient: LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: [Colors.transparent, Colors.black],
),
),
child: ClipRRect(
borderRadius: BorderRadius.circular(10),
child: Image.network(imgUrl
,
loadingBuilder: (BuildContext context,
Widget child,
ImageChunkEvent? loadingProgress) {
if (loadingProgress == null) return child;
return Center(
child: SizedBox(
height: 50,
width: 50,
child: CircularProgressIndicator(
strokeWidth: 4,
color: Colors.red,
),
),
);
},
fit: BoxFit.cover,
),
),
),
),
Padding(
padding: const EdgeInsets.only(bottom: 15),
child: Align(
alignment: Alignment.bottomCenter,
child: Text(
'Peaky Blinders',
style: GoogleFonts.openSans(
color: Colors.white,
fontSize: 18,
fontWeight: FontWeight.w700),
),
),
),
Padding(
padding: const EdgeInsets.only(top: 10, right: 10),
child: Align(
alignment: Alignment.topRight,
child: GestureDetector(
onTap: () {},
child: Icon(
Icons.delete,
color: Colors.white,
),
)),
),
],
),
],
),
],
),
),
),
],
),
);
}
}
I tried with Change Notifier Provider but it doesn't work and I don't have clue why it didn't work. Is there something else I can use instead Change Notifier Provider?
Thanks for help.

if you want to save the favorite movie of a user permanently, then you have to save the JSON data in firestore database.
Create a function to store the favorite movie json data to firestore, i,e , store the json data to collection like;
saveFavrotiesMovies() async {
final User user = auth.currentUser;
final uid = user.uid;
try {
await FirebaseFirestore.instance
.collection('Favorite Movies')
.doc()
.collection(uid.toString())
.doc()
.set(
movies.toJson());
print('data adedd succesfullyyyyyy');
} catch (e, s) {
print("#DatabaseService Exception IN ADDNG FAVOTRITE DATA $e");
print(s);
}
}
This function store the favorite movie of a specific user in his/her collection
Retrive and the Favorite movie json data of a user from the Firestore database using a function in same manner as will do in storing the favorite data, and display the data in the Favorite Screen

Related

How do I make it so that when I click an icon it opens another page file in flutter

How do I make it so that when I click an icon it opens another page file in flutter? I have this icons which when you click them it redirects you to a url, I want to make it so when you click one specific icon instead of opening a url it opens another page file, acting like a navigator.push...
But when I add an ontap to my taskcard I get an error, I had set the pageUrl = "", but it didn't return anything so I removed the this.required pageUrl and changed to this.pageUrl and now I have this error The parameter 'pageUrl' can't have a value of 'null' because of its type, but the implicit default value is 'null', my code is like this:
import 'dart:ui';
import 'package:url_launcher/url_launcher.dart';
import '';
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:schoolmanagement/nav_bar.dart';
class DinningScreen extends StatefulWidget {
const DinningScreen({super.key});
#override
State<DinningScreen> createState() => _DinningState();
}
class _DinningState extends State<DinningScreen> {
final GlobalKey<ScaffoldState> scaffoldKey = GlobalKey();
#override
Widget build(BuildContext context) {
return Scaffold(
drawer: NavBar(),
key: scaffoldKey,
appBar: AppBar(...),
body: Container(
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [Color(0xffF6FECE), Color(0xffB6C0C8)],
begin: Alignment.bottomCenter,
end: Alignment.topCenter,
tileMode: TileMode.clamp),
),
//Here we set the "Manage your ... box and it's properties"
padding: const EdgeInsets.all(12.0),
child: SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(...),
SizedBox(
height: 20.0,
),
Text(
"Sections",
style: TextStyle(
fontSize: 20.0,
fontWeight: FontWeight.bold,
fontFamily: "SpaceGrotesk",
color: Colors.black),
),
//Here we set the "Shortcuts"
//If you click Teachers it will take you the page where you can see the Teachers -
//names a nd availabity alongs side the subject they teach
//If you click EduPage it takes you to edupage
//If you click Timetable it takes you to the Timetable generator
//If you click Messages it asks you to join a messenger Gc of Students of your class
Row(
children: [
Expanded(
child: TaskCard(
label: "Teachers",
pageUrl: "",
)),
Expanded(
child: TaskCard(
imageUrl: "assets/school-bag.png",
label: "EduPage",
pageUrl: "https://willowcosta.edupage.org",
)),
//This is what I want to change from going to url to another page
Expanded(
child: InkWell(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => HomeScreen()),
);
},
child: TaskCard(
imageUrl: "assets/timetable.png",
pageUrl: "",
label: "Timetable",
),
)),
Expanded(
child: TaskCard(
imageUrl: "assets/message.png",
pageUrl: "https://www.messenger.com",
label: "Messages",
)),
],
),
//Here we set the tasks that we have
const SizedBox(
height: 20.0,
),
const Text(
"You have 6 tasks for this week",
style: TextStyle(
fontSize: 20.0,
fontWeight: FontWeight.bold,
fontFamily: "SpaceGrotesk",
color: Colors.black),
),
const TaskContainer(),
const TaskContainer(),
const TaskContainer(),
const TaskContainer(),
const TaskContainer(),
const TaskContainer(),
const SizedBox(
height: 100.0,
),
],
),
),
),
The TaskCard definition is here:
class TaskCard extends StatelessWidget {
final String? imageUrl;
final String? label;
final String pageUrl;
const TaskCard(
{Key? key, this.imageUrl, required this.label, required this.pageUrl})
: super(key: key);
//Function to launch the selected url
Future<void> goToWebPage(String urlString) async {
final Uri _url = Uri.parse(urlString);
if (!await launchUrl(_url)) {
throw 'Could not launch $_url';
}
}
#override
Widget build(BuildContext context) {
return Padding(
//Here we set the properties of our Sections (Teachers etc)
padding: const EdgeInsets.all(8.0),
child: Column(
children: [
Container(
height: 80.0,
width: 76.1,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(20.0),
boxShadow: [
BoxShadow(
color: Colors.grey, blurRadius: 2.0, spreadRadius: 0.5),
]),
child: IconButton(
onPressed: () async {
if(pageUrl !=""){
await goToWebPage(pageUrl);
}
},
icon: Image.asset(
imageUrl ?? "assets/teacher.png",
height: 75.0,
width: 70.0,
),
),
),
SizedBox(
height: 10.0,
),
Text(
label ?? "",
style: TextStyle(fontSize: 16.0),
)
],
),
);
}
}
The parameter 'pageUrl' can't have a value of 'null' because of its
type, but the implicit default value is 'null'.
Check whether the pageUrl is an empty String. If it is an empty String, don't call goToWebPage.
onPressed: () async {
if(pageUrl !=""){
await goToWebPage(pageUrl);
}
},

VideoPlayer working locally but is only playing audio in production

Im using the videoPlayer package and it has been working perfectly until i decided to change the format of the video to take height: MediaQuery.of(context).size.height and now it suddenly only plays the audio in production while working perfectly on my local device.
I have posten the full code below along with an image displaying what the error looks like enter image description here
class InspoDescription extends StatefulWidget {
String id;
String title;
String image;
String name;
String tag;
String description;
String video;
InspoDescription(
{required this.id,
required this.title,
required this.image,
required this.name,
required this.tag,
required this.description,
required this.video});
#override
State<InspoDescription> createState() => _InspoDescriptionState();
}
class _InspoDescriptionState extends State<InspoDescription> {
VideoPlayerController? controller;
#override
void initState() {
controller = VideoPlayerController.network(widget.video)
..addListener(() => setState(() {}))
..setLooping(true)
..initialize().then((value) => controller!.play());
super.initState();
}
#override
void dispose() {
controller!.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return Scaffold(
extendBodyBehindAppBar: true,
appBar: AppBar(
elevation: 0,
backgroundColor: Colors.transparent,
),
body: SingleChildScrollView(
child: Column(
children: [
controller!.value.isBuffering
? SizedBox(
width: double.infinity,
height: MediaQuery.of(context).size.height,
child: const Center(
child: CircularProgressIndicator(),
),
)
: Positioned.fill(
child: GestureDetector(
onTap: () => controller!.value.isPlaying
? controller!.pause()
: controller!.play(),
child: SizedBox(
width: double.infinity,
height: MediaQuery.of(context).size.height,
child: Stack(
children: [
VideoPlayer(controller!),
controller!.value.isPlaying
? Container()
: const Align(
alignment: Alignment.center,
child: Icon(
Icons.play_arrow_rounded,
size: 100,
color: Color.fromRGBO(255, 255, 255, 0.6),
),
),
const Align(
alignment: Alignment.bottomCenter,
child: Icon(
Icons.arrow_drop_down_sharp,
size: 100,
color: Color.fromRGBO(255, 255, 255, 0.6),
),
)
],
),
),
),
),
ExploreHeadline(
name: widget.name,
tag: widget.tag,
title: widget.title,
description: widget.description,
),
StreamBuilder<InspoModel>(
stream: Inspo().getCurrentExplorePage(widget.id),
builder: (context, snapshot) {
if (snapshot.hasError) {
return Text('Something went wrong ${snapshot.error}');
} else if (snapshot.hasData) {
final inspo = snapshot.data;
List<ProductModel> products = [];
inspo!.products.forEach(
(element) {
ProductModel product = ProductModel.fromJson(element);
products.add(product);
},
);
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 20),
child: GridView.builder(
itemCount: products.length,
shrinkWrap: true,
itemBuilder: (context, index) => Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Flexible(
child: GestureDetector(
onTap: () => Navigator.of(context).push(
CustomPageRoute(
child: ProductDescription(
sub_cat_id: products[index].id,
productId: products[index].id,
description: products[index]
.description,
details: products[index].details,
productImage: products[index].image,
productName: products[index].title,
productPrice: products[index].price,
cartQuantity:
products[index].cartQuantity,
categoryId:
products[index].category_id,
subTitle: products[index].subTitle,
inventory:
products[index].inventory))),
child: Container(
padding: const EdgeInsets.all(20),
decoration: BoxDecoration(
color: Colors.grey[100],
borderRadius: BorderRadius.circular(16),
),
child: Stack(
children: [
Align(
alignment: Alignment.center,
child: CachedNetworkImage(
imageUrl: products[index].image,
),
),
],
),
),
),
),
Text(
products[index].title,
style: TextStyle(
color: Colors.grey[500],
fontWeight: FontWeight.w400),
),
Text(
products[index].subTitle,
),
Text(
'${products[index].price} kr',
)
],
),
gridDelegate:
const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
childAspectRatio: 0.75,
crossAxisSpacing: 20,
mainAxisSpacing: 20,
),
),
);
} else {
return const CircularProgressIndicator();
}
}),
],
),
),
);
}
}
Video on local device
Full page on local device

News pages doesn't show article or blogs after building apk

I'm creating a flutter project on which it consist of news feature sadly after building an apk and installing it to try in become an empty screen with grey shade, i also try to test it on my phone and this is what happen i dont know where the bugs came from.. please help me
here's the code
import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:google_mobile_ads/google_mobile_ads.dart';
import 'Article_View.dart';
import 'News_Categories.dart';
import 'helper/Data.dart';
import 'helper/News.dart';
import 'model/Article_Model.dart';
import 'model/CategoryModel.dart';
class NewsHomePage extends StatefulWidget {
#override
_NewsHomePageState createState() => _NewsHomePageState();
}
class _NewsHomePageState extends State<NewsHomePage> {
List<CategoryModel> categories = <CategoryModel>[];
List<ArticleModel> articles = <ArticleModel>[];
bool _loading = true;
//bannerads
late BannerAd _bannerads;
bool _isAdsLoaded = false ;
#override
void initState() {
// TODO: implement initState
super.initState();
categories = getCategories();
getNews();
_initBannerAds();
}
getNews() async {
News newsClass = News();
await newsClass.getNews();
articles = newsClass.news;
setState(() {
_loading = false;
});
}
_initBannerAds(){
_bannerads = BannerAd(
size: AdSize.banner,
// ignore: deprecated_member_use
adUnitId: "ca-app-pub-8634651641429291/4830511818",
listener: BannerAdListener(
onAdLoaded: (ad){
setState(() {
_isAdsLoaded =true;
});
},
onAdFailedToLoad: (ad,error){}
),
request: const AdRequest()
);
_bannerads.load();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.green,
elevation: 0.0,
title: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: const [
Text('Stock '),
Text(
'News',
style: TextStyle(
color: Colors.black54,
),
),
],
),
centerTitle:true,
bottom: const PreferredSize(
preferredSize: Size.zero,
child: Text("Powered by news.org")),
),
body: _loading
? Container(
child: const Center(
child: CircularProgressIndicator(),
),
)
: SingleChildScrollView(
child: Container(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
///Categories
Container(
padding: const EdgeInsets.symmetric(horizontal: 22.0),
height: 90.0,
child: Expanded(
child: ListView.builder(
itemCount: categories.length,
scrollDirection: Axis.horizontal,
shrinkWrap: true,
itemBuilder: (context, index) {
return CategoryTile(
imageUrl: categories[index].imageAssetUrl,
categoryName: categories[index].categoryName,
);
}),
),
),
///Blogs
Container(
padding: const EdgeInsets.only(top: 16.0),
child: Expanded(
child: ListView.builder(
physics: const ClampingScrollPhysics(),
shrinkWrap: true,
itemCount: articles.length,
itemBuilder: (context, index) {
return BlogTile(
imageURL: articles[index].urlToImage,
title: articles[index].title,
desc: articles[index].description,
url: articles[index].url,
);
},
),
),
),
],
),
),
),
bottomNavigationBar: _isAdsLoaded?SizedBox(
height: _bannerads.size.height.toDouble(),
width: _bannerads.size.width.toDouble(),
child: AdWidget(ad: _bannerads),
)
:const SizedBox(),
);
}
}
class CategoryTile extends StatelessWidget {
final String imageUrl, categoryName;
const CategoryTile({required this.imageUrl, required this.categoryName});
#override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => CategoryNews(
category: categoryName.toLowerCase(),
),
),
);
},
child: Container(
margin: EdgeInsets.only(right: 10.0),
child: Stack(
children: [
ClipRRect(
borderRadius: BorderRadius.circular(6),
child: imageUrl != null
? CachedNetworkImage(
imageUrl: imageUrl,
width: 120,
height: 60.0,
fit: BoxFit.cover,
)
: Image.network(
imageUrl,
width: 120.0,
height: 60.0,
fit: BoxFit.cover,
),
),
Container(
alignment: Alignment.center,
decoration: BoxDecoration(
color: Colors.black26,
borderRadius: BorderRadius.circular(6),
),
width: 120,
height: 60.0,
child: Text(
categoryName,
style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.w500,
fontSize: 18.0,
),
),
),
],
),
),
);
}
}
class BlogTile extends StatelessWidget {
final String imageURL, title, desc, url;
BlogTile(
{required this.imageURL,
required this.title,
required this.desc,
required this.url});
#override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => ArticleView(
blogUrl: url,
)),
);
},
child: Container(
margin: const EdgeInsets.only(bottom: 16.0, left: 10.0, right: 10.0),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
ClipRRect(
borderRadius: BorderRadius.circular(6.0),
child: imageURL != null
? CachedNetworkImage(
imageUrl: imageURL,
)
: Image.network(imageURL),
),
const SizedBox(
height: 8.0,
),
Text(
title,
style: const TextStyle(
//color: Colors.black87,
fontSize: 17.0,
fontWeight: FontWeight.w500,
),
),
const SizedBox(
height: 8.0,
),
Text(
desc,
style: const TextStyle(
//color: Colors.black54,
),
),
],
),
),
);
}
}
and here's the screen shots of the app
[![debugging app][1]][1]
[![build app][2]][2]
[1]: https://i.stack.imgur.com/tvBsG.jpg
[2]: https://i.stack.imgur.com/wOuxS.jpg
Check if this line exists in android/app/src/main/AndroidManifest.xml file. If it doesn't add it right below the package name line. This will grant the app INTERNET permission so it can access it & display the data from the internet.
<uses-permission android:name="android.permission.INTERNET"/>
Flutter by default only adds the INTERNET permission in debug mode. When you build an APK in release mode, you have to explicitly add the permission by including the above line.
More info here.

How to fetch data (Text) from Website in Flutter / dart?

So, I'm pretty new on Flutter (just about a week) and dart but I hope this Question is not toooooo stupid:
I'm trying to create an App for an existing Website (a forum). I dont want to use the flutter WebView, because I want to create an comepletly new Interface (The Website is not optimized for mobile View, that's why I'm builing this App).
The (german) Forum:
https://www.porsche-914.com/forum
I want to fetch the single forum topics as well as the posts itself including username, title and date and then map the text to a custom widget to display it. The Widget Part is no problem, it's already done but I cant figure out how to fetch that data from the website and how to store it.
I don't know, hope you can help me...
Thanks a lot for the taken time.
How the mapping should work:
fetched[index].title, fetched[index].text
Center(
child: NeumorphismPost(
title: fetched[index].title,
titleColor: Theme.of(context).cardColor,
textColor: Theme.of(context).cardColor,
text: fetched[index].text,
width: 370,
onTap: () {
_popupPage(context,
title: fetched[index].title,
child: Padding(
padding: const EdgeInsets.all(15.0),
child: Text(
fetched[index].text,
style: TextStyle(
color: Theme.of(context).cardColor,
fontSize: 18),
),
),
);
},
),
),
This is my custom Widget:
import 'package:flutter/material.dart';
class NeumorphismPost extends StatefulWidget {
final double width;
final double height;
final double borderRadius;
final String title;
final String text;
final Color titleColor;
final Color textColor;
final double titleSize;
final double textSize;
final Function onTap;
NeumorphismPost({
this.width = 185,
this.height = 185,
this.title = "Title",
this.text = "",
this.borderRadius = 20,
this.titleColor = const Color(0xFF424242),
this.textColor = const Color(0xFF424242),
this.titleSize = 22,
this.textSize = 18,
required this.onTap,
});
#override
State<NeumorphismPost> createState() => _NeumorphismPostState();
}
class _NeumorphismPostState extends State<NeumorphismPost> {
#override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.all(8.0),
child: Wrap(
direction: Axis.vertical,
children: [
SingleChildScrollView(
child: SizedBox(
height: widget.height,
width: widget.width,
child: GestureDetector(
onTap: () {},
child: Scaffold(
backgroundColor: Colors.transparent,
body: SizedBox(
height: widget.height,
width: widget.width,
child: Center(
child: Container(
height: widget.height,
width: widget.width,
decoration: BoxDecoration(
color: Theme.of(context).backgroundColor,
borderRadius:
BorderRadius.circular(widget.borderRadius),
boxShadow: [
BoxShadow(
color: Theme.of(context).hintColor,
offset: const Offset(5, 5),
blurRadius: 15,
spreadRadius: 1,
),
BoxShadow(
color: Theme.of(context).backgroundColor,
offset: Offset(-5, -5),
blurRadius: 15,
spreadRadius: 1,
)
],
),
child: Wrap(
direction: Axis.horizontal,
children: [
SingleChildScrollView(
child: Center(
child: Column(
mainAxisAlignment:
MainAxisAlignment.spaceEvenly,
children: <Widget>[
Wrap(
direction: Axis.horizontal,
children: [
SizedBox(
height: widget.height / 3,
child: Wrap(
children: [
Column(
mainAxisAlignment:
MainAxisAlignment.start,
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
Padding(
padding: const EdgeInsets
.symmetric(
horizontal: 15,
vertical: 15),
child: Text(
widget.title,
textAlign:
TextAlign.center,
overflow:
TextOverflow.fade,
style: TextStyle(
fontSize:
widget.titleSize,
fontWeight:
FontWeight.bold,
color:
widget.titleColor,
),
),
),
],
),
],
),
),
],
),
Wrap(
direction: Axis.horizontal,
children: [
GestureDetector(
onTap: () {
widget.onTap();
},
child: Padding(
padding: const EdgeInsets.symmetric(
vertical: 5),
child: SizedBox(
height: widget.height / 1.38,
child: Padding(
padding:
const EdgeInsets.symmetric(
horizontal: 15,
vertical: 15),
child: Text(
widget.text,
textAlign: TextAlign.center,
style: TextStyle(
fontSize: widget.textSize,
fontWeight:
FontWeight.normal,
color: widget.textColor,
),
),
),
),
),
),
],
),
],
),
),
),
],
),
),
),
),
),
),
),
),
],
),
);
}
}
From my point of view, you want to create a scraper. I checked the target website (https://www.porsche-914.com/forum), it can be scraped without any special technique (they don't have many Ajax calls (you may test by using Postman)). So it is a possible task. My suggestion flow is:
Load the raw HTML using any technique (http, dio, inappwebview ...)
Parse it using BeautifulSoup (https://pub.dev/packages/beautiful_soup_dart) (or any parser; it is just my favorite parser.)
Map it to your existing model.
Here is some example code. Hope it helps:
import 'package:http/http.dart' as http;
import 'package:beautiful_soup_dart/beautiful_soup.dart';
class TestParse {
excuteSample() async {
var url = Uri.parse('https://www.porsche-914.com/forum');
var response = await http.get(url);
BeautifulSoup bs = BeautifulSoup(response.body);
final allHeaderName = bs.findAll('td', attrs: {'class': 'oben'});
allHeaderName.forEach((element) {
print('the header: ${element.text}');
});
}
}
Here is the result:
The final result you need is a long story and long code. Hope this will give you a starting point.
UPDATE: I added the full demo code, using your requested code:
import 'package:beautiful_soup_dart/beautiful_soup.dart';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
void main() => runApp(const MaterialApp(home: MyApp()));
class MyApp extends StatefulWidget {
const MyApp({Key? key}) : super(key: key);
#override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
final testparse = TestParse();
List<String> yourModelPleaseReplaceThis = [];
#override
void initState() {
super.initState();
excuteRequestAndParse();
}
excuteRequestAndParse() async {
final result =
await testparse.excuteSample(); //[1] i guess you missing this await
setState(() {
yourModelPleaseReplaceThis = result;
});
}
#override
Widget build(BuildContext context) {
return ListView.builder(
itemBuilder: (context, index) {
return Center(
child: NeumorphismPost(
title: yourModelPleaseReplaceThis[index],
titleColor: Theme.of(context).cardColor,
textColor: Theme.of(context).cardColor,
text: yourModelPleaseReplaceThis[index],
width: 370,
onTap: () {
//THIS CODE BELOW IS YOUR CODE....
},
),
);
},
itemCount: yourModelPleaseReplaceThis.length,
);
}
}
// BELOW IS TESTING CODE....
class TestParse {
Future<List<String>> excuteSample() async {
var url = Uri.parse('https://www.porsche-914.com/forum');
var response = await http.get(url);
BeautifulSoup bs = BeautifulSoup(response.body);
final allHeaderName = bs.findAll('td', attrs: {'class': 'oben'});
allHeaderName.forEach((element) {
print('the header: ${element.text}');
});
return Future.value(allHeaderName.map((e) => e.text).toList());
}
}
class NeumorphismPost extends StatefulWidget {
final double width;
final double height;
final double borderRadius;
final String title;
final String text;
final Color titleColor;
final Color textColor;
final double titleSize;
final double textSize;
final Function onTap;
NeumorphismPost({
this.width = 185,
this.height = 185,
this.title = "Title",
this.text = "",
this.borderRadius = 20,
this.titleColor = const Color(0xFF424242),
this.textColor = const Color(0xFF424242),
this.titleSize = 22,
this.textSize = 18,
required this.onTap,
});
#override
State<NeumorphismPost> createState() => _NeumorphismPostState();
}
class _NeumorphismPostState extends State<NeumorphismPost> {
#override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.all(8.0),
child: Wrap(
direction: Axis.vertical,
children: [
SingleChildScrollView(
child: SizedBox(
height: widget.height,
width: widget.width,
child: GestureDetector(
onTap: () {},
child: Scaffold(
backgroundColor: Colors.transparent,
body: SizedBox(
height: widget.height,
width: widget.width,
child: Center(
child: Container(
height: widget.height,
width: widget.width,
decoration: BoxDecoration(
color: Theme.of(context).backgroundColor,
borderRadius:
BorderRadius.circular(widget.borderRadius),
boxShadow: [
BoxShadow(
color: Theme.of(context).hintColor,
offset: const Offset(5, 5),
blurRadius: 15,
spreadRadius: 1,
),
BoxShadow(
color: Theme.of(context).backgroundColor,
offset: Offset(-5, -5),
blurRadius: 15,
spreadRadius: 1,
)
],
),
child: Wrap(
direction: Axis.horizontal,
children: [
SingleChildScrollView(
child: Center(
child: Column(
mainAxisAlignment:
MainAxisAlignment.spaceEvenly,
children: <Widget>[
Wrap(
direction: Axis.horizontal,
children: [
SizedBox(
height: widget.height / 3,
child: Wrap(
children: [
Column(
mainAxisAlignment:
MainAxisAlignment.start,
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
Padding(
padding: const EdgeInsets
.symmetric(
horizontal: 15,
vertical: 15),
child: Text(
widget.title,
textAlign:
TextAlign.center,
overflow:
TextOverflow.fade,
style: TextStyle(
fontSize:
widget.titleSize,
fontWeight:
FontWeight.bold,
color:
widget.titleColor,
),
),
),
],
),
],
),
),
],
),
Wrap(
direction: Axis.horizontal,
children: [
GestureDetector(
onTap: () {
widget.onTap();
},
child: Padding(
padding: const EdgeInsets.symmetric(
vertical: 5),
child: SizedBox(
height: widget.height / 1.38,
child: Padding(
padding:
const EdgeInsets.symmetric(
horizontal: 15,
vertical: 15),
child: Text(
widget.text,
textAlign: TextAlign.center,
style: TextStyle(
fontSize: widget.textSize,
fontWeight:
FontWeight.normal,
color: widget.textColor,
),
),
),
),
),
),
],
),
],
),
),
),
],
),
),
),
),
),
),
),
),
],
),
);
}
}
This is the result:
Please note:
This list I created is for sample, so it is just a list of Strings. You should create a complete Model.

add profile picture on on pressed flutter

i created a designed profile page for users i need a help to code a function to let the users select photo from their device when the click on my add button and i need to save that image data to my database
i just need to open up gallery and let the user select photo and it should save to my data base when she click on add button
this is the code of my profile page
class ProfileWidget extends StatefulWidget {
final GlobalKey<ScaffoldState> parentScaffoldKey;
ProfileWidget({Key key, this.parentScaffoldKey}) : super(key: key);
#override
_ProfileWidgetState createState() => _ProfileWidgetState();
}
class _ProfileWidgetState extends StateMVC<ProfileWidget> {
ProfileController _con;
_ProfileWidgetState() : super(ProfileController()) {
_con = controller;
}
#override
Widget build(BuildContext context) {
return Scaffold(
key: _con.scaffoldKey,
body: currentUser.value.apiToken == null
? PermissionDeniedWidget()
: SingleChildScrollView(
// padding: const EdgeInsets.symmetric(horizontal: 0, vertical: 10),
child: Column(
children: <Widget>[
ProfileAvatarWidget(user: currentUser.value),
ListTile(
contentPadding: EdgeInsets.symmetric(horizontal: 20, vertical: 10),
leading: Icon(
Icons.shopping_basket,
color: Theme.of(context).hintColor,
),
title: Text(
S.of(context).recent_orders,
style: Theme.of(context).textTheme.headline4,
),
),
_con.recentOrders.isEmpty
? EmptyOrdersWidget()
: ListView.separated(
scrollDirection: Axis.vertical,
shrinkWrap: true,
primary: false,
itemCount: _con.recentOrders.length,
itemBuilder: (context, index) {
var _order = _con.recentOrders.elementAt(index);
return OrderItemWidget(expanded: index == 0 ? true : false, order: _order);
},
separatorBuilder: (context, index) {
return SizedBox(height: 20);
},
),
],
),
),
);
}
}
code of profile avatar widget
class ProfileAvatarWidget extends StatelessWidget {
final User user;
ProfileAvatarWidget({
Key key,
this.user,
}) : super(key: key);
#override
Widget build(BuildContext context) {
return Container(
padding: EdgeInsets.symmetric(vertical: 30),
decoration: BoxDecoration(
color: Theme.of(context).accentColor,
borderRadius: BorderRadius.only(bottomLeft: Radius.circular(30), bottomRight: Radius.circular(30)),
),
child: Column(
children: <Widget>[
Container(
height: 160,
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
SizedBox(
width: 50,
height: 50,
child: FlatButton(
padding: EdgeInsets.all(0),
onPressed: () {},
child: Icon(Icons.add, color: Theme.of(context).primaryColor),
color: Theme.of(context).accentColor,
shape: StadiumBorder(),
),
),
ClipRRect(
borderRadius: BorderRadius.all(Radius.circular(300)),
child: CachedNetworkImage(
height: 135,
width: 135,
fit: BoxFit.cover,
imageUrl: user.image?.url,
placeholder: (context, url) => Image.asset(
'assets/img/loading.gif',
fit: BoxFit.cover,
height: 135,
width: 135,
),
errorWidget: (context, url, error) => Icon(Icons.error),
),
),
Users dart
import '../helpers/custom_trace.dart';
import '../models/media.dart';
enum UserState { available, away, busy }
class User {
String id;
String name;
String email;
String password;
String apiToken;
String deviceToken;
String phone;
String address;
String bio;
Media image;