Pure Coder
785 subscribers
189 photos
30 videos
8 files
150 links
⭕️آدرس سایت:
https://purecoder.ir

⭕️گروه پرسش و پاسخ:
@purecoder_gp

⭕️پشتیبانی:
@PureCoder_support
@MohammadTaherri
Download Telegram
This media is not supported in your browser
VIEW IN TELEGRAM
💊Capsule

Window

ViewInsets vs ViewPadding vs Padding

#capsule
💊Capsule

🟢ViewInsets
پیکسل هایی هستن که سیستم عامل برای مواردی مثل کیبرد استفاده میکند(System UI)

در این نواحی هیچ محتوایی از اپ رندر نمیشود.

🟢ViewPadding
پیکسل هایی هستن که در طرفین دستگاه قرار دارن (بالا و پایین) مثل noch

🟢Padding
با استفاده از دو مقدار بالا محاسبه میشود.

Padding = max(0.0, viewPadding - viewInsets)

🔥این پراپرتی ها رو میتونید توی MediaQuery پیدا کنید.

#capsule
💊Capsule

🔥توی اندروید های 10 به بعد یا Ui های اختصاصی شده مثل miui شاید دیده باشین که با کشیدن دست روی طرفین صفحه نمایش (چپ و راست) میتونیم صفجه رو بک کنیم.

🟢این قسمت ها یا این پیکسل ها در واقع پیکسل هایی هستن که محتوای اپ داخلشون رندر میشه ولی input gestures توی این پیکسل ها تشخیص داده نمیشه.

🟢در واقع سیستم عامل input gestures این پیکسل ها رو خودش مصرف میکنه و اجازه مدیریت اون توسط اپ رو نمیده.

🟢مثلا وقتی که کاربر میخواد منو کشویی رو باز کنه ولی با لمس اون نواحی به جای باز شدن منو صفحه بک میشه.

🔥مقدار پیکسلی که سیستم عامل توی این نواحی مصرف میکنه رو میشه با این پراپرتی از MediaQuery بدست اورد :‌

systemGestureInsets

#capsule
💊Capsule
BottomSheet
ℹ️

🔥توی متریال دیزاین دو نوع ‌Bottom Sheet داریم.

✔️Persistent
این نوع در واقع مکمل محتوای اصلی هست و جلوی تعامل کاربر با بقیه قسمت های صفحه رو نمیگیره و با لمس کردن بقیه قسمت های اپ بسته نمیشه.

🟢این نوع رو میشه به دو روش استفاده کرد :

🔥پارامتر bottomSheet توی ویجت Scaffold

🔥🔥استفاده از فانکشن
showBottomSheet
و یا
Scaffold.of(context).showBottomSheet()

🔴هر کدوم از این روش ها تفاوت هایی دارن که بعدا اشاره میکنیم.

✔️Modal
این نوع درواقع یک گزینه جایگزین برای Dialog یا popup menu هست و جلوی تعامل کاربر با بقیه قسمت های صفحه رو میگیره.

🟢در صورتی که Dismissible باشه با لمس کردن قسمت های دیگه صفحه بسته میشه.

🔥این مورد رو میشه با استفاده از فانکشن
showModalBottomSheet

استفاده کرد.

#capsule
#intermediate
💊Capsule
BottomSheet
2️⃣

✔️Persistent

گفتم که این مورد رو میشه به دو روش پیاده کرد.

🔥پارامتر bottomSheet توی Scaffold :‌

توی این حالت :‌

باتم شیت جزو محتوای اصلی صفحه حساب میشه.

جلوی تعامل کاربر با بقیه المان های صفحه رو نمیگیره

با لمس کردن بقیه قسمت های صفحه بسته نمیشه

امکان درگ کردن و بسته و باز کردن خود باتم شیت توسط کاربر نیست

دکمه بک به اپ بار اضافه نمیشه

با بک زدن یا Navigator.pop کل صفحه بسته میشه

🔥توی این حالت باتم شیت اون پایین صفحه میمونه و به هیچ وجه قابل بستن نیست مگر اینکه توی برنامه ست استیت کنی و توی build جدید باتم شیت نداشته باشی

#capsule
#intermediate
💊Capsule
BottomSheet
3️⃣

✔️Persistent

و اما روش دوم

🔥استفاده از فانکشن
showBottomSheet
یا
Scaffold.of(context).showBottomSheet

توی این حالت:

باتم شیت جلوی تعامل کاربر با بقیه قسمت های صفحه رو نمیگیره

با لمس کردن بقیه قسمت های صفحه بسته نمیشه

امکان درگ کردن و بسته و باز کردن باتم شیت توسط کاربر وجود داره

دکمه بک به اپ بار اضافه میشه

با بک زدن یا Navigator.pop ابتدا باتم شیت بسته میشه و با بک دوم صفحه

🔥توی این حالت باتم شیت قابل درگ شدن و بسته و باز شدن توسط کاربر هست و با بک هم بسته میشه.

#capsule
#intermediate
BottomSheet
4⃣

خب تا اینجا bottom sheet های نوع Persistent رو دیدیم و با دو روش استفاده از اون ها ، شباهت ها و تفاوت های این روش ها اشنا شدیم.

حالا چرا به اینا میگن Persistent؟

🔥این کلمه به معنی ماندگار هست (یه چیز توی این مایه ها 😝)

حالا چون این نوع از bottom sheet ها مزاحم کار کردن با بقیه قسمت های صفحه نمیشن و با کار کردن با بقیه قسمت های صفحه بسته نمیشن، توی متریال دیزاین بهشون میگن

Persistent Bottom Sheets

#capsule
#intermediate
🟢<type>(<scope>): <subject>

✔️type : required
✔️scope : optional
✔️subject: required

scope

🔥این پارامتر اختیاری هست

🔥کاملا قراردادی هست و بستگی داره به پروژه ای که انجام میدین و توی پروژه باید مشخص کنید که این پارامتر چه مواردی رو میتونه در بر بگیره .

پس دنبال موارد از پیش تعیین شده نباشید

🔰برای نمونه توی یه پروژه ای که لایه های مختلف مثل presentation, data, logic داره .
این ها میتونن به عنوان scope در نظر گرفته بشن

🔰یا پروژه ای که سرویس های مختلف داره...

🔰ریپوزیتوری bloc روی گیت هاب که خودش از پروژه های مختلف مثل bloc, fluttet_bloc, ... تشکیل شده، هر پروژه رو به عنوان یه scope در نظر گرفته.

پس کاملا قراردادیه.

مثل مورد قبلی یعنی type, ابتدای پروژه باید یه لیستی رو مشخص کنید و قرارداد کنید و از اون پیروی کنید ( البته در طول پروژه میتونه بروزرسانی بشه)

#advanced
#capsule
🟢<type>(<scope>): <subject>

✔️type : required
✔️scope : optional
✔️subject: required

subject

🔥برای این مورد از یک جمله کوتاه برای شرح دادن commit مورد نظر استفاده کنید.

جمله باید :

✔️زمان حال ساده باشه.
✔️امری باشه.
✔️با حروف کوچک شروع بشه.
✔️تهش نقطه نباشه

update the folan thing
Update the folan thing
update the folan thing.
updated the folan thing
the folan thing is updated
the folan thing was updated
the folan thing has been updated

#capsule
#advanced
💊Capsule
🔥extends vs implement
1⃣

🟢واژه extend به معنای گسترش دادن یا توسعه دادن هست

B extends A

یعنی اینکه B داره A رو توسعه میده (گسترش میده)

🟢واژه implement به معنای پیاده سازی یا اجرا کردن هست

B implement A

یعنی B داره A رو پیاده سازی میکنه.

#capsule
💊Capsule
🔥extends vs implement
2⃣

گفتم که extend به معنای توسعه دادن هست .
پس وقتی که کلاس B داره کلاس A رو توسعه میده (extends) , طبیعتا طبق معنای توسعه دادن، باید تمام ویژگی ها و رفتار های کلاس A رو داشته باشه و بتونه اون رفتار ها رو تغییر بده و یا ویژگی ها و رفتار های جدید بهش اضافه کنه.

هر کلاس دو تا مولفه داره
✔️Fields ویژگی
✔️Methods رفتار

این ها میتونن static یا instance باشن
✔️instance Fields or methods
✔️Static Fields or methods

در این جا با static ها کاری نداریم (چون در سطح کلاس هستن و نه در سطح اشیا ساخته شده از کلاس)

🔥وقتی یک کلاس از یک کلاس دیگه extends میکنه:

🟢همه instance Field ها و instance method های اون رو به ارث میبره .
به غیر از اعضای private
توی دارت private نداریم.

🟢میتونه اون ها رو تغییر یا به اصطلاح override کنه.

🟢یا میتونه field ها یا method های جدید رو به اون اضافه کنه.

🔥در اینجا اصطلاح super class و sub class معرفی میشه

B extends A
در نتیجه کلاس A در اینجا super class و کلاس B یک subclass از کلاس A هست

کلاس فرزند تمام رفتار ها و ویژگی های والد رو به ارث میبره.
میتونه اون ها رو به صورت دست نخورده باقی بگذاره یا اون ها رو تغییر بده.
همچنین میتونه رفتار ها و ویژگی های جدید اضافه کنه.

#capsule
💊Capsule
🔥extends vs implement
3⃣

خب بریم سراغ implement
گفتیم که این واژه به معنای پیاده سازی هست

یک لحظه از دنیای برنامه نویسی بیاین بیرون

توی دنیای واقعی

من به شما میگم، اقا خانم، فلان چیز رو پیاده سازی کن.

وقتی بهت میگم فلان چیز رو پیاده سازی کن شما منتظر چی هست؟ در جواب چی میگی؟

میگی چی رو؟
درسته؟

منتظر یه دستور هستی
منتظر یک یا چند دستور
دستور العمل

دستور هایی که یک نفر صادر کرده و دیگری میخواد پیاده کنه یا اجرا کنه.

🔥پس وقتی که میگیم B میخاد A رو implement کنه، در واقع A باید یک مجموعه ای از دستور العمل ها باشه.

در اینجا دیگه A چیزی پیاده نکرده، چون که A قراره که دستور رو صادر کنه و یکی دیگه اون ها رو پیاده یا اجرا کنه.

پس باید بفهمیم که چطور میتونیم یک مجموعه از دستور ها رو بنویسیم که دیگران اون ها رو اجرا کنن.

پست بعدی 😍
#capsule
💊Capsule
🔥extends vs implement
4⃣

رسیدیم به اینجا که یک مجموعه از دستور ها رو یه جایی بنویسم و بقیه کلاس ها بتونن اون ها implement کنن.

🔥برای این منظور توی زبان های برنامه نویسی از مفهومی به نام interface ها استفاده میکنن.

توی یک interface ما فقط یک سری متد تعریف میکنیم و این متد ها هیچ بدنه و یا body ندارند.

در واقع فقط داریم یک دستور رو صادر میکنیم.

کلاس های دیگه که interface مورد نظر رو implement میکنن، باید تمام متد هایی که داخل اون interface تعریف شده رو پیاده سازی کنن.

🔥در واقع توی interface ما فقط امضای متد یا Signature اون رو مشخص میکنیم.

interface Contract{
void doSomething() ;
}

Class Concrete implement Contract {

void doSomething () {
// do your work...
}
}


#capsule
💊Capsule
🔥extends vs implement
5⃣

توی دارت چیزی به نام interface نداریم.

🔥برای این منظور از abstract کلاس ها استفاده میکنیم.

abstract class Contract{
void doSomething() ;
}

Class Concrete implement Contract {

void doSomething () {
// do your work...
}
}


کلاس های abstract هم میتونن متد های معمولی داشته باشن (همراه با بدنه /مثل بقیه کلاس ها) و هم متد های بدون بدنه.

هم میتونیم یک abstract کلاس رو implement کنیم و هم میتونیم ازش extends کنیم.

ولی تفاوتش چیه؟ 🤔

🔥اگه extends کنیم، این کلاس مثل یک super class برای ما عمل میکنه و تمام ویژگی های اون رو به ارث میبریم و علاوه بر اون باید متد های بدون بدنه اون رو پیاده سازی کنیم.

🔥اگه اون رو implement کنیم، کلا دیگه موضوع به ارث بردن ویژگی های اون میره پی کارش و ما مجبور میشیم که تمام متد های اون رو (چه با بدنه و چه بدون بدنه) پیاده سازی کنیم.

در واقع حتی متد هایی از کلاس پدر که پیاده سازی هم دارن، نادیده گرفته میشن و باید همه متد هاش داخل کلاس مورد نظر پیاده سازی بشن.

ولی این مورد استفاده توصیه نمیشه.

اگه abstract کلاسمون همه متد هاش بدون بدنه بودن و شبیه به interface بود اون رو implement میکنیم.

و اگه هر دو نوع رو در خودش داشت ازش extends میکینم که بتونیم تمام ویژگی هاش رو به ارث ببریم و متد های بدون بدنش رو هم implement یا پیاده سازی کنیم.
#capsule
💊Capsule
🔥extends vs implement
6⃣

🔥اگه بخوایم یک abstract کلاس قابل ارث بری نباشه و کلاس های دیگه نتونن ازش extends کنن و فقط مجبور باشن که implement اش کنن و در واقع شکل interface به خودش بگیره از تکنیک زیر استفاده می کنیم.

abstract class MyInterface{

const MyInterface._() ;

}


البته کلاس هایی که توی یک فایل یا library هستن میتونن این دست انداز رو رد کنن و بازم extends کنن😝
#capsule
PYsvgTz.png
2 MB
🔥Design Patterns🔥

#capsule
💊Capsule
نام گذاری

برای نام گذاری متغیر ها , فانکشن ها , کلاس ها و ... توی زبان های برنامه نویسی از 4 الگوی مختلف استفاده میشه:

✔️snake_case
✔️camelCase
✔️PascalCase
✔️kebap-case

🔥هر زبان برنامه نویسی برای نام گذاری قوانین خودش رو داره و باید اون ها رو رعایت کنیم.

🔥توی دارت :

برای نام گذاری فایل ها از snake_case استفاده میکنیم.

home_page.dart

برای نام گذاری متغیر های و فانکشن ها از camelCase استفاده میکنیم.

var newUser;

User createUser(){}

برای نام گذاری کلاس ها از PascalCase استفاده میکنیم.

class HomePage{}

#capsule
💊Capsule
🔥Key
1⃣

🟢دو نوع Key توی فلاتر داریم :

GlobalKey
LocalKey

✔️هر دو subclass کلاس Key هستن.

تفاوت اول و مهم این دو در این هست که GlobalKey باید توی کل اپ unique باشه.

یعنی اگه به یه ویجت توی یک فریم یه GloablKey دادید، دیگه نمیتونید از اون GlobalKey برای ویجت دیگه و توی همون فریم استفاده کنید.

استفاده از یک GlobalKey یکسان برای دو ویجت متفاوت در یک فریم یکسان ممنوع.

ولی LocalKey ها اینطور نیستن و شما میتونید برای دو ویجت متفاوت و در یک فریم از یک LocalKey یکسان استفاده کنید.

🔥به شرطی که :

✔️اون دو ویجت فرزند مشترک یک ویجت پدر نباشند.

مثلا هر دو نباید فرزند مشترک یک column یا یک stack باشن.

🔥علاوه بر اون اگه از Navigator 2 استفاده میکنید باید به page هاتون LocalKey بدید و نمیتونید از یک LocalKey یکسان برای دو page مختلف استفاده کنید.

#capsule
#advanced
💊Capsule
🔥GlobalKey
2⃣

🟢اولین کاربرد مهم GlobalKey برای این هست که به context یک ویجت و همچنین به state اون (در صورتی که ویجت استیت فول) باشه، در بقیه قسمت های اپ دسترسی داشته باشیم.

با استفاده از دو variable به نام های
✔️currentContext
✔️currentState
میتونیم به این منظور برسیم.

🔥علت اینکه توی نام از current استفاده شده چون که این موارد میتونن در طول lifetime یک GlobalKey تغییر کنن.

مثال)
با دادن GlobalKey به نویگیتور به جای استفاده از
Navigator.of(context).push
میگیم
navigatorKey.currentState.push

🔥این کار از لحاظ پرفرمانس عملکرد بهتری داره.

🟢به همین صورت میتونید به ویجت مورد نظر GlobalKey بدید و در بقیه قسمت های اپ به state اون دسترسی پیدا کنین و متد های داخل state اش رو کال کنید (مثل نویگیتور)
یا به contextاش دسترسی پیدا کنید.

بیش از اندازه استفاده نکنید (مطابق نیاز)

#capsule
#advanced
💊Capsule
🔥GlobalKey
3️⃣

🟢در مورد کاربرد اول GlobalKey گفتیم که میتونیم با استفاده از اون به context و state یک ویجت برسیم.

🔥با استفاده از state میتونیم به متد های داخل state ویجت مورد نظر دسترسی داشته باشیم و کالشون کنیم.

مثلا برای Navigator , Scaffold و ... میتونه مفید باشه.

سعی کنید برای ویجت هایی که خودتون مینویسید از این مورد استفاده نکنید مگر اینکه واقعا لازم بود.

خیلی مواقع راه حل استفاده از استیت منجمنت هست.

🔥با استفاده از context هم میتونیم کار هایی از قبیل :‌

✔️دسترسی به renderObject ویجت مورد نظر

✔️نوتیف فرستادن به وسیله context

✔️و...

رو انجام داد.
#capsule