یک عنصر متنی اضافه کنید
برای شروع، جدیدترین نسخه اندروید استودیو را دانلود کنید و با انتخاب پروژه جدید یک برنامه ایجاد کنید و در زیر دسته تلفن و تبلت ، فعالیت خالی را انتخاب کنید. نام برنامه خود را 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
مشخص شده اند را نشان می دهد. برای بهروزرسانی پیشنمایشها در هر زمان، روی دکمه تازهسازی در بالای پنجره پیشنمایش کلیک کنید.
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") }
چند متن اضافه کنید
تاکنون اولین عملکرد و پیش نمایش قابل ترکیب خود را ساخته اید! برای کشف قابلیتهای 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!") ) }
این کد دو عنصر متنی را در داخل نمای محتوا ایجاد می کند. با این حال، از آنجایی که شما هیچ اطلاعاتی در مورد نحوه چیدمان آنها ارائه نکرده اید، عناصر متن روی هم کشیده می شوند و متن را غیرقابل خواندن می کند.
با استفاده از یک ستون
// ... 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
- متحرک سازی پیام ها در حین گسترش آنها
اگر میخواهید در برخی از این مراحل عمیقتر شوید، منابع زیر را بررسی کنید.