Codeit Mobile
94 subscribers
3 photos
1 video
243 links
📱 آموزش برنامه‌نویسی موبایل

Kotlin • Android

🚀 آموزش ساده، کاربردی و پروژه‌محور
💡 مخصوص توسعه‌دهندگان موبایل
Download Telegram
🔥 اپراتور Elvis (?:) در Kotlin ‒ نجات‌دهنده از null!

زمانی که با متغیرهای nullable کار می‌کنی، همیشه باید مقداردهی پیش‌فرض داشته باشی تا از NPE جلوگیری کنی. اپراتور Elvis (?:) مثل یک کوتاه‌نویس عمل می‌کند: اگر مقدار سمت چپش null باشه، مقدار سمت راست اجرا می‌شه.

مثال واقعی: فرض کن توی یک پروژه‌ی لاگین، اسم کاربر رو از سرور می‌گیری. اگر null بود، باید مقدار پیش‌فرض “کاربر ناشناس” نشون داده بشه.

val userName: String? = serverResponse?.name
val displayName = userName ?: "کاربر ناشناس"


📌 توضیح کد:
متغیر userName ممکنه null باشه. با ?: اگر null بود، "کاربر ناشناس" جایگزین می‌شه. این کار از کدهای طولانی if جلوگیری می‌کنه و کد خواناتر می‌شه.

💡 نکته: اپراتور Elvis رو می‌تونی با زنجیره‌ای از ?. و ?: ترکیب کنی تا یک‌خطی null-safe بنویسی.

برداشت نهایی: همیشه برای مقادیر nullable یک fallback داشته باش. Elvis دوست صمیمی Kotlin developer هاست!

#ElvisOperator #Kotlin #NullSafety #AndroidDev #Beginner #Codeit #Android #Kotlin
🌐 Codeit → https://code-it.ir

━━━━━━━━━━━━━━━
@CodeitMobile
🔥1
🔹 تا حالا توی «Kotlin» از «if» فقط برای شرط‌گذاری استفاده می‌کردی؟ 😲
🔸 وقتشه ببینی «if» می‌تونه یه مقدار برگردونه! یعنی مثل یه عبارت عمل کنه، نه فقط دستور.

یعنی به جای نوشتن چند خط کد برای مقداردهی، می‌تونی مستقیم از «if» خروجی بگیری.
⚡️ این ویژگی باعث میشه کدت خواناتر، کم‌حجم‌تر و حرفه‌ای‌تر بشه.

💡 مثال واقعی: فرض کن می‌خوای بر اساس امتیاز کاربر، یه پیام خوشامدگویی متفاوت نشون بدی.

📌 کد ساده با «if as expression»:

val score = 85
val message = if (score >= 90) {
"عالی! عالی! 🏆"
} else if (score >= 70) {
"خوب بود، ادامه بده 💪"
} else {
"نیاز به تلاش بیشتر داره 📚"
}
println(message)


🔍 اینجا «if» دقیقا مثل یه تابع عمل می‌کنه و مقدار نهایی رو به «message» نسبت میده.
🔁 دیگه نیازی به متغیر موقت یا «var» نداری، همه چیز یک‌خطی و تمیزه.

🎯 نکته مهم: حتما باید همه شاخه‌ها (if, else if, else) مقدار برگردونن، وگرنه کامپایل خطا میده.

🔥 یه قدم کوچیک به سمت کدنویسی حرفه‌ای‌تر با «Kotlin». از امروز تو پروژه‌هات از این قابلیت استفاده کن.

#Codeit #Android #Kotlin #Jetpack #KotlinTips #CleanCode #AndroidDev #Programming
🌐 Codeit → https://code-it.ir

━━━━━━━━━━━━━━━
@CodeitMobile
1🔥1
🚀 تو کاتلین، پراپرتی‌ها فقط متغیر نیستن – پشت پرده کلی قدرت دارن!
یکی از مهم‌ترین ابزارهاشون «backing field» هست که درکش برای کد تمیز و حرفه‌ای ضروریه.

🔹 مشکل کجاست؟
وقتی یه پراپرتی داریم و می‌خوایم توی «setter» یا «getter» یه کار اضافه انجام بدیم، مستقیم به اسم پراپرتی دسترسی داریم. اما اگه توی «setter» دوباره از اسم پراپرتی استفاده کنیم، باعث فراخوانی بی‌نهایت (recursion) می‌شه!

🔸 راه‌حل: «backing field»
کاتلین یه کلمه جادویی به اسم field داره که به حافظه واقعی پراپرتی اشاره می‌کنه و از حلقه بی‌نهایت جلوگیری می‌کنه.

💡 کاربرد واقعی:
مثلاً برای اعتبارسنجی مقدار ورودی، ذخیره مقدار محاسبه‌شده، یا جلوگیری از مقادیر نامعتبر.

کد زیر یه کلاس «Person» داره که سن رو فقط بین ۰ تا ۱۲۰ قبول می‌کنه:

class Person {
var age: Int = 0
set(value) {
if (value in 0..120) {
field = value
} else {
println("Invalid age: $value")
}
}
}


🧠 توضیح کد:
توی «setter» از field برای ذخیره مقدار جدید استفاده شده. اگه مستقیماً age = value می‌نوشتیم، دوباره «setter» صدا زده می‌شد و برنامه کرش می‌کرد.

نکته مهم:
اگه هم «getter» و هم «setter» رو بازنویسی نکنی، کاتلین خودش «backing field» رو مدیریت می‌کنه. ولی وقتی یکی از اون‌ها رو تغییر میدی، برای دسترسی به مقدار اصلی باید از field استفاده کنی.

📌 خلاصه:
«backing field» بهت کنترل کامل روی ذخیره‌سازی مقدار پراپرتی رو میده بدون ایجاد وابستگی بی‌نهایت. این یه ابزار قدرتمند برای اعتبارسنجی، لاگ‌گیری و محاسبات در لحظه‌ست.

#Codeit #Android #Kotlin #Jetpack #KotlinProperties #BackingField #CleanCode #AndroidDev
🌐 Codeit → https://code-it.ir

━━━━━━━━━━━━━━━
@CodeitMobile
2
🔒 فهم درست «Visibility Modifiers» توی کاتلین، تفاوت بین کد تمیز و کد آشغال رو مشخص می‌کنه
خیلی از توسعه‌دهنده‌ها می‌دونن که «private» یعنی فقط داخل کلاس دیده بشه، ولی خیلی‌ها «internal» رو اشتباه می‌گیرن.

📌 «public» — پیش‌فرض، همه‌جا دیده میشه (همون default جاوا).
📌 «private» — فقط داخل همون فایل یا کلاس.
📌 «internal» — فقط داخل همون ماژول (مثل ماژول اندروید).
📌 «protected» — فقط داخل کلاس و زیرکلاس‌ها (در کاتلین protected مثل private نیست).

🔧 کاربرد واقعی توی یک «ViewModel» اندروید:
باید منطق داخلی رو از بیرون پنهان کنی تا فقط از طریق «StateFlow» حالت رو نشون بدی.

مثال کد ساده:

class ProfileViewModel : ViewModel() {

// فقط خود ViewModel می‌تونه مقدار رو تغییر بده
private val _userName = MutableStateFlow("")
val userName: StateFlow<String> = _userName.asStateFlow()

internal fun updateUserName(newName: String) {
// فقط کلاس‌های هم‌ماژول (مثل Fragment) می‌تونن صدا بزنن
_userName.value = newName
}
}


🧠 توضیح:
- «MutableStateFlow» رو «private» کردیم تا کسی خارج از کلاس نتونه مستقیم بهش دسترسی داشته باشه.
- «StateFlow» رو «public» گذاشتیم تا UI فقط بخوندش.
- «updateUserName» رو «internal» کردیم تا فقط داخل ماژول صدا زده بشه، نه از کتابخونه‌های بیرون.

💡 نتیجه عملی: با استفاده درست از «visibility modifiers» امنیت داده رو بالا می‌بری، API تمیزتر می‌نویسی و از باگ‌های زمان کامپایل جلوگیری می‌کنی.

#Codeit #Android #Kotlin #Jetpack #CleanCode #KotlinVisibility #AndroidDev
🌐 Codeit → https://code-it.ir

━━━━━━━━━━━━━━━
@CodeitMobile
2
📱 یک تابع پرکاربرد در «Kotlin» که کد رو خواناتر و کوتاهتر میکنه: «apply»!

🔧 «apply» یک «Scope Function» هست که بهتون اجازه میده بدون تکرار اسم آبجکت، به پراپرتی‌هاش دسترسی داشته باشید و اون رو تنظیم کنید. به‌جای نوشتن چندین خط «obj.prop»، با «apply» همه چیز توی یک بلاک جمع میشه.

🎯 کجا به کار میاد؟ وقتی یک آبجکت جدید میسازید و باید چند تا پراپرتی رو مقداردهی کنید (مثلاً تنظیمات یک View یا یک DTO). «apply» آبجکت رو برمی‌گردونه، پس میتونید زنجیره‌ای استفاده کنید.

💡 مثال واقعی: فرض کنید یک «TextView» دارید و میخواید متن، رنگ و اندازه رو تنظیم کنید. بدون «apply» کد تکراری زیاد میشه. با «apply»:

val textView = TextView(context).apply {
text = "Hello"
textSize = 18f
setTextColor(Color.BLUE)
gravity = Gravity.CENTER
}


🧠 توضیح: داخل بلاک «apply»، «this» همون آبجکته، پس مستقیماً به متدها و پراپرتی‌هاش دسترسی دارید. نتیجه همون آبجکت هست، ولی با مقادیر تنظیم شده. کد خواناتر، کم‌حجم‌تر و خالی از تکرار!

نکته مهم: «apply» رو بیشتر برای مقداردهی اولیه (configuration) استفاده کنید، نه برای عملیات زنجیره‌ای طولانی. اینطوری خوانایی به حداکثر میرسه.

🚀 با «apply» کد خودتون رو حرفه‌ای‌تر کنید، مخصوصاً توی «Jetpack Compose» یا موقع تنظیم «ViewModel».

#Codeit #Android #Kotlin #Jetpack #ScopeFunctions #Apply #CleanCode #AndroidDev
🌐 Codeit → https://code-it.ir

━━━━━━━━━━━━━━━
@CodeitMobile
1
📂 «Portfolio»‌ای که واقعاً استخدامت کند، فقط لیست پروژه نیست.
یک داستان حرفه‌ای از مهارت‌های توست. 🚀

بسیاری از اندروید دولوپرها کلی پروژه می‌سازند اما استخدام نمی‌شوند.
علت؟ «Portfolio» مثل ویترین مغازه است؛ اگر مرتب و هدفمند نباشد، مشتری (کارفرما) رد می‌شود.

نکات کلیدی که «Portfolio» تو رو از بقیه جدا می‌کنه:

۱. کیفیت به جای کمیت – یک پروژه کامل با «Clean Architecture» و تست، بهتر از ده تا پروژه ناقصه.
۲. تمرکز روی مشکلات واقعی – اپلیکیشنی که یه نیاز روزمره رو حل کنه، جذاب‌تر از یه «To‑Do List» تکراریه.
۳. مستندسازی درست – حتماً هر پروژه رو با «README» حرفه‌ای، توضیح معماری و «Screenshots» همراه کن.
۴. حضور در «GitHub» – کد تمیز و «Commit»‌های معنادار نشون‌دهنده نظم ذهنیته.

یکی از بهترین راه‌ها مشارکت در پروژه‌های «Open Source» یا فورک یه «Library» معروف و اضافه کردن قابلیت جدیده.
این کار اعتماد کارفرما رو جلب می‌کنه.

اگر «Portfolio» نداری، همین حالا یکی از اپ‌های روزمره مثل «مدیریت هزینه» یا «یادآور دارو» رو با «Jetpack Compose» و «Room» بساز و تو «GitHub» منتشر کن.

یادت باشه: «Portfolio» نباید صرفاً لینک باشه، بلکه باید نشون بده چطور فکر می‌کنی. 💡

#Codeit #Android #Kotlin #Jetpack #PortfolioTips #CareerGrowth #AndroidDev
🌐 Codeit → https://code-it.ir

━━━━━━━━━━━━━━━
@CodeitMobile
1
🧩 «MutableList» در کاتلین، لیستی است که می‌توانید اعضای آن را تغییر دهید، اضافه کنید یا حذف کنید.
برخلاف «immutable list» که فقط خواندنی است، «MutableList» برای سناریوهای پویا عالی است.

📌 کاربرد: زمانی که نیاز دارید لیست کاربران، آیتم‌های سبد خرید یا نتایج جستجو را در حین اجرا تغییر دهید.

👨‍💻 کد ساده:
val names = mutableListOf("Ali", "Sara")
names.add("Reza")
names.remove("Sara")
names[0] = "Amir"
println(names) // خروجی: [Amir, Reza]

این کد نشان می‌دهد که چگونه اعضای لیست را اضافه، حذف و ویرایش کنید.

🔄 برای کار با داده‌های پویا در «ViewModel» یا «Repository» از این نوع استفاده کنید.
- همراه با «StateFlow» یا «LiveData» برای واکنش‌گرایی.

🎯 نکته: همیشه نوع «MutableList» را با متدهای کاربردی مثل forEach یا filter ترکیب کنید تا کد تمیزتر شود.

#Codeit #Android #Kotlin #Jetpack #MutableList #KotlinBasics #AndroidDev
🌐 Codeit → https://code-it.ir

━━━━━━━━━━━━━━━
@CodeitMobile
2🔥1
🔧 کال کردن جاوا از کاتلین – وقتی کد جاوا داری ولی با کاتلین کار میکنی، هیچ نگرانی نیست! کاتلین کاملاً با جاوا سازگاره و می‌تونی مستقیم از کلاس‌های جاوا توی پروژه استفاده کنی. 😎

⚠️ نکته مهم: توابع جاوا که مقدار nullable برمی‌گردونن، توی کاتلین به صورت «Platform Type» دیده می‌شن. یعنی مشخص نیست nullable هست یا نه. پس حواست باشه و با «!!» یا «?» مدیریتش کن.

🛠️ مثال عملی: فرض کن یه کلاس جاوا داری به اسم «JavaCalculator» که دو متد داره. می‌خوای توی کاتلین ازش استفاده کنی و ورودیش رو با «Null Safety» ترکیب کنی.

// فراخوانی مستقیم متد جاوا از کاتلین
val calculator = JavaCalculator()
val result = calculator.add(5, 10)
println("Result: $result") // Result: 15

// استفاده از SAM Conversion برای Java interface
val runnable = Runnable { println("Hello from Kotlin") }
Thread(runnable).start()


توضیح کد:
- متد «add» مستقیم صدا زده شده و مشکل نداره.
- برای «Runnable» از SAM Conversion استفاده کردیم تا کد خواناتر بشه.
- اگر متد جاوا «@Nullable» داشته باشه، توی کاتلین با «?» می‌گیری.

💡 نکته حرفه‌ای: برای دسترسی به متدهای static جاوا از «@JvmStatic» یا «Companion Object» استفاده کن. همچنین با «@JvmOverloads» می‌تونی overloaded functions رو برای جاوا مهیا کنی.

📌 گرفته عملی:
- همیشه نوع خروجی متدهای جاوا رو چک کن (با «@Nullable» یا «@NotNull»).
- برای callback های جاوا از SAM Conversion استفاده کن.
- از «Kotlin -> Java Interop» برای کد تمیزتر بهره ببر.

#Codeit #Android #Kotlin #Jetpack #JavaInterop #NullSafety #AndroidDev #KotlinTips
🌐 Codeit → https://code-it.ir

━━━━━━━━━━━━━━━
@CodeitMobile
🔥1
کار با تاریخ و زمان در اندروید همیشه چالش‌برانگیز بوده؛ مخصوصاً وقتی با مناطق زمانی مختلف و فرمت‌های غیراستاندارد سر و کار دارید.

📅 در کاتلین مدرن، کتابخانهٔ «java.time» بهترین گزینه است. دیگر نیازی به «SimpleDateFormat» یا «Calendar» ندارید.

🔍 یک مشکل رایج: تبدیل یک «Timestamp» به تاریخ محلی کاربر با رعایت منطقهٔ زمانی.

🧠 راه‌حل: استفاده از «Instant» و «ZoneId» برای تبدیل دقیق.

با این دو کلاس، همیشه نتیجه‌ی درست می‌گیرید.

👇 یک مثال عملی:

import java.time.Instant
import java.time.ZoneId
import java.time.ZonedDateTime
import java.time.format.DateTimeFormatter

val timestamp: Long = 1700000000000L // مثال
val instant = Instant.ofEpochMilli(timestamp)
val zone = ZoneId.of("Asia/Tehran")
val zonedDateTime = ZonedDateTime.ofInstant(instant, zone)
val formatter = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm")
val persianDate = zonedDateTime.format(formatter)
println(persianDate) // خروجی: ۱۴۰۲/۰۸/۲۰ ۱۲:۳۰


💡 این کد تایم‌استمپ را به تاریخ و زمان محلی بر اساس منطقه زمانی تهران تبدیل می‌کند.

⚙️ نکتهٔ پیشرفته: برای ذخیره در «Room Database»، بهتر است تاریخ را به «Long» (timestamp) تبدیل کنید و هنگام نمایش با «java.time» به فرمت دلخواه تغییر دهید.

🚀 با این روش، همهٔ پیچیدگی‌های «Daylight Saving Time» و مناطق زمانی خودکار مدیریت می‌شود.

📌 حتماً از این رویکرد در پروژه‌های جدید استفاده کنید.

#Codeit #Android #Kotlin #Jetpack #DateTime #javaTime #KotlinTips #AndroidDev
🌐 Codeit → https://code-it.ir

━━━━━━━━━━━━━━━
@CodeitMobile
🔥21
توی قسمت پنجم سری آموزشی «Flow»، سراغ «onEach» و «launchIn» میریم؛ دو ابزار قدرتمند برای مدیریت هوشمندانه جریان دادهها! 🧩
«onEach» بهت اجازه میده قبل از اینکه مقدار به دست مصرفکننده برسه، یه عملیات میانی روش انجام بدی؛ مثل ذخیرهسازی یا لاگ گرفتن. 📝
«launchIn» هم کار «collect» رو انجام میده ولی بدون اینکه مجبور باشی خودت «Coroutine» بسازی؛ فقط کافیه «Scope» رو بدی. 🚀
این دو باهم یه ترکیب عالی برای «ViewModel» هستن؛ دادهها رو دریافت میکنی، پردازش میکنی و رابط کاربری رو هم بلاک نمیکنی. 🔥
فرض کن دادههای دمای سنسور رو میگیری و باید هر مقدار رو توی «Room Database» ذخیره کنی؛ کد زیر رو ببین:

sensorRepository.sensorFlow
.onEach { data ->
localCache.save(data)
}
.launchIn(viewModelScope)


توی این کد، «onEach» هر مقدار خروجی سنسور رو قبل از ارسال به مصرفکننده ذخیره میکنه و «launchIn» مطمئن میشه همهچیز توی «viewModelScope» اجرا بشه. 🎯
یعنی نه خبری از «collect» دستیه، نه «launch» اضافه؛ کدت خلوت و خواناتر میشه.
یه نکته حرفهای: «launchIn» یه «Job» برمیگردونه؛ با «cancel» کردنش میتونی هر موقع خواستی جمعآوری رو متوقف کنی. 💡
اگه این الگو رو یاد بگیری، دیگه مجبور نیستی توی هر «Fragment» یا «ViewModel» کد تکراری بنویسی و مدیریت «Coroutine» هم دقیق و اصولی میشه. 📈
تمرین کن و این دو تا رو جایگزین «collect» های اضافی کن؛ نتیجه رو توی تمیزی کدهات فوراً حس میکنی.

#Codeit #Android #Kotlin #Jetpack #KotlinFlow #Flow #Coroutine #AndroidDev
🌐 Codeit → https://code-it.ir

━━━━━━━━━━━━━━━
@CodeitMobile
2🔥1
🚀 جستجوی هوشمند با «debounce» در «Kotlin Flow»
بالاخره وقتشه تایپ کاربر رو بهینه مدیریت کنیم!

تا حالا شده کاربر توی سرچ باکس تند تند تایپ کنه و هر کاراکتر باعث یه درخواست جدید بشه؟
این یعنی ترافیک بی‌فایده و کندی UI!

🔥 راه‌حل ساده: اپراتور «debounce» تو «Kotlin Flow»
این قابلیت باعث میشه فقط بعد از توقف تایپ (مثلاً ۳۰۰ میلی‌ثانیه) درخواست ارسال بشه.

📱 مثال واقعی: یه اپ لیست محصولات که کاربر اسم کالا رو تایپ میکنه:

class SearchViewModel : ViewModel() {

private val _query = MutableStateFlow("")

val searchResults: StateFlow<List<Product>> = _query
.debounce(300) // صبر کن 300 میلی‌ثانیه بعد از آخرین تغییر
.filter { it.length >= 2 } // حداقل 2 کاراکتر
.distinctUntilChanged() // فقط مقدار جدید
.flatMapLatest { query ->
repository.searchProducts(query) // API call
}
.stateIn(
scope = viewModelScope,
started = SharingStarted.WhileSubscribed(5000),
initialValue = emptyList()
)

fun onQueryChanged(query: String) {
_query.value = query
}
}


این کد چیکار میکنه؟
- وقتی کاربر تایپ میکنه، ۳۰۰ میلی‌ثانیه صبر میکنه
- اگر تایپ قطع بشه، درخواست API میره
- از تکرار مقادیر تکراری جلوگیری میکنه
- نتیجه رو به صورت خودکار به UI میرسونه

💡 مزیت بزرگ:
کاهش ۸۰٪ درخواست‌های اضافی + تجربه کاربری عالی
بدون نیاز به Handler یا Timer سنتی!

🌟 نکته حرفه‌ای:
مقدار debounce رو متناسب با سرعت تایپ کاربر تنظیم کن.
برای جستجوی فوری (مثل جستجوی زنده) ۳۰۰-۵۰۰ میلی‌ثانیه عالیه.

#Codeit #Android #Kotlin #Jetpack #Flow #Coroutines #CleanCode #AndroidDev
🌐 Codeit → https://code-it.ir

━━━━━━━━━━━━━━━
@CodeitMobile
2🔥1
🗂 «Jetpack Compose» قدم اولت رو برداشتی؟ حالا وقتشه با قلب این فریم‌ورک آشنا بشی: «Composable functions»!

🧠 هر «Composable function» یه تابع معمولی «Kotlin» هست که با افزودن «@Composable» بهش، می‌تونه رابط کاربری بسازه. بدونش هم می‌تونی کد بزنی، ولی با «@Composable» معجزه می‌کنه.

🔧 چرا بهش نیاز داری؟ چون با «Composable»ها می‌تونی UI رو به صورت تابعی و بدون دردسر مدیریت کنی. هر بار که وضعیت (state) تغییر کنه، فقط همون بخش لازم دوباره رندر می‌شه.

📱 مثال واقعی: فرض کن یک صفحه ساده داری که اسم کاربر رو نشون می‌ده. با «Composable» این کار رو خیلی راحت انجام می‌دی:

@Composable
fun Greeting(name: String) {
Text(text = "سلام $name!", fontSize = 24.sp)
}


این کد یه تابع «Composable» به اسم «Greeting» می‌سازه که یک «Text» رو با اسم ورودی نشون می‌ده. با تغییر اسم، فقط همین متن دوباره ساخته می‌شه و بقیه UI دست نمی‌خوره.

💡 نکته مهم: تو «Composable»ها خبری از «return» نیست. تو فقط می‌گی چی نشون بده، و «Compose» خودش بقیه کار رو می‌کنه.

🔗 حالا بیا این «Greeting» رو داخل یه «Activity» صدا بزنیم:

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
Greeting(name = "کاربر جان!")
}
}


توضیح: «setContent» یه «block» از «Composable»ها رو به عنوان ریشه UI معرفی می‌کنه. اینجا «Greeting» رو صدا زدیم تا متن خوش‌آمدگویی نمایش داده بشه.

💎 جمع‌بندی: «Composable function»ها پایه‌ترین مفاهیم «Jetpack Compose» هستن. هر UI که می‌سازی، در نهایت از این توابع تشکیل می‌شه. پس خوب یادشون بگیر.

#Codeit #Android #Kotlin #Jetpack #Compose #Composable #UI #AndroidDev
🌐 Codeit → https://code-it.ir

━━━━━━━━━━━━━━━
@CodeitMobile
3🥰1
🎯 «Jetpack Compose» قسمت ۵: «Button Composable»
یکی از پایهای‌ترین کامپوننت‌های UI در «Jetpack Compose» دکمه‌ها هستند.
بیایید ببینیم چطور می‌تونیم یک دکمه با ظاهر و رفتار دلخواه بسازیم.

🚀 مثال عملی:
فرض کنید یک دکمه «ثبت نام» می‌خواهید که با کلیک روی آن، یک پیام نمایش بدهد.

🛠️ کد ساده برای شروع:
@Composable
fun SimpleButton() {
Button(
onClick = {
println("دکمه کلیک شد!")
},
colors = ButtonDefaults.buttonColors(
containerColor = Color.Blue,
contentColor = Color.White
),
shape = RoundedCornerShape(12.dp)
) {
Text(text = "ثبت نام")
}
}

💡 توضیح:
- onClick: عملی است که بعد از کلیک اجرا می‌شه.
- colors: رنگ پس‌زمینه و متن رو مشخص می‌کنه.
- shape: گوشه‌های دکمه رو گرد می‌کنه (مثلاً ۱۲ پیکسل).

🎨 شخصی‌سازی بیشتر:
می‌تونید Modifier اضافه کنید تا اندازه، حاشیه یا ارتفاع دکمه رو تنظیم کنید:

Button(
onClick = { /* کلیک */ },
modifier = Modifier
.fillMaxWidth()
.height(56.dp)
.padding(horizontal = 16.dp)
) {
Text("ورود به حساب")
}

📌 کاربرد:
این کد یک دکمه تمام‌عرض با ارتفاع ثابت و فاصله از کناره‌ها می‌سازه.

نتیجه‌گیری:
با «Button» در «Jetpack Compose» می‌تونید دکمه‌های زیبا و واکنش‌گرا با کمترین کد بسازید.

#Codeit #Android #Kotlin #Jetpack #JetpackCompose #UI #Button #AndroidDev

🌐 Codeit → https://code-it.ir

━━━━━━━━━━━━━━━
@CodeitMobile
1🔥1🥰1
🎯 قسمت ششم از سری «Jetpack Compose»: آموزش «Image Composable» 🖼️

گاهی اوقات ساده‌ترین کارها مثل نمایش یک تصویر، در برنامه‌نویسی اندروید کلی دردسر دارد. اما در «Jetpack Compose» با «Image Composable» همه چیز راحت و تمیز می‌شود.

🔹 «Image» یک کامپوننت آماده است که هر نوع تصویری را در «Compose» نمایش می‌دهد.
🔹 برای استفاده از آن فقط باید منبع تصویر (مثلاً یک «drawable resource») را مشخص کنید.
🔹 اگر تصویر از اینترنت باشد، از کتابخانه‌های «Coil» یا «Glide» همراه با «rememberAsyncImagePainter» کمک می‌گیرید.

یک مثال ساده: نمایش تصویر از پوشه «res/drawable»:

@Composable
fun ShowImage() {
Image(
painter = painterResource(id = R.drawable.sample_image),
contentDescription = "تصویر نمونه",
modifier = Modifier
.fillMaxWidth()
.height(200.dp),
contentScale = ContentScale.Crop
)
}


📌 در این کد از «painterResource» برای بارگذاری تصویر داخلی استفاده شده.
📌 «contentDescription» برای دسترسی‌پذیری (Accessibility) ضروری است.
📌 «contentScale» نحوه تطبیق تصویر با فضا را مشخص می‌کند (مثلاً «Crop» برای برش).

💡 کاربردی: اگر تصویر پروفایل کاربر یا بنر تبلیغاتی دارید، با این روش به راحتی نمایش می‌دهید.
«Image Composable» انعطاف‌پذیر و سریع است – حتی انیمیشن و تغییر اندازه هم آسان.

#Codeit #Android #Kotlin #Jetpack #JetpackCompose #ImageComposable #AndroidDev #ComposeUI
🌐 Codeit → https://code-it.ir

━━━━━━━━━━━━━━━
@CodeitMobile
2🔥1
📦 «Box» در «Jetpack Compose» ساده‌ترین راه برای لایه‌بندی ویجت‌ها روی هم است.
👨‍💻 وقتی می‌خواهید یک متن را روی تصویر بگذارید یا یک دکمه را در گوشه‌ی کارت قرار دهید، «Box» بهترین انتخاب است.
🔍 «Box» یک «Layout» است که فرزندانش را به‌ترتیب روی هم می‌چیند و هر کدام می‌توانند موقعیت متفاوتی داشته باشند.

💡 مثال واقعی: یک کارت با عکس پس‌زمینه و متن روی آن.

کد زیر را ببینید:

Box(
modifier = Modifier
.fillMaxWidth()
.height(200.dp)
) {
Image(
painter = painterResource(id = R.drawable.background),
contentDescription = null,
modifier = Modifier.fillMaxSize(),
contentScale = ContentScale.Crop
)
Text(
text = "عنوان کارت",
color = Color.White,
fontSize = 24.sp,
modifier = Modifier
.align(Alignment.BottomCenter)
.padding(16.dp)
)
}


در این کد، «Image» تمام فضای «Box» را پر می‌کند و «Text» با استفاده از «align» به پایین و وسط چسبانده شده است.
🎯 «Box» هم‌چنین برای نمایش «CircularProgressIndicator» روی یک محتوا یا قرار دادن نشانگر «Badge» روی آیکون کاربرد دارد.

📌 نکته: از «Modifier.align» برای تعیین موقعیت دقیق هر فرزند استفاده کنید.
🌐 «Box» را به‌عنوان پایه‌ای برای «Stack» در «XML» به خاطر بسپارید.

#Codeit #Android #Kotlin #Jetpack #JetpackCompose #BoxLayout #UI #AndroidDev
🌐 Codeit → https://code-it.ir

━━━━━━━━━━━━━━━
@CodeitMobile
1🔥1🥰1
🔥 یه لیست بلندبالا تو اپت داری و می‌خوای بدون لگ و کندی نشونش بدی؟
«LazyColumn» دقیقاً همون چیزیه که بهش نیاز داری.

📌 فرقش با «Column» معمولی اینه که فقط آیتم‌هایی رو که توی صفحه قابل دیدن هستن رو می‌سازه.
بقیه آیتم‌ها منتظر می‌مونن تا کاربر اسکرول کنه. به این کار می‌گن «Lazy Loading».

💡 استفاده از «LazyColumn» توی یه اپ فروشگاهی یا پیام‌رسان ضروریه.
اگه بخوای ۱۰۰۰ تا محصول رو با «Column» نمایش بدی، اپ کرش یا خیلی کند میشه.

📝 یه نمونه ساده:

@Composable
fun ProductList(products: List<String>) {
LazyColumn {
items(products) { product ->
Text(
text = product,
modifier = Modifier.padding(16.dp)
)
}
}
}


این کد یه لیست از محصولات رو با اسکرول نرم و عملکرد بالا نشون میده.
«items» تابعیه که لیست رو دریافت می‌کنه و برای هر آیتم یه «Composable» می‌سازه.

💡 نکته حرفه‌ای:
برای کنترل بهتر از «LazyListState» استفاده کن تا موقعیت اسکرول رو ذخیره و بازیابی کنی.

📌 جمع‌بندی:
«LazyColumn» همون راه‌حل استاندارد برای نمایش لیست‌های بلند در «Jetpack Compose» هست.
با این تکنیک اپت روان‌تر و حرفه‌ای‌تر به نظر می‌رسه.

#Codeit #Android #Kotlin #Jetpack #JetpackCompose #LazyColumn #AndroidDev
🌐 Codeit → https://code-it.ir

━━━━━━━━━━━━━━━
@CodeitMobile
2🔥1👏1
📱 «Jetpack Compose» — قسمت ۱۱: اصول «State»

اگه می‌خوای یه اپلیکیشن تعاملی بسازی، باید باهاش حرف بزنی 🗣️
«State» همون حافظه‌ی کوتاه‌مدته که به کامپوزر می‌گه چی رو نشون بده 🔄

💡 هر وقت «State» عوض بشه، «Composable» دوباره کشیده میشه (Recomposition)
مثلاً وقتی کاربر روی دکمه کلیک میکنه، عدد شمارنده افزایش پیدا کنه

✍️ ساده‌ترین روش: استفاده از «remember» و «mutableStateOf»
این دو تا با هم «State» رو توی حافظه نگه می‌دارن و UI رو به‌روزرسانی می‌کنن

🔍 یه مثال عملی: شمارنده‌ای که با هر کلیک یکی زیاد میشه

@Composable
fun Counter() {
var count by remember { mutableStateOf(0) }
Button(onClick = { count++ }) {
Text("تعداد کلیک: $count")
}
}


«remember» مقدار رو تا وقتی کامپوننت حذف نشده حفظ میکنه
«mutableStateOf» باعث میشه با تغییر مقدار، UI دوباره ساخته بشه
با «by» دیگه نیازی به .value نداری و کد خواناتر میشه

🎯 نکته: اگه «State» رو درست مدیریت نکنی، برنامه کند یا ناهماهنگ میشه
🛠️ تمرین: یه فیلد ورودی بساز و متن تایپ شده رو نمایش بده

#Codeit #Android #Kotlin #Jetpack #JetpackCompose #StateManagement #MobileDev #AndroidDev
🌐 Codeit → https://code-it.ir

━━━━━━━━━━━━━━━
@CodeitMobile
2🥰1👏1
🎨 مستندسازی خودکار وضعیت UI با «remember» در «Jetpack Compose» 🧠

تا حالا شده توی Compose یه متغیر ساده تعریف کنی، ولی با هر ری‌کامپوز مقدارش از بین بره؟ 😵
اینجاست که «remember» وارد می‌شه! یه ابزار ساده که مقدار رو توی حافظه نگه می‌داره و تا وقتی Composable زنده‌ست، ناپدید نمی‌شه.

📌 کاربرد واقعی:
فرض کن داری یه اپلیکیشن تسک‌منیجر می‌سازی و می‌خوای تعداد کلیک‌ها روی یه دکمه رو نمایش بدی. بدون «remember» هر بار UI ریفرش می‌شه و شمارشگر صفر می‌شه.

اول یه متغیر معمولی رو نشون می‌دم، بعد با «remember» درستش می‌کنیم:

@Composable
fun CounterWithoutRemember() {
var count = 0
Button(onClick = { count++ }) {
Text("تعداد: $count")
}
}


⚠️ این کد کار نمی‌کنه چون count با هر ری‌کامپوز دوباره صفر می‌شه.

حالا با «remember» اصلاحش می‌کنیم:

@Composable
fun CounterWithRemember() {
val count = remember { mutableIntStateOf(0) }
Button(onClick = { count.intValue++ }) {
Text("تعداد: ${count.intValue}")
}
}


اینجا «mutableIntStateOf» باعث می‌شه وقتی مقدار تغییر می‌کنه، UI به‌طور خودکار آپدیت بشه و «remember» هم مقدار رو توی ری‌کامپوزها حفظ می‌کنه.

💡 نکته طلایی:
اگر مقدار به «Lifecycle» وابسته‌ست (مثلاً ورودی کاربر)، از «rememberSaveable» استفاده کن تا حتی با چرخش صفحه هم داده‌ها از دست نره.

#Codeit #Android #Kotlin #Jetpack #JetpackCompose #ComposeState #Remember #AndroidDev
🌐 Codeit → https://code-it.ir

━━━━━━━━━━━━━━━
@CodeitMobile
1🔥1🥰1
📱 وقتی تلفن رو می‌چرخونی، اپ‌هات یادش می‌ره توی TextField چی نوشتی؟ 😤

«Jetpack Compose» یه راه‌حل ساده داره: «rememberSaveable»!
برخلاف «remember» که بعد از تغییر چرخش صفحه (Configuration Change) ریست می‌شه،
«rememberSaveable» مقدار رو توی «Bundle» ذخیره می‌کنه و موقع بازسازی کامپوزیشن برمی‌گردونه.

🌟 استفاده کاربردی: ذخیره ورودی کاربر، وضعیت چک‌باکس، شمارنده و هر داده‌ای که از بین نره.

یه مثال عملی می‌زنم:
کد زیر یک شمارنده داره که با دکمه زیاد میشه و بعد از چرخش صفحه مقدارش رو حفظ می‌کنه:

@Composable
fun CounterScreen() {
var count by rememberSaveable { mutableStateOf(0) }

Column(
modifier = Modifier.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center
) {
Text(text = "شمارنده: $count", fontSize = 32.sp)
Button(onClick = { count++ }) {
Text("افزایش")
}
}
}


توضیح کد:
«rememberSaveable» مقدار count رو در Bundle ذخیره می‌کنه.
وقتی صفحه بچرخه یا اپ در حالت background بره، مقدار از دست نمیره.
داخل «mutableStateOf» هم خودش ری‌کامپوز رو مدیریت می‌کنه.

💡 نکته: برای داده‌های سنگین یا شیءهای سفارشی، باید Parcelable یا Serializable باشه،
اما برای انواع ساده (Int, String, Boolean) بدون مشکل کار می‌کنه.

🚀 این تکنیک رو امروز تو پروژه‌ات استفاده کن تا تجربه کاربری بهتری بدی.

#Codeit #Android #Kotlin #Jetpack #JetpackCompose #StateManagement #MobileDev #AndroidDev
🌐 Codeit → https://code-it.ir

━━━━━━━━━━━━━━━
@CodeitMobile
1🔥1🥰1
📌 «Recomposition» در Jetpack Compose چیه؟
وقتی state تغییر می‌کنه، Compose مجدداً composable‌های وابسته رو اجرا می‌کنه تا UI به‌روز بشه. به این فرآیند می‌گن «Recomposition».

🔹 نکته مهم: فقط بخش‌هایی که به state تغییر یافته وابسته‌ان recompose می‌شن، نه کل UI.

مثال ساده: یه دکمه شمارنده با «mutableStateOf»:

@Composable
fun Counter() {
var count by remember { mutableStateOf(0) }
Button(onClick = { count++ }) {
Text("Clicked: $count")
}
}


با هر کلیک، count تغییر می‌کنه و فقط composable «Counter» دوباره اجرا می‌شه. Compose خودش تشخیص می‌ده کدوم بخش‌ها نیاز به به‌روزرسانی دارن.

برای بهینه‌سازی:
- از «remember» برای نگهداری state در recompose استفاده کنید.
- از «derivedStateOf» برای محاسبات سنگین وابسته به state بهره ببرید.

نتیجه: درک «Recomposition» به شما کمک می‌کنه UIهای واکنش‌گرا و کارآمد با کمترین سربار بنویسید.

#Codeit #Android #Kotlin #Jetpack #JetpackCompose #Recomposition #StateManagement #AndroidDev
🌐 Codeit → https://code-it.ir

━━━━━━━━━━━━━━━
@CodeitMobile
1