Jetpack Compose پیادهسازی طراحی مواد را ارائه میدهد، یک سیستم طراحی جامع برای ایجاد میاناهای دیجیتال. مؤلفههای طراحی مواد (دکمهها، کارتها، کلیدها، و غیره) براساس موضوعدهی Material ساخته شدهاند که روشی نظاممند برای سفارشیسازی «طراحی مواد» است تا نمانام محصولتان را بهتر منعکس کند. یک Material Theme شامل مشخصههای رنگ، حروفچینی، و شکل است. وقتی این مشخصهها را سفارشیسازی میکنید، تغییرات شما بهطور خودکار در مؤلفههایی که برای ساختن برنامهتان استفاده میکنید منعکس میشود.
Jetpack Compose این مفاهیم را با MaterialTheme
ترکیبکردنی پیادهسازی میکند:
MaterialTheme( colors = // ... typography = // ... shapes = // ... ) { // app content }
پارامترهایی را که به MaterialTheme ارسال میکنید پیکربندی کنید تا برنامه شما زمینهدار شود.
رنگ
رنگها در Compose با کلاس Color مدلسازی میشوند که یک کلاس نگهدارنده داده است.
val Red = Color(0xffff0000) val Blue = Color(red = 0f, green = 0f, blue = 1f)
اگرچه میتوانید این موارد را به هر شکلی که دوست دارید سازماندهی کنید (بهعنوان ثابتهای سطح بالا، در یک تکقلو، یا تعریفشده بهصورت درونخطی)، ما بهشدت توصیه میکنیم رنگها را در زمینه خود مشخص کنید و رنگها را از آنجا بازیابی کنید. این رویکرد امکان پشتیبانی از زمینه تیره و زمینههای تودرتو را فراهم میکند.
Compose کلاس Colors را برای مدلسازی سیستم رنگ Material ارائه میدهد. Colors توابع سازندهای را برای ایجاد مجموعههایی از
رنگهای روشن یا تیره ارائه میدهد:
private val Yellow200 = Color(0xffffeb46) private val Blue200 = Color(0xff91a4fc) // ... private val DarkColors = darkColors( primary = Yellow200, secondary = Blue200, // ... ) private val LightColors = lightColors( primary = Yellow500, primaryVariant = Yellow400, secondary = Blue700, // ... )
پساز تعریف Colors، میتوانید آنها را به MaterialTheme منتقل کنید:
MaterialTheme( colors = if (darkTheme) DarkColors else LightColors ) { // app content }
استفاده از رنگهای زمینه
میتوانید Colors ارائهشده به MaterialTheme composable را بااستفاده از MaterialTheme.colors بازیابی کنید.
Text( text = "Hello theming", color = MaterialTheme.colors.primary )
رنگ سطح و محتوا
بسیاری از مؤلفهها یک جفت رنگ و رنگ محتوا را میپذیرند:
Surface( color = MaterialTheme.colors.surface, contentColor = contentColorFor(color), // ... ) { /* ... */ } TopAppBar( backgroundColor = MaterialTheme.colors.primarySurface, contentColor = contentColorFor(backgroundColor), // ... ) { /* ... */ }
این به شما امکان میدهد نهتنها رنگ یک composable را تنظیم کنید، بلکه یک رنگ پیشفرض برای محتوا، composableهای موجود در آن، ارائه دهید. بسیاری از
ترکیبشدنیها بهطور پیشفرض از این رنگ محتوا استفاده میکنند. برای مثال، Text رنگ خود را براساس رنگ محتوای والد خود قرار میدهد و Icon از آن رنگ برای تنظیم تهرنگ خود استفاده میکند.
روش contentColorFor() رنگ «روشن» مناسب را برای هر رنگ زمینهای بازیابی میکند. برای مثال، اگر رنگ پسزمینه primary را روی
Surface تنظیم کنید، از این تابع برای تنظیم onPrimary بهعنوان رنگ محتوا استفاده میکند.
اگر رنگ پسزمینه غیرزمینه تنظیم میکنید، باید رنگ محتوای مناسبی نیز مشخص کنید. از LocalContentColor برای بازیابی رنگ محتوای ترجیحی برای پسزمینه فعلی در موقعیت مشخصی در سلسلهمراتب استفاده کنید.
آلفای محتوا
اغلب میخواهید میزان تأکید بر محتوا را تغییر دهید تا اهمیت آن را منتقل کنید و سلسلهمراتب دیداری ارائه دهید. توصیههای خوانایی نوشتار Material Design توصیه میکنند که از سطوح مختلفی از کدر بودن برای انتقال سطوح مختلف اهمیت استفاده شود.
Jetpack Compose این کار را بااستفاده از LocalContentAlpha پیادهسازی میکند. میتوانید با ارائه مقداری برای این CompositionLocal، آلفای محتوا را برای سلسلهمراتب مشخص کنید. ترکیبپذیرهای تودرتو میتوانند از این مقدار برای اعمال
پردازش آلفا به محتوایشان استفاده کنند. برای مثال، Text و Icon بهطور پیشفرض از ترکیب LocalContentColor استفاده میکنند که برای استفاده از LocalContentAlpha تنظیم شده است. Material برخیاز مقادیر استاندارد آلفا
(high، medium، disabled) را که توسط شیء
ContentAlpha مدلسازی شدهاند مشخص میکند.
// By default, both Icon & Text use the combination of LocalContentColor & // LocalContentAlpha. De-emphasize content by setting content alpha CompositionLocalProvider(LocalContentAlpha provides ContentAlpha.medium) { Text( // ... ) } CompositionLocalProvider(LocalContentAlpha provides ContentAlpha.disabled) { Icon( // ... ) Text( // ... ) }
برای کسب اطلاعات بیشتر درباره CompositionLocal، به دادههای با دامنه محلی با
CompositionLocal مراجعه کنید.
ContentAlpha.high استفاده میکند. خط دوم حاوی فرادادههای کماهمیتتر است و بنابراین از ContentAlpha.medium استفاده میکند.زمینه تیره
در Compose، با ارائه مجموعههای مختلفی از
Colors به ترکیبشدنی MaterialTheme، زمینههای روشن و تیره را پیادهسازی میکنید:
@Composable fun MyTheme( darkTheme: Boolean = isSystemInDarkTheme(), content: @Composable () -> Unit ) { MaterialTheme( colors = if (darkTheme) DarkColors else LightColors, /*...*/ content = content ) }
در این مثال، MaterialTheme در تابع ترکیبپذیر خودش قرار گرفته است،
که پارامتری را میپذیرد که مشخص میکند از زمینه تیره استفاده شود یا نه. در
این حالت، تابع با پرسمان از
تنظیم زمینه دستگاه، مقدار پیشفرض را برای darkTheme دریافت میکند.
میتوانید از کدی مانند این برای بررسی اینکه آیا Colors فعلی روشن یا تاریک است استفاده کنید:
val isLightTheme = MaterialTheme.colors.isLight Icon( painterResource( id = if (isLightTheme) { R.drawable.ic_sun_24 } else { R.drawable.ic_moon_24 } ), contentDescription = "Theme" )
رونهادهای ارتفاع
در Material، سطوح در طرحهای زمینه تیره با ارتفاع بیشتر، روکشهای ارتفاع دریافت میکنند که پسزمینه آنها را روشنتر میکند. هرچه ارتفاع سطح بیشتر باشد (به منبع نور فرضی نزدیکتر شود)، آن سطح روشنتر میشود.
Surface composable applies these overlays automatically when using
dark colors, and so does any other Material composable which uses a surface:
Surface( elevation = 2.dp, color = MaterialTheme.colors.surface, // color will be adjusted for elevation /*...*/ ) { /*...*/ }
surface بهعنوان پسزمینه استفاده میکنند. ازآنجاییکه کارتها و پیمایش پایین در سطوح ارتفاعی متفاوتی نسبت به پسزمینه قرار دارند، رنگهای کمی متفاوتی دارند - کارتها روشنتر از پسزمینه هستند و پیمایش پایین روشنتر از کارتها است.برای سناریوهای سفارشی که شامل Surface نمیشوند، از
LocalElevationOverlay استفاده کنید، CompositionLocal حاوی
ElevationOverlay که توسط مؤلفههای Surface استفاده میشود:
// Elevation overlays // Implemented in Surface (and any components that use it) val color = MaterialTheme.colors.surface val elevation = 4.dp val overlaidColor = LocalElevationOverlay.current?.apply( color, elevation )
برای غیرفعال کردن همپوشانیهای ارتفاع، null را در نقطه انتخابشده در
سلسلهمراتب ترکیبپذیر ارائه دهید:
MyTheme { CompositionLocalProvider(LocalElevationOverlay provides null) { // Content without elevation overlays } }
رنگهای ثانویه محدود
Material توصیه میکند برای زمینههای تیره از رنگهای تأکیدی محدود استفاده کنید و در بیشتر موارد، استفاده از رنگ surface را به رنگ primary ترجیح دهید. ترکیبپذیرهای Material مانند TopAppBar و BottomNavigation
این رفتار را بهطور پیشفرض پیادهسازی میکنند.
برای سناریوهای سفارشی، از ویژگی افزونه primarySurface استفاده کنید:
Surface( // Switches between primary in light theme and surface in dark theme color = MaterialTheme.colors.primarySurface, /*...*/ ) { /*...*/ }
نویسهنگاری
Material سیستم نوع را تعریف میکند و شما را تشویق میکند از تعداد کمی سبک با نام معنایی استفاده کنید.
Compose سیستم نوع را با کلاسهای Typography،
TextStyle، و مرتبط با قلم پیادهسازی میکند. سازنده Typography
برای هر سبک، پیشفرضهایی ارائه میدهد تا بتوانید هرکدام را که نمیخواهید سفارشیسازی کنید حذف کنید:
val raleway = FontFamily( Font(R.font.raleway_regular), Font(R.font.raleway_medium, FontWeight.W500), Font(R.font.raleway_semibold, FontWeight.SemiBold) ) val myTypography = Typography( h1 = TextStyle( fontFamily = raleway, fontWeight = FontWeight.W300, fontSize = 96.sp ), body1 = TextStyle( fontFamily = raleway, fontWeight = FontWeight.W600, fontSize = 16.sp ) /*...*/ ) MaterialTheme(typography = myTypography, /*...*/) { /*...*/ }
اگر میخواهید از یک طرح حروف در سراسر سند استفاده کنید، پارامتر defaultFontFamily را مشخص کنید و fontFamily را از هر عنصر TextStyle حذف کنید:
val typography = Typography(defaultFontFamily = raleway) MaterialTheme(typography = typography, /*...*/) { /*...*/ }
استفاده از سبکهای نوشتار
عناصر TextStyle بااستفاده از MaterialTheme.typography قابلدسترسی هستند. عناصر TextStyle را بهصورت زیر بازیابی کنید:
Text( text = "Subtitle2 styled", style = MaterialTheme.typography.subtitle2 )
شکلها
Material سیستم شکل را تعریف میکند و به شما امکان میدهد شکلهایی برای عناصر بزرگ، متوسط، و کوچک تعریف کنید.
Compose سیستم شکل را با کلاس Shapes پیادهسازی میکند که به شما امکان میدهد
CornerBasedShape را برای هر دسته اندازه مشخص کنید:
val shapes = Shapes( small = RoundedCornerShape(percent = 50), medium = RoundedCornerShape(0f), large = CutCornerShape( topStart = 16.dp, topEnd = 0.dp, bottomEnd = 0.dp, bottomStart = 16.dp ) ) MaterialTheme(shapes = shapes, /*...*/) { /*...*/ }
بسیاری از مؤلفهها بهطور پیشفرض از این شکلها استفاده میکنند. برای مثال، Button،
TextField، و FloatingActionButton بهطور پیشفرض کوچک هستند،
AlertDialog بهطور پیشفرض متوسط است، و ModalDrawer بهطور پیشفرض
بزرگ است — برای نگاشت کامل، به مرجع طرح شکل مراجعه کنید.
استفاده از شکلها
عناصر Shape بااستفاده از MaterialTheme.shapes قابلدسترسی هستند. عناصر
Shape را با کدی مثل این بازیابی کنید:
Surface( shape = MaterialTheme.shapes.medium, /*...*/ ) { /*...*/ }
سبکهای پیشفرض
مفهوم معادلی در Compose برای سبکهای پیشفرض از Android
Views وجود ندارد. میتوانید با ایجاد overload
توابع ترکیبپذیر خودتان که مؤلفههای Material را دربرمیگیرند، عملکرد مشابهی ارائه دهید. برای مثال، برای ایجاد
سبک دکمه، دکمهای را در تابع ترکیبپذیر خودتان بپیچید، مستقیماً
پارامترهایی را که میخواهید یا نیاز دارید تغییر دهید تنظیم کنید و بقیه را بهعنوان پارامترهایی برای
ترکیبپذیر حاوی آنها نمایش دهید.
@Composable fun MyButton( onClick: () -> Unit, modifier: Modifier = Modifier, content: @Composable RowScope.() -> Unit ) { Button( colors = ButtonDefaults.buttonColors( backgroundColor = MaterialTheme.colors.secondary ), onClick = onClick, modifier = modifier, content = content ) }
رونهادهای زمینه
میتوانید با تودرتو کردن composableهای MaterialTheme، به معادل همپوشانیهای زمینهای از Android Views در Compose دست یابید. چون
MaterialTheme رنگها، تایپوگرافی، و شکلها را بهطور پیشفرض روی مقدار زمینه فعلی تنظیم میکند،
وقتی زمینهای فقط یکی از این پارامترها را تنظیم میکند،
همه پارامترهای دیگر مقادیر پیشفرض خود را حفظ میکنند.
علاوهبراین، هنگام انتقال صفحههای مبتنی بر View به Compose، مراقب استفاده از مشخصه android:theme باشید. احتمالاً به MaterialTheme جدیدی
در آن بخش از درخت Compose UI نیاز دارید.
در این مثال، صفحه جزئیات از PinkTheme برای بیشتر صفحه،
و سپس از BlueTheme برای بخش مربوطه استفاده میکند. نماگرفت و کد زیر این مفهوم را نشان میدهد:
@Composable fun DetailsScreen(/* ... */) { PinkTheme { // other content RelatedSection() } } @Composable fun RelatedSection(/* ... */) { BlueTheme { // content } }
وضعیت عناصر
اجزای Material که میتوان با آنها تعامل داشت (کلیک کرد، تغییر وضعیت داد، و غیره) میتوانند در حالتهای دیداری مختلفی باشند. حالتها شامل فعال، غیرفعال، فشردهشده، و غیره است.
ترکیبشدنیها اغلب پارامتر enabled دارند. تنظیم آن روی false از تعامل جلوگیری میکند و ویژگیهایی مانند رنگ و ارتفاع را تغییر میدهد تا وضعیت مؤلفه را بهصورت بصری منتقل کند.
enabled = true (چپ) و enabled = false (راست).در بیشتر موارد میتوانید برای مقادیری مثل رنگ و ارتفاع به پیشفرضها تکیه کنید. اگر باید مقادیر مورداستفاده در حالتهای مختلف را پیکربندی کنید، کلاسها و توابع راحتی دردسترس هستند. مثال دکمه زیر را درنظر بگیرید:
Button( onClick = { /* ... */ }, enabled = true, // Custom colors for different states colors = ButtonDefaults.buttonColors( backgroundColor = MaterialTheme.colors.secondary, disabledBackgroundColor = MaterialTheme.colors.onBackground .copy(alpha = 0.2f) .compositeOver(MaterialTheme.colors.background) // Also contentColor and disabledContentColor ), // Custom elevation for different states elevation = ButtonDefaults.elevation( defaultElevation = 8.dp, disabledElevation = 2.dp, // Also pressedElevation ) ) { /* ... */ }
enabled = true (چپ) و enabled = false (راست)، با مقادیر رنگ و ارتفاع تنظیمشده.امواج
مؤلفههای Material از موج برای نشان دادن تعامل با آنها استفاده میکنند. اگر
از MaterialTheme در سلسلهمراتب خود استفاده میکنید، یک Ripple بهعنوان
Indication پیشفرض در داخل اصلاحکنندههایی مانند clickable و
indication استفاده میشود.
در بیشتر موارد میتوانید به Ripple پیشفرض اعتماد کنید. اگر لازم است ظاهر آنها را پیکربندی کنید، میتوانید از RippleTheme برای تغییر ویژگیهایی مثل رنگ و آلفا استفاده کنید.
میتوانید RippleTheme را گسترش دهید و از توابع سودمندی defaultRippleColor و
defaultRippleAlpha استفاده کنید. سپس میتوانید بااستفاده از LocalRippleTheme، زمینه موجدار سفارشیتان را در سلسلهمراتب خود ارائه دهید:
@Composable fun MyApp() { MaterialTheme { CompositionLocalProvider( LocalRippleTheme provides SecondaryRippleTheme ) { // App content } } } @Immutable private object SecondaryRippleTheme : RippleTheme { @Composable override fun defaultColor() = RippleTheme.defaultRippleColor( contentColor = MaterialTheme.colors.secondary, lightTheme = MaterialTheme.colors.isLight ) @Composable override fun rippleAlpha() = RippleTheme.defaultRippleAlpha( contentColor = MaterialTheme.colors.secondary, lightTheme = MaterialTheme.colors.isLight ) }
RippleConfiguration ارائه شدهاند.بیشتر بدانید
برای کسب اطلاعات بیشتر درباره «موضوعدهی Material» در Compose، به منابع تکمیلی زیر مراجعه کنید.
Codelabs
ویدیوها
توصیهشده برای شما
- توجه: وقتی جاوا اسکریپت خاموش باشد، نوشتار پیوند نمایش داده میشود
- سیستمهای طراحی سفارشی در Compose
- انتقال از Material 2 به Material 3 در Compose
- دسترسپذیری در Compose