Add favorite button to list by provider to flutter app

Add favorite button to list by provider to flutter app

شرح اضافة favorite button الى flutter app بواسطة ال Provider 

Add favorite button to list by provider to flutter app

شرح الموضوع على الفيديو:



نبذه عن التطبيق:

عبارة عن تطبيق يحتوي على عدة قوائم تحتوي على عنوان و وصف قصير حول الموقع وصورة الموقع والرابط الخاص بها وعند الضغط على اي قائمة تنتقل الى موقع الخاص بها   مضاف اليها  ايقونة عند الضغط عليها يظهر لك Dialog  ل اضافة زر المفضلة مع ايقونة بعداد لتحديد عدد القوائم  ,  بحيث بستطاعتك اضافة اي قايمة الى صفحة المفضلة  والاطلاع عليها في وقت اخر.





1- نقوم باضافة حزمة Provaider لملف pubspace.yaml

dependencies:
provider: ^5.0.0


2- انشاء مجلد من نوع Directory :

ونسمية ب assets واضافة الصور التي تريد استخدامها  داخلة ثم الذهاب الى ملف pubspace.yaml وتحرير مستودع استدعاء الصور ثم كتابة مسار واسم كل صورة  مع صيغتها



3- انشاء ملف ب اسم item_model  ثم نقوم ب انشاء كلاس ب اسم ItemModel من نوع ChangeNotifier 

 ثم نضيف داخلة العناصر المطلوب عرضها  ثم تعريفها 

class ItemModel with ChangeNotifier {
final String title;
final String describtion;
final String url;
final String id;
final String image;

ItemModel({
this.id,
this.title,
this.describtion,
this.url,
this.image,
});
}


4- انشاء ملف ب اسم model_favorite ثم نقوم ب انشاء كلاس  ب اسم FavoriteModel من نوع ChangeNotifier

 ثم نضيف داخلة نفس العناصر السابقة مع اضافة عنصر جديد ب اسم itemsId ثم نقوم بتعريفعا

class FavoriteModel with ChangeNotifier {
final String title;
final String describtion;
final String url;
final String id;
final String itemsId;
final String image;

FavoriteModel(
{this.id,
@required this.itemsId,
this.title,
this.describtion,
this.url,
this.image});
}


5- انشاء ملف جديد ب اسم items_provider ثم ثم نقوم ب انشاء كلاس  ب اسم ItemsProvider من نوع ChangeNotifier 

class ItemsProvider with ChangeNotifier {}


ثم ننشى داخل الكلاس قايمة بنفس العناصر التي تم تعريفها في كلاس ItemModel  مع اضافة البيانات الخاصة بها 

List<ItemModel> _provideritems = [
ItemModel(
id: '',
title: '',
describtion: '',
image: '',
url: '',
),];


نقوم ب استدعاء  كلاس model_items


قم بتكرار القايمة بالعدد الذي المطلوب ثم قم بتعبية البيانات الخاصة بك كما في المثال  بالاسفل بشرط الا  تتشابة قيم id يجب ان تاخذ كل id قيمة مختلفة

ItemModel(
id: '1-T1',
title: 'flutter',
describtion:
'Flutter SDK is Google UI toolkit for crafting beautiful, natively compiled applications for mobile, web, and desktop from a single codebase.',
image: 'assets/flutter.png',
url: 'https://flutter.dev/',
),


ثم نكتب كود الحصول على قايمة ItemModel بواسطة get

List<ItemModel> get provideritems {
return [..._provideritems];
}


ثم نكتب كود العثور على عناصر قايمة ItemModel بواسطة itemId

ItemModel findById(String itemId) {
return _provideritems.firstWhere((element) => element.id == itemId);
}


6- انشاء ملف جديد ب اسم favorite_provider ثم نقوم ب انشاء كلاس  ب اسم FavoriteProvider من نوع ChangeNotifier

class FavoriteProvider with ChangeNotifier {}

 

ثم نقوم بتعريف  favoriteItems  داخل Map 

Map<String, FavoriteModel> _favoriteItems = {};



ثم ننشى داخل الكلاس  كود الحصول على قايمة favoriteItems بواسطة get

Map<String, FavoriteModel> get getFavoriteItems {
return {..._favoriteItems};
}


ثم نقوم ب استدعاء  كلاس model_favorite


ثم نظيف وظيفة void addItemToFavorite  وتعريف العناصر الخاصة بها مع اضافة الاداة الشرطية if and elso

void addItemToFavorite(
String itemId,
String name,
String url,
String describtion,
String image,
) {
if (_favoriteItems.containsKey(itemId)) {
_favoriteItems.update(
itemId,
(exitingFavoriteItem) => FavoriteModel(
id: exitingFavoriteItem.id,
itemsId: exitingFavoriteItem.itemsId,
title: exitingFavoriteItem.title,
describtion: exitingFavoriteItem.describtion,
url: exitingFavoriteItem.url,
image: exitingFavoriteItem.image));
} else {
_favoriteItems.putIfAbsent(
itemId,
() => FavoriteModel(
id: DateTime.now().toString(),
itemsId: itemId,
title: name,
describtion: describtion,
url: url,
image: image));
}
notifyListeners();
}


ثم نظيف الكود المسول عن ازالة العنصر من قايمة المفضلة

void removeItem(String itemId) {
_favoriteItems.remove(itemId);
notifyListeners();
}


بعد ذلك نظيف الكود المسول عن ازالة كل العنصر من قايمة المفضلة 

void clearItem() {
_favoriteItems.clear();
notifyListeners();
}


7- ننتقل لملف main.dart

 ونقوم بلصق الكود الاتي

import 'package:flutter/material.dart';

void main() {
runApp(MyApp());
}

class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Provider Demo',
theme: ThemeData.light(),
home: Home(),

);
}
}


ثم نضيف  خاصية MultiProvider و نظيف الكلاسين التابعين لل Provider

 [FavoriteProvider + ItemsProvider] بعمل  Wrap with widget لل MaterialApp ولصق الكود التالي

MultiProvider(
providers: [
ChangeNotifierProvider<ItemsProvider>(
create: (context) => ItemsProvider(),
),
ChangeNotifierProvider<FavoriteProvider>(
create: (context) => FavoriteProvider(),
),
],


8- انشاء ملف جديد ب اسم home ثم ثم نقوم ب انشاء كلاس  ب اسم Home من نوع StatefulWidget 

class Home extends StatefulWidget {
// static const routeName = '/Home';
@override
_HomeState createState() => _HomeState();
}
class _HomeState extends State<Home> {
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.blue,
appBar: AppBar(
title: Text(
'Home',
style: TextStyle(color: Colors.white),
),
centerTitle: true,actions: [
  IconButton(
icon: Icon(
Icons.notification_add_rounded,
color: Colors.white,
),
onPressed: () {},
),],
),
);
}
}


نقوم بتعريف واستدعى كلا من ال [ itemsProvider + provideritems ]

final itemsProvider = Provider.of<ItemsProvider>(context);
List<ItemModel> itemsList = itemsProvider.provideritems;


نضيف داخل الكلاس Consumer خاص ب FavoriteProvider في Badge لاكن قبل ذلك يجب ان نستدعي حزمة Badges 

dependencies:
badges: ^2.0.1

Add favorite button to list by provider to flutter app


وهذا كود ال Consumer 

Consumer<FavoriteProvider>(
builder: (_, favorite, ch) => Badge(
badgeColor: Colors.white,
animationType: BadgeAnimationType.slide,
toAnimate: true,
position: BadgePosition.topEnd(top: 5, end: 7),
badgeContent: Text(
favorite.getFavoriteItems.length.toString(),
style: TextStyle(color: Colors.red),
),
child: IconButton(
icon: Icon(
Icons.favorite,
color: Colors.red,
),
// onPressed: () {
// Navigator.of(context).pushNamed(FavoriteScreen.routeName);
},
),
),
),


ثم ننشى ال body التابع للكلاس عن طريق اضافة GridView.coint والتي ستكون المسولة عن عرض عناصر ItemsProvider الموجودة في قايمة  itemsList  وذلك ب استدعاء قيمها عن طريق hangeNotifierProvider.value

body: GridView.count(
crossAxisCount: 1,
childAspectRatio: 1 / 0.6,
children: List.generate(itemsList.length, (index) {
return ChangeNotifierProvider.value(
value: itemsList[index],
);
}),
),


ثم نضيف child يحتوي على كلاس ب اسم HomeItems والذي سيحدد طريقة عرض كل عنصر 

child: HomeItems(),

Add favorite button to list by provider to flutter app


9- فتح ملف جديد  ب اسم home_items ثم  ننشى كلاس ب اسم HomeItems  من نوع StatefulWidget

import 'package:flutter/material.dart';

class HomeItems extends StatefulWidget {
@override
_HomeItemsState createState() => _HomeItemsState();
}

class _HomeItemsState extends State<HomeItems> {
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
width: 250,
height: 290,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10),
color: Colors.white,
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Stack(
children: [
ClipRRect(
borderRadius: BorderRadius.circular(2),
child: Container(
width: double.infinity,
height: MediaQuery.of(context).size.height * 0.15,
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage(''
// itemElements.image,
),
fit: BoxFit.contain,
),
),
),
),
],
),
],
),
FlatButton(
onPressed: () {
// _launchinbrowser(
// (itemElements.url),
// );
},
child: Container(
padding: EdgeInsets.only(left: 5),
margin: EdgeInsets.only(left: 5, bottom: 2, right: 3),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(
height: 4,
),
Container(
alignment: Alignment.center,
child: Text(
'',
// itemElements.title,
style: TextStyle(
fontSize: 20,
color: Colors.red,
fontWeight: FontWeight.w800),
),
),
Text(
'',
// itemElements.describtion,
style: TextStyle(
fontSize: 14,
color: Colors.black,
fontWeight: FontWeight.bold),
),
],
),
),
)
],
),
),
);
}
}


ثم نقوم  بتعريف  ال ItemModel

final itemElements = Provider.of<ItemModel>(context);


ثم نضيف العناصر ال ItemModel   داخل الكلاس 


نقوم ب استدعى حزمة Url_launcher في ملف pubspace.yaml من اجل فتح الروابط عند الضغط عليها  

dependencies:
url_launcher: ^6.0.9


نضيف معرف الحزمة

  Future<void> _launchinbrowser(String url) async {
if (await canLaunch(url)) {
await launch(url);
} else {
throw 'Could not launch $url';
}
}


ثم نقوم ب اضافة تصميم الايقونة الخاصة ب مربع الظهور او ما يسمى Dialog 

Padding(
padding: const EdgeInsets.symmetric(vertical: 8.0),
),
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Material(
color: Colors.transparent,
child: InkWell(
borderRadius: BorderRadius.circular(18.0),
child: Icon(
Icons.more_horiz_sharp,
color: Colors.blue,
)),
),
],
),


Add favorite button to list by provider to flutter app



اضافة كود  اظهار  القوايم الى مربع الظهور او ما يسمى  Dialog عن طريق InkWell والذي سيظهر اي قايمة تم اختيارها  عن طريق  ال itemId الخاص بها 

onTap: () async {
showDialog(
context: context,
builder: (BuildContext context) => FeedDialog(
itemId: itemElements.id,
),
);
},


10- نقوم بقتح ملف جديد  ب اسم feeds_dialog ثم  ننشى كلاس ب اسم  FeedDialog من نوع StatelessWidget

وهو المسول عن عرض القوايم في مربع الظهور او مايسمى Dialog 

import 'package:flutter/material.dart';

class FeedDialog extends StatelessWidget {
@override
Widget build(BuildContext context) {
return
}
}

نقوم  بتعريف المتغير itemId داخل الكلاس 

final String itemId;
const FeedDialog({@required this.itemId});


ثم نقوم بتعريف واستدعى كلا من ال

 [ FavoriteProvider+ itemId + ItemsProvider ]

final itemsData = Provider.of<ItemsProvider>(context, listen: false);

final favoriteProvider = Provider.of<FavoriteProvider>(context);
final itemElements = itemsData.findById(itemId);


نقوم بتصميم شكل مربع الظهور او مايسمى Dialog ثم نضيف العناصر الى التصميم 

Dialog(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(16),
),
elevation: 0.0,
backgroundColor: Colors.transparent,
child: SingleChildScrollView(
child: Column(children: [
Container(
constraints: BoxConstraints(
minHeight: 100,
maxHeight: MediaQuery.of(context).size.height * 0.2),
width: double.infinity,
decoration: BoxDecoration(
color: Theme.of(context).scaffoldBackgroundColor,
),
child: Image.asset(
'',
// itemElements.image,
fit: BoxFit.contain,
)),
Container(
padding: EdgeInsets.all(8),
color: Theme.of(context).scaffoldBackgroundColor,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'',
// itemElements.describtion,
maxLines: 2,
overflow: TextOverflow.ellipsis,
style: TextStyle(fontWeight: FontWeight.w600, fontSize: 15),
),
],
),
),
Container(
color: Theme.of(context).scaffoldBackgroundColor,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Flexible(
child: dialogContent(
context,
2,
favoriteProvider.getFavoriteItems.containsKey(itemId)
? () {}
: () {
favoriteProvider.addItemToFavorite(
itemId,
itemElements.describtion,
itemElements.url,
itemElements.title,
itemElements.image);
Navigator.canPop(context)
? Navigator.pop(context)
// ignore: unnecessary_statements
: null;
},
),
),
]),
),
Container(
margin: EdgeInsets.all(8),
decoration: BoxDecoration(
border: Border.all(color: Colors.white, width: 1.3),
shape: BoxShape.circle),
child: Material(
color: Colors.transparent,
child: InkWell(
borderRadius: BorderRadius.circular(30),
splashColor: Colors.grey,
onTap: () =>
Navigator.canPop(context) ? Navigator.pop(context) : null,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Icon(Icons.close, size: 28, color: Colors.white),
),
),
),
),
]),
),
);


Add favorite button to list by provider to flutter app


نقوم  بانشاء Widget ب اسم dialogContent 



Widget dialogContent(BuildContext context, int index, Function fct) {
return FittedBox(
child: Material(
color: Colors.transparent,
child: InkWell(
onTap: fct,
splashColor: Colors.grey,
child: Container(
width: MediaQuery.of(context).size.width * 0.25,
padding: EdgeInsets.all(4),
child: Column(
children: [
Container(
decoration: BoxDecoration(
color: Colors.white,
shape: BoxShape.circle,
boxShadow: [
BoxShadow(
color: Colors.black26,
blurRadius: 10.0,
offset: const Offset(0.0, 10.0),
),
],
),
),
SizedBox(
height: 20,
)
],
),
),
),
),
);
}


 ثم نقوم بتعريف واستدعى FavoriteProvider داخل ال Widget

final favorite = Provider.of<FavoriteProvider>(context);


ثم نقوم بتصميم شكل ايقونة المفضلة

child: ClipOval(
child: SizedBox(
width: 50,
height: 50,
child: Icon(
favorite.getFavoriteItems.containsKey(itemId)
? Icons.favorite
: Icons.favorite_border,
color: Colors.red,
size: 25,
),
),
),


11- نقوم ب اضافة ملف ب اسم dialog_methods يحتوي على كلاس ب اسم  DialogMethods 

وهو المسول عن تصميم شاشة  التحذير  للموافقة او الغاء  حذف عناصر المفضلة 

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';

class DialogMethods {
Future<void> showDialogg(String name, String describtion, Function fct,
BuildContext context) async {
showDialog(
context: context,
builder: (BuildContext ctx) {
return AlertDialog(
title: Row(
children: [
Expanded(
child: Icon(
Icons.warning,
color: Colors.red,
size: 50,
)),
Padding(
padding: const EdgeInsets.all(8.0),
child: Text(name),
),
],
),
content: Text(describtion),
actions: [
TextButton(
onPressed: () => Navigator.pop(context),
child: Text('cancel')),
TextButton(
onPressed: () {
fct();
Navigator.pop(context);
},
child: Text('yes'))
],
);
});
}
}


Add favorite button to list by provider to flutter app



12- اضافة ملف ب اسم favorite_screen يحتوي على كلاس ب اسم  FavoriteScreen من نوع StatefulWidget

وهو المسول عن كيفية ظهور شاشتين : الاولى شاشة المفضلة في حال تم اضافة عناصر للمفضلة او شاشة المفضلة في حال لم يتم اضافة اي عنصر  للمفضلة الكود يحتوي على 2 Scaffold  و 2 body ثم نكتب كود الحصول على العناصر لكل شاشة على حدة 

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';


class FavoriteScreen extends StatefulWidget {
// static const routeName = '/FavoriteScreen';

@override
_FavoriteScreenState createState() => _FavoriteScreenState();
}

class _FavoriteScreenState extends State<FavoriteScreen> {
@override
Widget build(BuildContext context) {
return favoriteProvider.getFavoriteItems.isEmpty
? Scaffold(body: FavoriteEmptyList())
: Scaffold(
backgroundColor: Colors.blue,
appBar: AppBar(
backgroundColor: Colors.blue,
title: Text(
'Favorite (${favoriteProvider.getFavoriteItems.length})'),
actions: [
IconButton(
onPressed: () {
globalMethods.showDialogg(
' Remove Item',
'It will remove from favorite list',
() => favoriteProvider.clearItem(),
context);
// cartProvider.clearCart();
},
icon: Icon(Icons.delete_forever),
)
],
),
body: Container(
margin: EdgeInsets.only(bottom: 60),
child: ListView.builder(
itemCount: favoriteProvider.getFavoriteItems.length,
itemBuilder: (BuildContext ctx, int index) {
return ChangeNotifierProvider.value(
value: favoriteProvider.getFavoriteItems.values
.toList()[index],
child: FavoriteFullList(
itemId: favoriteProvider.getFavoriteItems.keys
.toList()[index],
),
);
}),
),
);
}
}


نقوم بتعريف كلاس ال DialogMethods

DialogMethods globalMethods = DialogMethods();


ثم نعرف FavoriteProvider 

final favoriteProvider = Provider.of<FavoriteProvider>(context);


13- اضافة ملف ب اسم favorite_empty_list يحتوي على كلاس ب اسم  FavoriteEmptyList من نوع StatelessWidget

وهو المسول عن تصميم شاشة المفضلة في حال لم يتم اضافة اي عنصر

import 'package:flutter/material.dart';

import '../home.dart';

class FavoriteEmptyList extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Container(
// margin: EdgeInsets.only(top: 80),
width: double.infinity,
height: MediaQuery.of(context).size.height * 0.3,
decoration: BoxDecoration(
image: DecorationImage(
fit: BoxFit.contain,
image: AssetImage('assets/empty-wishlist.png'),
),
),
),
Text(
'No favorite items',
textAlign: TextAlign.center,
style: TextStyle(
color: Theme.of(context).textSelectionColor,
fontSize: 36,
fontWeight: FontWeight.w600),
),
SizedBox(
height: 10,
),
Text(
'Add your favorite items',
textAlign: TextAlign.center,
style: TextStyle(
color: Colors.black, fontSize: 26, fontWeight: FontWeight.w600),
),
SizedBox(
height: 30,
),
Container(
width: MediaQuery.of(context).size.width * 0.9,
height: MediaQuery.of(context).size.height * 0.1,
child: RaisedButton(
// onPressed: () {
// Navigator.of(context).pushNamed(Home.routeName);
// },
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(16),
side: BorderSide(color: Colors.red),
),
color: Colors.redAccent,
child: Text(
'Back to Home'.toUpperCase(),
textAlign: TextAlign.center,
style: TextStyle(
color: Colors.white,
fontSize: 26,
fontWeight: FontWeight.w600),
),
),
),
],
);
}
}


Add favorite button to list by provider to flutter app



14- اضافة ملف ب اسم favorite_full_list يحتوي على كلاس ب اسم  FavoriteFullList من نوع StatefulWidget

وهو المسول عن تصميم شاشة المفضلة في حال تم اضافة العناصر للمفضلة

import 'package:flutter/material.dart';

class FavoriteFullList extends StatefulWidget {
@override
_FavoriteFullListState createState() => _FavoriteFullListState();
}

class _FavoriteFullListState extends State<FavoriteFullList> {
@override
Widget build(BuildContext context) {

return Container(height: 135,
margin: const EdgeInsets.all(10),
decoration: BoxDecoration(
borderRadius: BorderRadius.only(
bottomRight: const Radius.circular(16.0),
topRight: const Radius.circular(16.0),
),
    color: Colors.white),);}}


نقوم باضافة كود تصميم شاشة المفضلة

child: Row(
children: [
Container(
width: 130.0,
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage(''
// favoriteElements.image
),
fit: BoxFit.contain,
),
),
),
Flexible(
child: Padding(
padding: const EdgeInsets.all(2.0),
child: Column(
children: [
FlatButton(
onPressed: () {
// _launchinbrowser(
// (favoriteElements.url),
// );
},
child: Row(
children: [
Expanded(
child: Text('',
// (favoriteElements.describtion),
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.w600,
color: Colors.blue,
),
),
),
Material(
color: Colors.transparent,
child: InkWell(
borderRadius: BorderRadius.circular(32.0),
// splashColor: ,
onTap: () {
globalMethods.showDialogg(
'Remove item',
'It will remove from favorite list',
() => favoriteProvider
.removeItem(widget.itemId),
context);
//
},
child: Container(
height: 50,
width: 50,
child: Icon(
Icons.cancel,
color: Colors.red,
size: 22,
),
),
),
),
],
),
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Flexible(
child: Text('',
// favoriteElements.title,
maxLines: 2,
overflow: TextOverflow.ellipsis,
style: TextStyle(
fontWeight: FontWeight.w600, fontSize: 15),
),
),
],
),
],
),
),
),
],
),


Add favorite button to list by provider to flutter app


نقوم بتعريف كلاس ال DialogMethods

DialogMethods globalMethods = DialogMethods();


ثم نقوم بتعريف واستدعى كلا من

 [ FavoriteProvider + FavoriteModel ]

final favoriteProvider = Provider.of<FavoriteProvider>(context);
final favoriteElements = Provider.of<FavoriteModel>(context);


نقوم  بتعريف المتغير itemId داخل الكلاس 

final String itemId;

const FavoriteFullList({this.itemId});


ثم نقوم ب اضافة العناصر داخل الكلاس 


ثم نقوم باستدعى معرف حزمة url_launcher 

Future<void> _launchinbrowser(String url) async {
if (await canLaunch(url)) {
await launch(
url,
forceSafariVC: false,
forceWebView: true,
enableJavaScript: true,
headers: <String, String>{'header_key': 'header_value'},
);
} else {
throw 'Could not launch $url';
}
}


اضافة طرق الانتقال في main.dart 
routes: {
'/FavoriteScreen': (context) => FavoriteScreen(),
'/Home': (context) => Home(),
},


شكرا لمتابعتكم كما نرجوا الاعجاب بالفيديو والاشتراك بالقناة وكتابة ملاحظاتكم في الكومنتات ^_^

تعليقات