تغییرات در توسعه اپهای موبایل معمولا با گرایشات و روندهای جدید همراه است چه این روندها در حوزه ایمنی و ثبات زبان باشد، و چه در بهبود عملکرد برنامه، به هرحال همیشه باید از این روندها پیروی کرد چرا که کارکرد و توسعه اپلیکیشنها را بهبود میبخشد. Jetpack Compose در مراسم گوگل IO 2019 برای طراحی رابط کاربری (UI) معرفی شد و روز به روز در حال پیشرفت میباشد. در ادامه مقاله خواهیم دید که Jetpack Compose که شرکت گوگل برای توسعه اپلیکیشنهای اندرویدی ارائه کرده است چیست. قبل از اینکه Jetpack Compose را توضیح دهیم آیا میدانید Jetpack چیست؟ شما میتوانید در وب سایت ما مقالهی جت پک چیست را مطالعه نمایید. Android Jetpack مجموعهای از مؤلفههای نرم افزار اندرویدی است که به ما در ساخت برنامههای عالی و بی عیب اندرویدی کمک میکند. این مؤلفههای نرم افزاری به موارد زیر کمک میکنند:
بهطور خلاصه میتوان گفت ابزار مدرنی میباشد که برای ساخت رابط کاربری (Material UI) در اندروید معرفی شده است.Jetpack Compose سهولت و مختصر بودن زبان برنامه نویسی کاتلین را با مدل برنامه نویسی reactive ترکیب میکند. و به صورت کاملا اعلانی است. به این معنی که رابط کاربری شما با فراخواندن دنبالهای از توابع که داده را به سلسه مراتبی از رابط کاربری تبدیل میکند، تعریف میشود. زمانی که دادههای اصلی تغییر میکند، فریم ورک به صورت اتوماتیک با فراخوانی دوباره تابعها سلسله مراتبی از viewها را برای شما بروزرسانی میکند. Android Jetpack Compose مانند سایر کتابخانههای JetPack در مراحل اولیه خود است. Jetpack Compose با کد کمتر، ابزاریهای قدرتمند و Apiهای بصری کاتلین باعث سادهتر شدن و تسریع در پیاده سازی رابط کاربری در اندروید میشود.
به طور کلی، ما از Relative Layout ،Linear Layout، یا Frame Layout برای ساخت Layout fileها استفاده میکنیم. اما پس از اینکه Constraint Layout فوق العاده وارده صحنه شد، همهی برنامه نویسان اندروید را مجذوب خود کرد. این خوب است، اما Constraint Layout, Relative Layout, Linear Layout, Frame Layoutها فقط درLayout ما قابل استفاده هستند. اگر روابط Linear Layout وجود نداشت یا ما مجبور بودیم Constraint Layout را درون فایل هایمان کد نویسی کنیم چه میشد؟ ما میتوانیم کمی رو به جلو برویم و بگوییم اگر یک راه جدید برای ساخت رابط کاربری بدون Layout Fileها داریم چطور است؟ آیا این ممکن است؟ بله هست، و این چیزی است که ما به آن Jetpack Compose میگوییم. مهم نیست که ما چند Layout پیشرفته مانند Relative Layout یا Constraint Layout داشته باشیم ما همیشه یک رابط کاربری ( declarative UI) در اندروید نیاز داریم. اگر چه ما چندین کتابخانه Third-party داریم، خیلی خوب است که یک Native library داشته باشیم. هم اکنون آن را در اختیار داریم، و اسم آن جت پک کامپوز میباشد. توجه: پیش نیاز استفاده از Jetpack Compose تجربه کار با کاتلین میباشد. توجه: این ویژگی در نسخه پیش نمایش ( Preview ) است و حتما برای پشتیبانی از Jetpack Compose باید از نسخه Android Studio Canary استفاده نمایید.
برای شروع یک پروژه جدید Android Studio Canary ، Compose را باز کنید و Start a new Android Studio project را انتخاب کنید همانطور که در زیر نشان داده شده است: اگر صفحهی بالا نشان داده نشد به File > New > New Project مراجعه نمایید. زمانی که یک پروژه جدید ساختید Empty Compose Activity را از قالبهای موجود انتخاب کنید. Next را انتخاب کنید و پروژه را مثل همیشه پیکربندی کنید. اطمینان پیدا کنید که نسخه minimum Sdk حتما روی Api 21 باشد بهدلیل اینکه حداقل Api که Compose پشتیبانی میکند Api 21 یا همان اندروید Lollipop است. برای کسب اطلاعات بیشتر در مورد تنظیم Compose با یک Empty Activity یا اضافه کردن آن به یک پروژه موجود، مستندات آن را مورد بررسی قرار دهید.
زمانی که قالب Empty Compose Activity را انتخاب کردید، کدهای زیر در پروژه شما ایجاد میشود. این پروژه در حال حاضر پیکربندی شده است و قابل استفاده برای Compose میباشد: فایل ساخته شده در AndroidManifest.xml و app/build.gradle فایلهای وارد شدهی کتابخانههای Compose، اندروید استودیو را قادر میسازد که Compose بتواند با buildFeature { compose true } flag کار کند.
android {
defaultConfig {
...
minSdkVersion 21
}
buildFeatures {
// Enables Jetpack Compose for this module
compose true
}
...
// Set both the Java and Kotlin compilers to target Java 8.
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = "1.8"
}
composeOptions {
kotlinCompilerExtensionVersion "0.1.0-dev09"
}
}
یک اپلیکیشن Compose از توابع Composable ساخته شده، توابع منظم با Annotation) @Composable) مشخص شده است، که میتواند سایر تابعهای Composable را فراخوانی کند. یک تابع تمام چیزی هست که شما برای ساخت رابط کاربری جدید نیاز دارید. Annotation (حاشیه نویسی) به Compose میگوید که برای بروزرسانی و حفظ رابط کاربری خود در طول زمان، پشتیبانی ویژهای را برای توابع فراهم میکند. توابع Composable را میتوان فقط از دیگر توابع Composable فراخوانی کرد. Compose به ما این امکان را میدهد تا ساختار کدهای خود را به قطعههای کوچک تبدیل کنیم. اغلب مواقع به Composable Functions، به طور کوتاه Composables میگوییم. برای استفاده از آخرین نسخه از Compose، فایل app/build.gradle را باز کنید. کتابخانههای Compose را بروزرسانی کنید:
dependencies {
// You also need to include the following Compose toolkit dependencies.
implementation 'androidx.ui:ui-framework:0.1.0-dev10'
implementation 'androidx.ui:ui-tooling:0.1.0-dev10'
implementation 'androidx.ui:ui-layout:0.1.0-dev10'
implementation 'androidx.ui:ui-material:0.1.0-dev10'
...
}
MainActivity.kt را باز کنید، کدها را بررسی و کار را شروع کنید:
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
MaterialTheme {
Greeting("Android")
}
}
}
}
@Composable
fun Greeting(name: String) {
Text(text = "Hello $name!")
}
@Preview
@Composable
fun DefaultPreview() {
MaterialTheme {
Greeting("Android")
}
}
تابع Composable یک تابع منظم است که با Composable@ حاشیه نویسی ( Annotation ) میشود. این عملکرد شما را قادر میسازد تا دیگر توابع داخلی Composable را فراخوانی کنید. میتوانید ببنید که تابع Greeting چگونه Composable@ را حاشیه نویسی کرده است. این تابع قطعهای از سلسله مراتب رابط کاربری را تولید کرده و ورودی داده شده را نمایش میهد. Text یک تابع Composable است که توسط کتابخانه ایجاد شده است.
@Composable
fun Greeting(name: String) {
Text(text = "Hello $name!")
}
تابع Composable، یک تابع کاتلین میباشد که با annotation) @Composable) نشانه گذاری شده است، در مثال بالا میبینید. با Composable ،Activity همچنان نقطه ورود یک برنامه اندرویدی است. در پروژه ما، زمانی که کاربر برنامه را باز میکند MainActivity راه اندازی میشود. ( همانطور که در فایل AndroidManifest.xml مشخص شده است). ما از setContent برای تعریف طرح خود استفاده میکنیم اما به جای استفاده از یک فایل XML، توابع Composable را درون آن قرار میدهیم.
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
MaterialTheme {
Greeting("Android")
}
}
}
}
MaterialTheme روشی برای استایل دادن به توابع Composable است، در بخش Theming your app برنامه اطلاعات بیشتری در این مورد خواهیم دید. برای دیدن نحوه نمایش متن روی صفحه، میتوانید برنامه را در یک شبیه ساز یا دستگاه اجرا کنید. یا از پیش نمایش Android Studio استفاده کنید. برای استفاده از پیش نمایش Android Studio، شما فقط باید توابع Composable را بدون پارامتر با annotation) @Preview) علامت گذاری کنید و پروژه خود را بسازید. در حال حاضر میتوانید یک پیش نمایش از عملکرد Composable را در فایل MainActivity.kt مشاهده کنید. میتوانید پیش نمایشهای مختلفی در همان فایل داشته باشید و به آنها نام بدهید.
@Preview("Text preview")
@Composable
fun DefaultPreview() {
MaterialTheme {
Greeting(name = "Android")
}
}
هنگام وارد کردن کلاسهای مربوط به Jetpack Compose در این پروژه، از کلاسهای زیر استفاده کنید:
androidx.compose.* for compiler and runtime classes
androidx.ui.* for UI toolkit and libraries
اگر حالت نمایش "فقط کد" انتخاب شود، پیش نمایش ظاهر نمیشود. برای دیدن پیش نمایش همانطور که در تصویر زیر مشاهده میکنید، روی حالت نمایش "تقسیم" ضربه بزنید:
برای تنظیم یک رنگ پس زمینه برای Text و بقیه صفحه، باید Surface را تعریف کنیم که شامل آن باشد:
@Composable
fun Greeting(name: String) {
Surface(color = Color.Yellow) {
Text (text = "Hello $name!")
}
}
مؤلفه هایی که درون Surface قرار دارند، بالای آن رنگ پس زمینه کشیده میشوند (مگر این که توسط یک Surface دیگر مشخص شده باشد). هنگامی که آن کد را به پروژه اضافه میکنید، دکمه Build & Refresh را در گوشه بالا سمت راست Android Studio مشاهده خواهید کرد. برای دیدن تغییرات جدید در پیش نمایش، روی آن ضربه بزنید یا پروژه را بسازید. میتوانید تغییرات جدید را در پیش نمایش مشاهده کنید: بیشتر عناصر رابط کاربری Compose مانند Text و Surface یک پارامتر modifier اختیاری را میپذیرند. پارامتر modifier به عناصر رابط کاربری میگوید که چیدمانش در صفحه نمایش چگونه باشد یا چطور رفتار کنند. modifier اشیاء معمولی زبان کاتلین هستند. میتوانید آنها را به متغیرها اختصاص دهید و از آنها دوباره استفاده کنید. همچنین میتوانید چندین مورد از این modifierها را با عملگر (+) زنجیر کنید که در یک آرگومان واحد ادغام شدهاند. چیدمان modifierها میتوانند نحوه اندازه گیری و تنظیم یک مؤلفه رابط کاربری را تغییر دهند. Layoutهای modifier که در Compose در دسترس هستند، به عنوان مثال شامل: ( LayoutPaddin , LayoutAlign , LayoutSize) میشوند. LayoutPadding در modifier مقداری از فضای اطراف عنصر را تزیین میکند. برای افزودن padding به متن روی صفحه، میتوانیم modifier را به متن خود اضافه کنیم:
@Composable
fun Greeting(name: String) {
Surface(color = Color.Yellow) {
Text(text = "Hello $name!", modifier = Modifier.padding(24.dp))
}
}
برای دیدن تغییرات جدید، روی دکمه Build & Refresh کلیک کنید.
هرچه مؤلفههای بیشتری به رابط کاربری اضافه کنیم، سطح تو در توی بیشتری را نیز ایجاد میکنیم، دقیقاً مانند سایر توابع موجود که در پایگاه داده شما ایجاد شده است. اگر توابع بسیار بزرگ شوند، این میتواند بر خوانایی تأثیر بگذارد. با ساخت اجزای کوچک و قابل استفاده مجدد، ایجاد کتابخانهای از عناصر رابط کاربری مورد استفاده در برنامه شما آسان است. هر تابع مسئولیت یک بخش کوچک صفحه را دارد و میتواند به طور مستقل ویرایش شود. وقتی کد رابط کاربری خود را refactor میکنیم، باید تابع خود را با حاشیه نویسی Composable علامت گذاری کنیم تا به کامپایلر بگوییم که این یک تابع Composable است و این امکان را فراهم میکند تا دیگر توابع سازنده را فراخوانی کند. کامپایلر همچنین باعث میشود که این تابع از یک تابع Composable دیگر فراخوانی شود. نکته: توجه داشته باشید که حاشیه نویسی Composable فقط برای توابعی که از رابط کاربری emit میشوند ضروری است. annotationها میتوانند توابع معمولی و Composable را فراخوانی کنند. اگر تابعی این شرایط را برآورده نکند، نباید با Composable حاشیه نویسی شود. توجه کنید که توابع Composable در MainActivity.kt در خارج از کلاس MainActivity هستند که به عنوان توابع سطح بالا اعلام میشوند. هرچه کدهای بیشتری در خارج از Activity داشته باشیم، میتوانیم از اشتراک و استفاده مجدد بیشتری استفاده کنیم.
ابتدا اجازه دهید یک تابع جدید Composable در MyApp ایجاد کنیم که حاوی منطق Compose UI مخصوص این Activity است. دوم، معقول نیست که رنگ پس زمینه برنامه در Greeting Composable قابل استفاده مجدد قرار گیرد، آن پیکربندی باید برای هر قطعه رابط کاربری در این صفحه اعمال شود، بنابراین Surface را در Greeting به توابع در MyApp جدید خود منتقل میکنیم:
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
MyApp()
}
}
}
@Composable
fun MyApp() {
MaterialTheme {
Surface(color = Color.Yellow) {
Greeting(name = "Android")
}
}
}
@Composable
fun Greeting(name: String) {
Text(text = "Hello $name!", modifier = Modifier.padding(24.dp))
}
@Preview
@Composable
fun DefaultPreview() {
MyApp()
}
ما میخواهیم از توابع Composable ،MyApp در Activityهای مختلف دوباره استفاده کنیم زیرا پیکربندی سطح بالایی را تعریف میکند که میتواند در مکانهای مختلف استفاده شود. از آنجا که Greeting در آن تعبیه شده است وضعیت فعلی توابع اجازه نمیدهد دوباره استفاده شود. در ادامه Container را تنظیم میکنیم که پیکربندی برنامه مشترک را داشته باشیم.
اگر بخواهیم Container بسازیم که تمام پیکربندی مشترک برنامه ما را داشته باشد،باید چه کاری انجام دهیم؟ برای ساختن یک Container عمومی، ما یک تابع Composable ایجاد میکنیم که به عنوان پارامتر تابع Composable (که در اینجا children نامیده میشود) Unit را برمیگرداند. ما Unit را برمیگردانیم زیرا همانطور که ممکن است متوجه شده باشید، تمام توابع Composable باید Unit را برگردانند:
@Composable
fun MyApp(children: @Composable() () -> Unit) {
MaterialTheme {
Surface(color = Color.Yellow) {
children()
}
}
}
هنگام استفاده از یک عملکرد Composable به عنوان یک پارامتر، مراقب پرانتز اضافی در () Composable@ باشید. از آنجا که حاشیه نویسی (Annotation) بر روی یک تابع اعمال میشود، به آن نیاز دارید و لازم است!
fun MyApp(children: @Composable() () -> Unit) { ... }
تابع ما، تمام پیکربندی مشترکی را که میخواهیم Container ما تهیه کند را تعریف میکند و سپس فرزندان منتقل شده Composable را میتوان به کمک آنها فراخوانی کرد. در این حالت، ما میخواهیم از MaterialTheme و یک surface زرد استفاده کرده و سپس children () را فراخوانی کنیم.
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
MyApp {
Greeting("Android")
}
}
}
}
@Preview("Text preview")
@Composable
fun DefaultPreview() {
MyApp {
Greeting("Android")
}
}
این کد معادل چیزی است که در بخش قبلی داشتیم اما اکنون انعطاف پذیرتر است. انجام توابع سازگار با ظروف یک روش خوب است که باعث بهبود خوانایی میشود و استفاده از کد را ترغیب میکند.
ما اجزای رابط کاربری را در توابع Composable استخراج میکنیم تا بدون استفاده از کد تکراری بتوانیم از آنها دوباره استفاده کنیم. در مثال زیر میتوانیم از دو greetings دوباره استفاده کنیم و همان توابع Composable با پارامترهای مختلف را نشان دهیم. برای قرار دادن آیتمها در یک ترتیب عمودی، ما از تابع Column Composable ( مشابه یک LinearLayout عمودی) استفاده میکنیم.
@Composable
fun MyScreenContent() {
Column {
Greeting("Android")
Divider(color = Color.Black)
Greeting("there")
}
}
Divider یک تابع Composable است که یک تقسیم افقی ایجاد میکند. از آنجا که ما میخواهیم MyScreenContent همان چیزی باشد که کاربران ما هنگام باز کردن برنامه میبینند، ما باید بر این اساس کد MainActivity را اصلاح کنیم. همچنین، میتوانیم کد پیش نمایش را تغییر دهیم، تا بتوانیم بدون استفاده از برنامه در دستگاه یا شبیه ساز، سریعتر در Android Studio کار را پیش ببریم:
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
MyApp {
MyScreenContent()
}
}
}
}
@Preview("MyScreen preview")
@Composable
fun DefaultPreview() {
MyApp {
MyScreenContent()
}
}
اگر پیش نمایش را Refresh کنیم، مواردی را میبینیم که به صورت عمودی قرار دارند: هنگامی که یک تابع Composable خوانده میشود، عناصر را به سلسله مراتب Compose UI اضافه میکند. برای افزودن عناصر جدید میتوانید با استفاده از چندین قسمت از کد خود، عملکرد مشابه (با پارامترهای متفاوت) را فراخوانی کنید.
توابع Compose را میتوان مانند سایر توابع در Kotlin دانست. این امر باعث میشود که UIهای برنامه قدرتمند باشند زیرا میتوانیم statements را اضافه کنیم تا در نحوه نمایش UI تاثیر داده شود. به عنوان مثال، میتوانیم از حلقه for استفاده کنیم تا عناصر را به ستون MyScreenContent اضافه کنیم:
@Composable
fun MyScreenContent(names: List<String> = listOf("Android", "there")) {
Column {
for (name in names) {
Greeting(name = name)
Divider(color = Color.Black)
}
}
}
شما میتوانید با Annotation (حاشیه نویسی) Model@ حالت را مدیریت نمایید. نوشتن برنامهها با فراخوانی توابع Composable دادهها را به UI تبدیل میکند. اگر دادههای شما تغییر کند، این توابع بروزرسانی شده و یک رابط کاربری جدید را ایجاد میکنید. ابزارهای پیشنهادی Compose با مشاهده تغییرات در دادههای برنامه شما به طور خودکار توابع شما را بروزرسانی میکند. Compose همچنین بررسی میکند که دادههای مورد نیاز توسط یک فرد سازنده مورد نیاز است یا نه، به طوری که فقط مؤلفه هایی را که دادههای آنها تغییر کرده است بررسی کرده و اگر در برنامه نیاز بود، دوباره میتوانند فراخوانی شوند. Compose از یک افزونه کامپایلر Kotlin استفاده میکند، بنابراین وقتی دادههای اساسی تغییر میکنند، توابع Composable برای بروزرسانی سلسله مراتب رابط کاربری دوباره فراخوانی میشوند. نکته: Annotation (حاشیه نویسی) Model@ باعث خواهد شد که کامپایلر Compose دوباره کلاس را بازنویسی کند تا آن را قابل مشاهده و Thread-safe کند. در ادامه یک شمارنده (Counter) درست میکنیم که اگر کاربر چند بار روی یک دکمه کلیک کند. حالت شمارنده که یک عدد Integer خواهد بود اضافه شود:
@Model
class CounterState(var count: Int = 0)
ما CounterState را با Model@ حاشیه نویسی (Annotation) کرده ایم زیرا میخواهیم توابع Composable که این کلاس را به عنوان یک پارامتر در نظر میگیرند به محض تغییر مقدار شمارش به صورت خودکار اضافه شود.
@Composable
fun Counter(state: CounterState) {
Button(onClick = { state.count++ }) {
Text("I've been clicked ${state.count} times")
}
}
Compose انواع مختلفی از دکمهها را مطابق مشخصات دکمه طراحی متریال ارائه میدهد: OutlinesButton ،Button و TextButton. در این مورد ما، از OutlinesButton استفاده خواهیم کرد و یک متن به عنوان محتوای دکمه خواهیم داشت که نشان میدهد OutlinesButton چند بار کلیک شده است. از آنجا که دکمه شمارش را میخواند، هرگاه تعداد شمارش تغییر کند، دکمه دوباره تجدید میشود و مقدار جدید شمارش را نشان میدهد. اکنون میتوانیم Counter را به صفحه خود اضافه کنیم:
@Composable
fun MyScreenContent(
names: List<String> = listOf("Android", "there"),
counterState: CounterState = CounterState()
) {
Column {
for (name in names) {
Greeting(name = name)
Divider(color = Color.Black)
}
Divider(color = Color.Transparent, height = 32.dp)
Counter(counterState)
}
}
پیش نمایش در این بخش پاسخگو نیست، برای دیدن این که کار میکند، باید برنامه را در یک شبیه ساز یا یک دستگاه واقعی اجرا کنیم. اگر برنامه را اجرا کنیم، میبینیم که Counter چگونه حالت را حفظ میکند و در هر کلیک آن را افزایش میدهد.
ما به طور خلاصه Column را معرفی کردیم که برای قرار دادن موارد در یک ترتیب عمودی استفاده میشود. به همین روش میتوانید از Row برای قرار دادن موارد به صورت افقی استفاده کنید. Row و Column آیتمها را یکی پس از دیگری قرار میدهد. اگر میخواهید برخی از موارد انعطاف پذیر باشد تا صفحه نمایش با وزن مشخصی اشغال شود، میتوانید از Flexible modifier استفاده کنید. (Inflexible رفتار پیش فرض است). اگر بخواهیم دکمه را در پایین صفحه قرار دهیم در حالی که محتوای دیگر در بالای صفحه قرار دارد. ما میتوانیم این کار را با مراحل زیر انجام دهیم:
@Composable
fun MyScreenContent(
names: List<String> = listOf("Android", "there"),
counterState: CounterState = CounterState()
) {
Column(modifier = Modifier.fillMaxHeight()) {
Column(modifier = Modifier.weight(1f)) {
for (name in names) {
Greeting(name = name)
Divider(color = Color.Black)
}
}
Counter(counterState)
}
}
مثالی دیگر با if else:
@Composable
fun Counter(state: CounterState) {
Button(
onClick = { state.count++ },
backgroundColor = if (state.count > 5) Color.Green else Color.White
) {
Text("I've been clicked ${state.count} times")
}
}
تمامی کدهای این بخش:
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import androidx.compose.Composable
import androidx.compose.Model
import androidx.ui.core.Modifier
import androidx.ui.core.setContent
import androidx.ui.foundation.Text
import androidx.ui.graphics.Color
import androidx.ui.layout.Column
import androidx.ui.layout.fillMaxHeight
import androidx.ui.layout.padding
import androidx.ui.material.Button
import androidx.ui.material.Divider
import androidx.ui.material.MaterialTheme
import androidx.ui.material.Surface
import androidx.ui.tooling.preview.Preview
import androidx.ui.unit.dp
@Model
class CounterState(var count: Int = 0)
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
MyApp {
MyScreenContent()
}
}
}
}
@Composable
fun MyApp(children: @Composable() () -> Unit) {
MaterialTheme {
Surface(color = Color.Yellow) {
children()
}
}
}
@Composable
fun MyScreenContent(
names: List<String> = listOf("Android", "there"),
counterState: CounterState = CounterState()
) {
Column(modifier = Modifier.fillMaxHeight()) {
Column(modifier = Modifier.weight(1f)) {
for (name in names) {
Greeting(name = name)
Divider(color = Color.Black)
}
}
Counter(counterState)
}
}
@Composable
fun Greeting(name: String) {
Text(text = "Hello $name!", modifier = Modifier.padding(24.dp))
}
@Composable
fun Counter(state: CounterState) {
Button(
onClick = { state.count++ },
backgroundColor = if (state.count > 5) Color.Green else Color.White
) {
Text("I've been clicked ${state.count} times")
}
}
@Preview("MyScreen preview")
@Composable
fun DefaultPreview() {
MyApp {
MyScreenContent()
}
}
ما در مثالهای قبلی هیچ نوع طرحی یا استایلی را تعریف نکردیم. چگونه میتوانیم به برنامه خود طرح (Theme) بدهیم؟ Theme بخشی از سلسله مراتبی از اجزاء به عنوان سایر تابعهای Composable است. (MaterialTheme نمونه ای از این مورد است) MaterialTheme یک تابع Composable است که منعکس کننده اصول یک ظاهر طراحی شده از مشخصات طراحی Material است. در رابط کاربری ساده اصلی، ما میتوانیم از MaterialTheme به شرح زیر استفاده کنیم:
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
MaterialTheme {
Greeting(name = "Android")
}
}
}
}
از آنجا که Material Theme، یک لایه بر روی Greeting است، Greeting با ویژگیهای تعریف شده یک Theme طراحی شده است. ما میتوانیم خصوصیات MaterialTheme را بازیابی کنیم و از آنها برای تعریف استایل Text به این روش استفاده کنیم:
@Composable
fun Greeting(name: String) {
Text (
text = "Hello $name!",
modifier = Modifier.padding(24.dp),
style = MaterialTheme.typography.h1
)
}
متن ترکیب شده در مثال بالا سه آرگومان، یک String ،modifier و یک TextStyle را تنظیم میکند. میتوانید TextStyle خود را ایجاد کنید، یا میتوانید با استفاده از MaterialTheme.typography یک استایل تعریف شده از موضوع را بازیابی کنید. این MaterialTheme.typography به شما امکان دسترسی به استایلهای متن تعریف شده، مانند h1 ،body1 یا subtitle1 را میدهد. در این مثال ما از h1 استفاده میکنیم. هر زمان که یک رنگ یا استایل متنی میخواهید، از یک تابع Composable از MaterialTheme.colors یا MaterialTheme.typography استفاده کنید. به عنوان مثال پیش نمایش را با این کد Refresh کنید:
@Preview("Text preview")
@Composable
fun DefaultPreview() {
MaterialTheme {
Greeting("Android")
}
}
حال تصویر زیر را مشاهده میکنید:
بیایید یک طرح (Theme) برای برنامه خود ایجاد کنیم. یک فایل جدید با نام MyAppTheme.kt ایجاد کنید. از آنجا که ممکن است بخواهیم از MyAppTheme خود در مکانهای مختلف برنامه (همهی Activity ها) استفاده کنیم، یک تابع قابل استفاده مجدد ایجاد خواهیم کرد.
import androidx.compose.Composable
@Composable
fun MyAppTheme(children: @Composable() () -> Unit) {
// TODO
}
MaterialTheme پیکربندی رنگها و تایپوگرافی را در اختیار دارد. ما فقط در این مرحله رنگها را تغییر میدهیم تا به طراحی مورد نظر خود برسیم.
import androidx.compose.Composable
import androidx.ui.graphics.Color
import androidx.ui.material.MaterialTheme
import androidx.ui.material.lightColorPalette
val green = Color(0xFF1EB980)
private val themeColors = lightColorPalette(
primary = green,
surface = Color.DarkGray,
onSurface = green
)
@Composable
fun MyAppTheme(children: @Composable() () -> Unit) {
MaterialTheme(colors = themeColors) {
children()
}
}
شما میتوانید از رنگ موجود دیگری نیز استفاده کنید.
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import androidx.compose.Composable
import androidx.ui.core.Modifier
import androidx.ui.core.setContent
import androidx.ui.foundation.Text
import androidx.ui.layout.padding
import androidx.ui.material.MaterialTheme
import androidx.ui.material.Surface
import androidx.ui.tooling.preview.Preview
import androidx.ui.unit.dp
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
MyAppTheme {
Surface {
Greeting("Android")
}
}
}
}
}
@Composable
fun Greeting2(name: String) {
Text (
text = "Hello $name!",
modifier = Modifier.padding(24.dp),
style = MaterialTheme.typography.h1
)
}
@Preview("Text preview")
@Composable
fun DefaultPreview() {
MyAppTheme {
Surface {
Greeting("Android")
}
}
}
اگر پیش نمایش را Refresh کنید، شکل زیر را مشاهده خواهید کرد: جمعبندی: در این مقاله بعضی از آخرین تغییرات دنیای طراحی رابط کاربری اندروید (Jetpack Compose) را تجربه کردید. اما این فقط گوشه کوچکی از سطح وسیع تغییرات پیش روی جت پک کامپوز بود. ما باید منتظر نسخه پایدار این کتابخانه باشیم. این کتابخانه دنیای جدیدی از طراحی رابط کاربری را برای ما به ارمغان میآورد و به ما این امکان را میدهد تا سرعت توسعه برنامه هایمان را بالا ببریم و از امکانات جدید و بروز استفاده کنیم، اگر سوال یا تجربه ای در استفاده از Jetpack Compose دارید خوشحال میشویم که با ما به اشتراک بگذاریم.
اگر به یادگیری بیشتر در زمینهی اندروید علاقه داری، با شرکت در دورهی آموزش برنامه نویسی اندروید در کمتر از یکسال به یک توسعهدهنده اندروید همه فن حریف تبدیل میشوی که آمادهی استخدام، دریافت پروژه و حتی پیادهسازی اپلیکیشن خودت هستی.
منابع این مقاله: developer.android.com github.com/android medium.com