آموزش

آموزش نوشتن Jetpack

Jetpack Compose یک جعبه ابزار مدرن برای ایجاد رابط کاربری بومی اندروید است. Jetpack Compose توسعه UI در Android را با کد کمتر، ابزارهای قدرتمند و APIهای شهودی Kotlin ساده و تسریع می‌کند.

در این آموزش، یک کامپوننت رابط کاربری ساده با توابع اعلامی می سازید. شما هیچ طرح‌بندی XML را ویرایش نمی‌کنید یا از ویرایشگر طرح‌بندی استفاده نمی‌کنید. در عوض، توابع composable را فراخوانی می‌کنید تا مشخص کنید چه عناصری را می‌خواهید، و کامپایلر Compose بقیه کارها را انجام خواهد داد.

پیش نمایش کامل
پیش نمایش کامل

یک عنصر متنی اضافه کنید

برای شروع، جدیدترین نسخه اندروید استودیو را دانلود کنید و با انتخاب پروژه جدید یک برنامه ایجاد کنید و در زیر دسته تلفن و تبلت ، فعالیت خالی را انتخاب کنید. نام برنامه خود را ComposeTutorial بگذارید و روی Finish کلیک کنید. الگوی پیش‌فرض قبلاً حاوی برخی از عناصر Compose است، اما در این آموزش شما آن را مرحله به مرحله ایجاد می‌کنید.

ابتدا یک "سلام جهان!" متن را با افزودن یک عنصر متنی در متد onCreate . این کار را با تعریف یک بلوک محتوا و فراخوانی تابع Text composable انجام می دهید. بلوک setContent طرح‌بندی فعالیت را که در آن توابع قابل ترکیب فراخوانی می‌شوند، تعریف می‌کند. توابع قابل ترکیب را فقط می توان از سایر توابع ترکیب پذیر فراخوانی کرد.

Jetpack Compose از یک افزونه کامپایلر Kotlin برای تبدیل این توابع قابل ترکیب به عناصر رابط کاربری برنامه استفاده می کند. به عنوان مثال، تابع Text composable که توسط کتابخانه Compose UI تعریف شده است، یک برچسب متنی را روی صفحه نمایش می دهد.

import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.material3.Text

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            Text("Hello world!")
        }
    }
}
  
نمایش پیش نمایش
پنهان کردن پیش نمایش

یک تابع ترکیبی را تعریف کنید

برای ایجاد یک تابع قابل ترکیب، حاشیه نویسی @Composable را اضافه کنید. برای امتحان کردن این، یک تابع MessageCard تعریف کنید که یک نام ارسال می شود و از آن برای پیکربندی عنصر متن استفاده می کند.

// ...
import androidx.compose.runtime.Composable

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            MessageCard("Android")
        }
    }
}

@Composable
fun MessageCard(name: String) {
    Text(text = "Hello $name!")
}

  
نمایش پیش نمایش
پنهان کردن پیش نمایش

عملکرد خود را در Android Studio پیش نمایش کنید

حاشیه‌نویسی @Preview به شما امکان می‌دهد عملکردهای قابل ترکیب خود را در Android Studio بدون نیاز به ساخت و نصب برنامه در دستگاه یا شبیه‌ساز Android پیش‌نمایش کنید. حاشیه نویسی باید روی یک تابع ترکیبی که پارامترها را نمی گیرد استفاده شود. به همین دلیل، نمی‌توانید عملکرد MessageCard را مستقیماً پیش‌نمایش کنید. در عوض، تابع دومی به نام PreviewMessageCard بسازید که MessageCard با یک پارامتر مناسب فراخوانی می کند. یادداشت @Preview را قبل از @Composable اضافه کنید.

// ...
import androidx.compose.ui.tooling.preview.Preview

@Composable
fun MessageCard(name: String) {
    Text(text = "Hello $name!")
}

@Preview
@Composable
fun PreviewMessageCard() {
    MessageCard("Android")
}
  
نمایش پیش نمایش
پنهان کردن پیش نمایش

پروژه خود را بازسازی کنید خود برنامه تغییر نمی کند، زیرا عملکرد جدید PreviewMessageCard هیچ جا فراخوانی نمی شود، اما Android Studio یک پنجره پیش نمایش اضافه می کند که می توانید با کلیک بر روی نمای تقسیم (طراحی/کد) آن را گسترش دهید. این پنجره پیش نمایشی از عناصر UI ایجاد شده توسط توابع قابل ترکیب که با حاشیه نویسی @Preview مشخص شده اند را نشان می دهد. برای به‌روزرسانی پیش‌نمایش‌ها در هر زمان، روی دکمه تازه‌سازی در بالای پنجره پیش‌نمایش کلیک کنید.

پیش نمایش یک تابع قابل ترکیب در Android Studio
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.material3.Text

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            Text("Hello world!")
        }
    }
}
  
نمایش پیش نمایش
پنهان کردن پیش نمایش
// ...
import androidx.compose.runtime.Composable

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            MessageCard("Android")
        }
    }
}

@Composable
fun MessageCard(name: String) {
    Text(text = "Hello $name!")
}

  
نمایش پیش نمایش
پنهان کردن پیش نمایش
// ...
import androidx.compose.ui.tooling.preview.Preview

@Composable
fun MessageCard(name: String) {
    Text(text = "Hello $name!")
}

@Preview
@Composable
fun PreviewMessageCard() {
    MessageCard("Android")
}
  
نمایش پیش نمایش
پنهان کردن پیش نمایش
پیش نمایش یک تابع قابل ترکیب در Android Studio

چند متن اضافه کنید

تاکنون اولین عملکرد و پیش نمایش قابل ترکیب خود را ساخته اید! برای کشف قابلیت‌های Jetpack Compose بیشتر، می‌خواهید یک صفحه پیام‌رسانی ساده حاوی لیستی از پیام‌ها بسازید که می‌توان آن را با برخی انیمیشن‌ها گسترش داد.

با نمایش نام نویسنده و محتوای پیام، پیام را غنی‌تر بسازید. ابتدا باید پارامتر composable را تغییر دهید تا یک شیء Message را به جای String بپذیرید و یک Text قابل نوشتن دیگر را در داخل MessageCard composable اضافه کنید. حتما پیش نمایش را نیز به روز کنید.

// ...

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            MessageCard(Message("Android", "Jetpack Compose"))
        }
    }
}

data class Message(val author: String, val body: String)

@Composable
fun MessageCard(msg: Message) {
    Text(text = msg.author)
    Text(text = msg.body)
}

@Preview
@Composable
fun PreviewMessageCard() {
    MessageCard(
        msg = Message("Lexi", "Hey, take a look at Jetpack Compose, it's great!")
    )
}

  
نمایش پیش نمایش
پنهان کردن پیش نمایش

این کد دو عنصر متنی را در داخل نمای محتوا ایجاد می کند. با این حال، از آنجایی که شما هیچ اطلاعاتی در مورد نحوه چیدمان آنها ارائه نکرده اید، عناصر متن روی هم کشیده می شوند و متن را غیرقابل خواندن می کند.

با استفاده از یک ستون

تابع Column به شما امکان می دهد عناصر را به صورت عمودی مرتب کنید. اضافه کردن Column به عملکرد MessageCard .
می‌توانید Row برای چیدمان افقی آیتم‌ها و Box برای چیدمان عناصر استفاده کنید.

// ...
import androidx.compose.foundation.layout.Column

@Composable
fun MessageCard(msg: Message) {
    Column {
        Text(text = msg.author)
        Text(text = msg.body)
    }
}

نمایش پیش نمایش
پنهان کردن پیش نمایش

یک عنصر تصویر اضافه کنید

کارت پیام خود را با افزودن تصویر نمایه فرستنده غنی کنید. از مدیر منابع برای وارد کردن یک تصویر از کتابخانه عکس خود استفاده کنید یا از آن استفاده کنید. یک Row composable اضافه کنید تا طراحی خوبی داشته باشید و یک Image قابل ترکیب داخل آن.

// ...
import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.Row
import androidx.compose.ui.res.painterResource

@Composable
fun MessageCard(msg: Message) {
    Row {
        Image(
            painter = painterResource(R.drawable.profile_picture),
            contentDescription = "Contact profile picture",
        )
    
       Column {
            Text(text = msg.author)
            Text(text = msg.body)
        }
  
    }
  
}
  
نمایش پیش نمایش
پنهان کردن پیش نمایش

چیدمان خود را پیکربندی کنید

طرح بندی پیام شما ساختار مناسبی دارد اما عناصر آن به خوبی فاصله ندارند و تصویر خیلی بزرگ است! برای تزئین یا پیکربندی یک ترکیب، Compose از اصلاح‌کننده‌ها استفاده می‌کند. آنها به شما این امکان را می دهند که اندازه، چیدمان، ظاهر آن را تغییر دهید یا تعاملات سطح بالا را اضافه کنید، مانند ایجاد یک عنصر قابل کلیک. می‌توانید آن‌ها را برای ایجاد ترکیب‌پذیری غنی‌تر به زنجیر بزنید. از برخی از آنها برای بهبود چیدمان استفاده خواهید کرد.

// ...
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.unit.dp

@Composable
fun MessageCard(msg: Message) {
    // Add padding around our message
    Row(modifier = Modifier.padding(all = 8.dp)) {
        Image(
            painter = painterResource(R.drawable.profile_picture),
            contentDescription = "Contact profile picture",
            modifier = Modifier
                // Set image size to 40 dp
                .size(40.dp)
                // Clip image to be shaped as a circle
                .clip(CircleShape)
        )

        // Add a horizontal space between the image and the column
        Spacer(modifier = Modifier.width(8.dp))

        Column {
            Text(text = msg.author)
            // Add a vertical space between the author and message texts
            Spacer(modifier = Modifier.height(4.dp))
            Text(text = msg.body)
        }
    }
}
  
نمایش پیش نمایش
پنهان کردن پیش نمایش
// ...

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            MessageCard(Message("Android", "Jetpack Compose"))
        }
    }
}

data class Message(val author: String, val body: String)

@Composable
fun MessageCard(msg: Message) {
    Text(text = msg.author)
    Text(text = msg.body)
}

@Preview
@Composable
fun PreviewMessageCard() {
    MessageCard(
        msg = Message("Lexi", "Hey, take a look at Jetpack Compose, it's great!")
    )
}

  
نمایش پیش نمایش
پنهان کردن پیش نمایش
پیش نمایش دو متن قابل ترکیب با هم تداخل دارند
// ...
import androidx.compose.foundation.layout.Column

@Composable
fun MessageCard(msg: Message) {
    Column {
        Text(text = msg.author)
        Text(text = msg.body)
    }
}

نمایش پیش نمایش
پنهان کردن پیش نمایش
// ...
import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.Row
import androidx.compose.ui.res.painterResource

@Composable
fun MessageCard(msg: Message) {
    Row {
        Image(
            painter = painterResource(R.drawable.profile_picture),
            contentDescription = "Contact profile picture",
        )
    
       Column {
            Text(text = msg.author)
            Text(text = msg.body)
        }
  
    }
  
}
  
نمایش پیش نمایش
پنهان کردن پیش نمایش
// ...
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.unit.dp

@Composable
fun MessageCard(msg: Message) {
    // Add padding around our message
    Row(modifier = Modifier.padding(all = 8.dp)) {
        Image(
            painter = painterResource(R.drawable.profile_picture),
            contentDescription = "Contact profile picture",
            modifier = Modifier
                // Set image size to 40 dp
                .size(40.dp)
                // Clip image to be shaped as a circle
                .clip(CircleShape)
        )

        // Add a horizontal space between the image and the column
        Spacer(modifier = Modifier.width(8.dp))

        Column {
            Text(text = msg.author)
            // Add a vertical space between the author and message texts
            Spacer(modifier = Modifier.height(4.dp))
            Text(text = msg.body)
        }
    }
}
  
نمایش پیش نمایش
پنهان کردن پیش نمایش

از متریال دیزاین استفاده کنید

طرح پیام شما اکنون طرح بندی دارد، اما هنوز عالی به نظر نمی رسد.

Jetpack Compose پیاده سازی Material Design 3 و عناصر رابط کاربری آن را خارج از جعبه ارائه می دهد. با استفاده از طراحی متریال طراحی ظاهر MessageCard ما را بهبود می‌بخشید.

برای شروع، تابع MessageCard را با موضوع Material ایجاد شده در پروژه خود، ComposeTutorialTheme و همچنین یک Surface بپیچید. این کار را هم در @Preview و هم در تابع setContent انجام دهید. انجام این کار به اجزای سازنده شما اجازه می‌دهد تا سبک‌هایی را که در موضوع برنامه شما تعریف شده است، به ارث ببرند و از ثبات در سراسر برنامه شما اطمینان حاصل کنند.

طراحی متریال حول سه ستون ساخته شده است: Color ، Typography و Shape . آنها را یکی یکی اضافه خواهید کرد.

توجه: الگوی Empty Compose Activity یک تم پیش‌فرض برای پروژه شما ایجاد می‌کند که به شما امکان می‌دهد MaterialTheme سفارشی کنید. اگر نام پروژه خود را متفاوت از ComposeTutorial گذاشته اید، می توانید موضوع سفارشی خود را در فایل Theme.kt در زیر بسته ui.theme پیدا کنید.

// ...

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            ComposeTutorialTheme {
                Surface(modifier = Modifier.fillMaxSize()) {
                    MessageCard(Message("Android", "Jetpack Compose"))
                }
            }
        }
    }
}

@Preview
@Composable
fun PreviewMessageCard() {
    ComposeTutorialTheme {
        Surface {
            MessageCard(
                msg = Message("Lexi", "Take a look at Jetpack Compose, it's great!")
            )
        }
    }
}


  
نمایش پیش نمایش
پنهان کردن پیش نمایش

رنگ

از MaterialTheme.colorScheme برای استایل دادن به رنگ های تم پیچیده شده استفاده کنید. شما می توانید از این مقادیر از موضوع در هر جایی که به رنگی نیاز است استفاده کنید. این مثال از رنگ‌های موضوعی پویا (تعریف شده توسط تنظیمات برگزیده دستگاه) استفاده می‌کند. برای تغییر این مورد می توانید dynamicColor در فایل MaterialTheme.kt روی false قرار دهید.

عنوان را استایل دهید و یک حاشیه به تصویر اضافه کنید.

// ...
import androidx.compose.foundation.border
import androidx.compose.material3.MaterialTheme

@Composable
fun MessageCard(msg: Message) {
   Row(modifier = Modifier.padding(all = 8.dp)) {
       Image(
           painter = painterResource(R.drawable.profile_picture),
           contentDescription = null,
           modifier = Modifier
               .size(40.dp)
               .clip(CircleShape)
               .border(1.5.dp, MaterialTheme.colorScheme.primary, CircleShape)
       )

       Spacer(modifier = Modifier.width(8.dp))

       Column {
           Text(
               text = msg.author,
               color = MaterialTheme.colorScheme.secondary
           )

           Spacer(modifier = Modifier.height(4.dp))
           Text(text = msg.body)
       }
   }
}

  
نمایش پیش نمایش
پنهان کردن پیش نمایش

تایپوگرافی

سبک‌های تایپوگرافی متریال در MaterialTheme در دسترس هستند، فقط آنها را به Text composable اضافه کنید.

// ...

@Composable
fun MessageCard(msg: Message) {
   Row(modifier = Modifier.padding(all = 8.dp)) {
       Image(
           painter = painterResource(R.drawable.profile_picture),
           contentDescription = null,
           modifier = Modifier
               .size(40.dp)
               .clip(CircleShape)
               .border(1.5.dp, MaterialTheme.colorScheme.primary, CircleShape)
       )
       Spacer(modifier = Modifier.width(8.dp))

       Column {
           Text(
               text = msg.author,
               color = MaterialTheme.colorScheme.secondary,
               style = MaterialTheme.typography.titleSmall
           )

           Spacer(modifier = Modifier.height(4.dp))

           Text(
               text = msg.body,
               style = MaterialTheme.typography.bodyMedium
           )
       }
   }
}

  
نمایش پیش نمایش
پنهان کردن پیش نمایش

شکل

با Shape می توانید آخرین لمس ها را اضافه کنید. ابتدا متن متن پیام را در اطراف یک Surface composable بپیچید. انجام این کار امکان سفارشی کردن شکل و ارتفاع متن پیام را فراهم می کند. برای چیدمان بهتر، padding نیز به پیام اضافه شده است.

// ...
import androidx.compose.material3.Surface

@Composable
fun MessageCard(msg: Message) {
   Row(modifier = Modifier.padding(all = 8.dp)) {
       Image(
           painter = painterResource(R.drawable.profile_picture),
           contentDescription = null,
           modifier = Modifier
               .size(40.dp)
               .clip(CircleShape)
               .border(1.5.dp, MaterialTheme.colorScheme.primary, CircleShape)
       )
       Spacer(modifier = Modifier.width(8.dp))

       Column {
           Text(
               text = msg.author,
               color = MaterialTheme.colorScheme.secondary,
               style = MaterialTheme.typography.titleSmall
           )

           Spacer(modifier = Modifier.height(4.dp))

           Surface(shape = MaterialTheme.shapes.medium, shadowElevation = 1.dp) {
               Text(
                   text = msg.body,
                   modifier = Modifier.padding(all = 4.dp),
                   style = MaterialTheme.typography.bodyMedium
               )
           }
       }
   }
}

  
نمایش پیش نمایش
پنهان کردن پیش نمایش

تم تیره را فعال کنید

تم تاریک (یا حالت شب) را می توان برای جلوگیری از روشن شدن صفحه نمایش به خصوص در شب یا صرفه جویی در باتری دستگاه فعال کرد. به لطف پشتیبانی از طراحی مواد، Jetpack Compose می‌تواند به صورت پیش‌فرض از تم تیره استفاده کند. استفاده از رنگ‌ها، متن و پس‌زمینه متریال دیزاین به‌طور خودکار با پس‌زمینه تیره سازگار می‌شود.

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

یک حاشیه نویسی پیش نمایش جدید اضافه کنید و حالت شب را فعال کنید.

// ...
import android.content.res.Configuration

@Preview(name = "Light Mode")
@Preview(
    uiMode = Configuration.UI_MODE_NIGHT_YES,
    showBackground = true,
    name = "Dark Mode"
)
@Composable
fun PreviewMessageCard() {
   ComposeTutorialTheme {
    Surface {
      MessageCard(
        msg = Message("Lexi", "Hey, take a look at Jetpack Compose, it's great!")
      )
    }
   }
}
  
نمایش پیش نمایش
پنهان کردن پیش نمایش

انتخاب رنگ برای تم های روشن و تیره در فایل Theme.kt ایجاد شده توسط IDE تعریف شده است.

تا به حال یک عنصر رابط کاربری پیام ایجاد کرده اید که یک تصویر و دو متن را با سبک های مختلف نمایش می دهد و هم در تم های روشن و هم در زمینه های تاریک خوب به نظر می رسد!

// ...
import android.content.res.Configuration

@Preview(name = "Light Mode")
@Preview(
    uiMode = Configuration.UI_MODE_NIGHT_YES,
    showBackground = true,
    name = "Dark Mode"
)
@Composable
fun PreviewMessageCard() {
   ComposeTutorialTheme {
    Surface {
      MessageCard(
        msg = Message("Lexi", "Hey, take a look at Jetpack Compose, it's great!")
      )
    }
   }
}
  
نمایش پیش نمایش
پنهان کردن پیش نمایش
// ...

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            ComposeTutorialTheme {
                Surface(modifier = Modifier.fillMaxSize()) {
                    MessageCard(Message("Android", "Jetpack Compose"))
                }
            }
        }
    }
}

@Preview
@Composable
fun PreviewMessageCard() {
    ComposeTutorialTheme {
        Surface {
            MessageCard(
                msg = Message("Lexi", "Take a look at Jetpack Compose, it's great!")
            )
        }
    }
}


  
نمایش پیش نمایش
پنهان کردن پیش نمایش
// ...
import androidx.compose.foundation.border
import androidx.compose.material3.MaterialTheme

@Composable
fun MessageCard(msg: Message) {
   Row(modifier = Modifier.padding(all = 8.dp)) {
       Image(
           painter = painterResource(R.drawable.profile_picture),
           contentDescription = null,
           modifier = Modifier
               .size(40.dp)
               .clip(CircleShape)
               .border(1.5.dp, MaterialTheme.colorScheme.primary, CircleShape)
       )

       Spacer(modifier = Modifier.width(8.dp))

       Column {
           Text(
               text = msg.author,
               color = MaterialTheme.colorScheme.secondary
           )

           Spacer(modifier = Modifier.height(4.dp))
           Text(text = msg.body)
       }
   }
}

  
نمایش پیش نمایش
پنهان کردن پیش نمایش
// ...

@Composable
fun MessageCard(msg: Message) {
   Row(modifier = Modifier.padding(all = 8.dp)) {
       Image(
           painter = painterResource(R.drawable.profile_picture),
           contentDescription = null,
           modifier = Modifier
               .size(40.dp)
               .clip(CircleShape)
               .border(1.5.dp, MaterialTheme.colorScheme.primary, CircleShape)
       )
       Spacer(modifier = Modifier.width(8.dp))

       Column {
           Text(
               text = msg.author,
               color = MaterialTheme.colorScheme.secondary,
               style = MaterialTheme.typography.titleSmall
           )

           Spacer(modifier = Modifier.height(4.dp))

           Text(
               text = msg.body,
               style = MaterialTheme.typography.bodyMedium
           )
       }
   }
}

  
نمایش پیش نمایش
پنهان کردن پیش نمایش
// ...
import androidx.compose.material3.Surface

@Composable
fun MessageCard(msg: Message) {
   Row(modifier = Modifier.padding(all = 8.dp)) {
       Image(
           painter = painterResource(R.drawable.profile_picture),
           contentDescription = null,
           modifier = Modifier
               .size(40.dp)
               .clip(CircleShape)
               .border(1.5.dp, MaterialTheme.colorScheme.primary, CircleShape)
       )
       Spacer(modifier = Modifier.width(8.dp))

       Column {
           Text(
               text = msg.author,
               color = MaterialTheme.colorScheme.secondary,
               style = MaterialTheme.typography.titleSmall
           )

           Spacer(modifier = Modifier.height(4.dp))

           Surface(shape = MaterialTheme.shapes.medium, shadowElevation = 1.dp) {
               Text(
                   text = msg.body,
                   modifier = Modifier.padding(all = 4.dp),
                   style = MaterialTheme.typography.bodyMedium
               )
           }
       }
   }
}

  
نمایش پیش نمایش
پنهان کردن پیش نمایش
// ...
import android.content.res.Configuration

@Preview(name = "Light Mode")
@Preview(
    uiMode = Configuration.UI_MODE_NIGHT_YES,
    showBackground = true,
    name = "Dark Mode"
)
@Composable
fun PreviewMessageCard() {
   ComposeTutorialTheme {
    Surface {
      MessageCard(
        msg = Message("Lexi", "Hey, take a look at Jetpack Compose, it's great!")
      )
    }
   }
}
  
نمایش پیش نمایش
پنهان کردن پیش نمایش
پیش نمایشی که هم ترکیب‌پذیر با مضمون روشن و هم تاریک را نشان می‌دهد.

لیستی از پیام ها ایجاد کنید

چت با یک پیام کمی احساس تنهایی می کند، بنابراین می خواهیم مکالمه را به بیش از یک پیام تغییر دهیم. شما باید یک تابع Conversation ایجاد کنید که چندین پیام را نشان دهد. برای این مورد، از Compose's LazyColumn و LazyRow استفاده کنید. این ترکیب‌پذیرها فقط عناصری را ارائه می‌کنند که روی صفحه قابل مشاهده هستند، بنابراین برای لیست‌های طولانی بسیار کارآمد طراحی شده‌اند.

در این قطعه کد می بینید که LazyColumn دارای یک items فرزند است. یک List به عنوان پارامتر می گیرد و لامبدا آن پارامتری را که ما نامش را message گذاشته ایم دریافت می کند (می توانستیم نام آن را هر چه می خواهیم بگذاریم) که نمونه ای از Message است. به طور خلاصه، این لامبدا برای هر مورد از List ارائه شده فراخوانی می شود. برای کمک به بوت استرپ سریع مکالمه، مجموعه داده نمونه را در پروژه خود کپی کنید.

// ...
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items

@Composable
fun Conversation(messages: List<Message>) {
    LazyColumn {
        items(messages) { message ->
            MessageCard(message)
        }
    }
}

@Preview
@Composable
fun PreviewConversation() {
    ComposeTutorialTheme {
        Conversation(SampleData.conversationSample)
    }
}

  
نمایش پیش نمایش
پنهان کردن پیش نمایش

پیام ها را در حین گسترش متحرک کنید

گفتگو جذاب تر می شود. وقت آن است که با انیمیشن ها بازی کنید! شما توانایی گسترش یک پیام برای نشان دادن پیام طولانی‌تر را اضافه می‌کنید که هم اندازه محتوا و هم رنگ پس‌زمینه را متحرک می‌کند. برای ذخیره این حالت رابط کاربری محلی، باید پیگیری کنید که آیا پیامی گسترش یافته است یا خیر. برای پیگیری این تغییر حالت، باید از توابع remember و mutableStateOf استفاده کنید.

توابع Composable می توانند با استفاده از remember وضعیت محلی را در حافظه ذخیره کنند و تغییرات مقدار ارسال شده به mutableStateOf را دنبال کنند. Composable ها (و فرزندان آنها) که از این حالت استفاده می کنند، هنگامی که مقدار به روز می شود، به طور خودکار دوباره ترسیم می شوند. به این ترکیب مجدد می گویند.

با استفاده از APIهای حالت Compose مانند remember و mutableStateOf ، هر تغییری در حالت به‌طور خودکار رابط کاربری را به‌روزرسانی می‌کند.

توجه: برای استفاده صحیح از نحو خصوصیت واگذار شده کاتلین ( by کلیدی) باید واردهای زیر را اضافه کنید. Alt+Enter یا Option+Enter آنها را برای شما اضافه می کند.
import androidx.compose.runtime.getValue import androidx.compose.runtime.setValue

// ...
import androidx.compose.foundation.clickable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue

class MainActivity : ComponentActivity() {
   override fun onCreate(savedInstanceState: Bundle?) {
       super.onCreate(savedInstanceState)
       setContent {
           ComposeTutorialTheme {
               Conversation(SampleData.conversationSample)
           }
       }
   }
}

@Composable
fun MessageCard(msg: Message) {
    Row(modifier = Modifier.padding(all = 8.dp)) {
        Image(
            painter = painterResource(R.drawable.profile_picture),
            contentDescription = null,
            modifier = Modifier
                .size(40.dp)
                .clip(CircleShape)
                .border(1.5.dp, MaterialTheme.colorScheme.primary, CircleShape)
        )
        Spacer(modifier = Modifier.width(8.dp))

        // We keep track if the message is expanded or not in this
        // variable
        var isExpanded by remember { mutableStateOf(false) }

        // We toggle the isExpanded variable when we click on this Column
        Column(modifier = Modifier.clickable { isExpanded = !isExpanded }) {
            Text(
                text = msg.author,
                color = MaterialTheme.colorScheme.secondary,
                style = MaterialTheme.typography.titleSmall
            )

            Spacer(modifier = Modifier.height(4.dp))

            Surface(
                shape = MaterialTheme.shapes.medium,
                shadowElevation = 1.dp,
            ) {
                Text(
                    text = msg.body,
                    modifier = Modifier.padding(all = 4.dp),
                    // If the message is expanded, we display all its content
                    // otherwise we only display the first line
                    maxLines = if (isExpanded) Int.MAX_VALUE else 1,
                    style = MaterialTheme.typography.bodyMedium
                )
            }
        }
    }
}

  
نمایش پیش نمایش
پنهان کردن پیش نمایش

اکنون می‌توانید پس‌زمینه محتوای پیام را بر اساس isExpanded زمانی که روی یک پیام کلیک می‌کنیم، تغییر دهید. شما از اصلاح کننده clickable برای مدیریت رویدادهای کلیکی روی composable استفاده خواهید کرد. به جای تغییر رنگ پس‌زمینه Surface ، رنگ پس‌زمینه را با تغییر تدریجی مقدار آن از MaterialTheme.colorScheme.surface به MaterialTheme.colorScheme.primary و بالعکس متحرک خواهید کرد. برای انجام این کار، از تابع animateColorAsState استفاده خواهید کرد. در نهایت، شما از اصلاح کننده animateContentSize برای متحرک سازی حجم محفظه پیام به راحتی استفاده خواهید کرد:

// ...
import androidx.compose.animation.animateColorAsState
import androidx.compose.animation.animateContentSize

@Composable
fun MessageCard(msg: Message) {
    Row(modifier = Modifier.padding(all = 8.dp)) {
        Image(
            painter = painterResource(R.drawable.profile_picture),
            contentDescription = null,
            modifier = Modifier
                .size(40.dp)
                .clip(CircleShape)
                .border(1.5.dp, MaterialTheme.colorScheme.secondary, CircleShape)
        )
        Spacer(modifier = Modifier.width(8.dp))

        // We keep track if the message is expanded or not in this
        // variable
        var isExpanded by remember { mutableStateOf(false) }
        // surfaceColor will be updated gradually from one color to the other
        val surfaceColor by animateColorAsState(
            if (isExpanded) MaterialTheme.colorScheme.primary else MaterialTheme.colorScheme.surface,
        )

        // We toggle the isExpanded variable when we click on this Column
        Column(modifier = Modifier.clickable { isExpanded = !isExpanded }) {
            Text(
                text = msg.author,
                color = MaterialTheme.colorScheme.secondary,
                style = MaterialTheme.typography.titleSmall
            )

            Spacer(modifier = Modifier.height(4.dp))

            Surface(
                shape = MaterialTheme.shapes.medium,
                shadowElevation = 1.dp,
                // surfaceColor color will be changing gradually from primary to surface
                color = surfaceColor,
                // animateContentSize will change the Surface size gradually
                modifier = Modifier.animateContentSize().padding(1.dp)
            ) {
                Text(
                    text = msg.body,
                    modifier = Modifier.padding(all = 4.dp),
                    // If the message is expanded, we display all its content
                    // otherwise we only display the first line
                    maxLines = if (isExpanded) Int.MAX_VALUE else 1,
                    style = MaterialTheme.typography.bodyMedium
                )
            }
        }
    }
}

  
نمایش پیش نمایش
پنهان کردن پیش نمایش
// ...
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items

@Composable
fun Conversation(messages: List<Message>) {
    LazyColumn {
        items(messages) { message ->
            MessageCard(message)
        }
    }
}

@Preview
@Composable
fun PreviewConversation() {
    ComposeTutorialTheme {
        Conversation(SampleData.conversationSample)
    }
}

  
نمایش پیش نمایش
پنهان کردن پیش نمایش
// ...
import androidx.compose.foundation.clickable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue

class MainActivity : ComponentActivity() {
   override fun onCreate(savedInstanceState: Bundle?) {
       super.onCreate(savedInstanceState)
       setContent {
           ComposeTutorialTheme {
               Conversation(SampleData.conversationSample)
           }
       }
   }
}

@Composable
fun MessageCard(msg: Message) {
    Row(modifier = Modifier.padding(all = 8.dp)) {
        Image(
            painter = painterResource(R.drawable.profile_picture),
            contentDescription = null,
            modifier = Modifier
                .size(40.dp)
                .clip(CircleShape)
                .border(1.5.dp, MaterialTheme.colorScheme.primary, CircleShape)
        )
        Spacer(modifier = Modifier.width(8.dp))

        // We keep track if the message is expanded or not in this
        // variable
        var isExpanded by remember { mutableStateOf(false) }

        // We toggle the isExpanded variable when we click on this Column
        Column(modifier = Modifier.clickable { isExpanded = !isExpanded }) {
            Text(
                text = msg.author,
                color = MaterialTheme.colorScheme.secondary,
                style = MaterialTheme.typography.titleSmall
            )

            Spacer(modifier = Modifier.height(4.dp))

            Surface(
                shape = MaterialTheme.shapes.medium,
                shadowElevation = 1.dp,
            ) {
                Text(
                    text = msg.body,
                    modifier = Modifier.padding(all = 4.dp),
                    // If the message is expanded, we display all its content
                    // otherwise we only display the first line
                    maxLines = if (isExpanded) Int.MAX_VALUE else 1,
                    style = MaterialTheme.typography.bodyMedium
                )
            }
        }
    }
}

  
نمایش پیش نمایش
پنهان کردن پیش نمایش
// ...
import androidx.compose.animation.animateColorAsState
import androidx.compose.animation.animateContentSize

@Composable
fun MessageCard(msg: Message) {
    Row(modifier = Modifier.padding(all = 8.dp)) {
        Image(
            painter = painterResource(R.drawable.profile_picture),
            contentDescription = null,
            modifier = Modifier
                .size(40.dp)
                .clip(CircleShape)
                .border(1.5.dp, MaterialTheme.colorScheme.secondary, CircleShape)
        )
        Spacer(modifier = Modifier.width(8.dp))

        // We keep track if the message is expanded or not in this
        // variable
        var isExpanded by remember { mutableStateOf(false) }
        // surfaceColor will be updated gradually from one color to the other
        val surfaceColor by animateColorAsState(
            if (isExpanded) MaterialTheme.colorScheme.primary else MaterialTheme.colorScheme.surface,
        )

        // We toggle the isExpanded variable when we click on this Column
        Column(modifier = Modifier.clickable { isExpanded = !isExpanded }) {
            Text(
                text = msg.author,
                color = MaterialTheme.colorScheme.secondary,
                style = MaterialTheme.typography.titleSmall
            )

            Spacer(modifier = Modifier.height(4.dp))

            Surface(
                shape = MaterialTheme.shapes.medium,
                shadowElevation = 1.dp,
                // surfaceColor color will be changing gradually from primary to surface
                color = surfaceColor,
                // animateContentSize will change the Surface size gradually
                modifier = Modifier.animateContentSize().padding(1.dp)
            ) {
                Text(
                    text = msg.body,
                    modifier = Modifier.padding(all = 4.dp),
                    // If the message is expanded, we display all its content
                    // otherwise we only display the first line
                    maxLines = if (isExpanded) Int.MAX_VALUE else 1,
                    style = MaterialTheme.typography.bodyMedium
                )
            }
        }
    }
}

  
نمایش پیش نمایش
پنهان کردن پیش نمایش

مراحل بعدی

تبریک می گویم، شما آموزش نوشتن را به پایان رساندید! شما یک صفحه چت ساده ساخته‌اید که فهرستی از پیام‌های قابل گسترش و متحرک حاوی یک تصویر و متون را به‌طور کارآمد نشان می‌دهد، که با استفاده از اصول طراحی متریال با تم تیره و پیش‌نمایش طراحی شده است—همه در کمتر از 100 خط کد!

در اینجا چیزی است که تا کنون یاد گرفته اید:

  • تعریف توابع ترکیب پذیر
  • اضافه کردن عناصر مختلف در ترکیب بندی شما
  • ساختار مؤلفه UI خود را با استفاده از layout composables
  • گسترش ترکیبات با استفاده از اصلاح کننده ها
  • ایجاد یک لیست کارآمد
  • پیگیری وضعیت و اصلاح آن
  • افزودن تعامل کاربر بر روی یک Composable
  • متحرک سازی پیام ها در حین گسترش آنها

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

مراحل بعدی

راه اندازی
اکنون که آموزش Compose را به پایان رساندید، آماده شروع ساختن با Compose هستید.
مسیر
مسیر منتخب ما از نرم‌افزارها و ویدیوها را بررسی کنید که به شما در یادگیری و تسلط بر Jetpack Compose کمک می‌کند.