Jetpack Compose پیادهسازی طراحی Material را ارائه میدهد، سیستم طراحی جامعی برای ایجاد میاناهای دیجیتال. عناصر طراحی Material (دکمهها، کارتها، کلیدها، و غیره) برپایه زمینه Material ساخته شدهاند که روشی نظاممند برای سفارشیسازی «طراحی Material» است تا بهتر نمانام محصولتان را منعکس کند. «تم» Material شامل مشخصههای رنگ، حروفچینی، و شکل است. وقتی این مشخصهها را سفارشیسازی میکنید، تغییرات شما بهطور خودکار در عناصری که برای ساختن برنامهتان استفاده میکنید منعکس میشود.
Jetpack Compose این مفاهیم را با MaterialTheme
ترکیبشونده پیادهسازی میکند:
MaterialTheme( colors = // ... typography = // ... shapes = // ... ) { // app content }
پارامترهایی را که به MaterialTheme ارسال میکنید پیکربندی کنید تا برنامه شما زمینهدار شود.
رنگ
رنگها در «نوشتن» با کلاس 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 }
استفاده از رنگهای زمینه
بااستفاده از MaterialTheme.colors میتوانید Colors ارائهشده به عنصر ترکیبی MaterialTheme را بازیابی کنید.
Text( text = "Hello theming", color = MaterialTheme.colors.primary )
رنگ سطح و محتوا
بسیاری از عناصر جفت رنگ و رنگ محتوا را میپذیرند:
Surface( color = MaterialTheme.colors.surface, contentColor = contentColorFor(color), // ... ) { /* ... */ } TopAppBar( backgroundColor = MaterialTheme.colors.primarySurface, contentColor = contentColorFor(backgroundColor), // ... ) { /* ... */ }
این کار به شما امکان میدهد نهتنها رنگ یک عنصر ترکیبی را تنظیم کنید، بلکه رنگ پیشفرضی برای محتوا، عناصر ترکیبی موجود در آن نیز ارائه دهید. بسیاری از عناصر
ترکیبی بهطور پیشفرض از این رنگ محتوا استفاده میکنند. برای مثال، Text رنگ خود را براساس رنگ محتوای عنصر والد خود تعیین میکند و Icon از آن رنگ برای تنظیم رنگآمیزی خود استفاده میکند.
روش contentColorFor() رنگ «روشن» مناسب را برای
هر رنگ زمینهای بازیابی میکند. برای مثال، اگر primary رنگ پسزمینهای را در
Surface تنظیم کنید، از این تابع برای تنظیم onPrimary بهعنوان رنگ محتوا استفاده میکند.
اگر رنگ پسزمینه غیرزمینهای تنظیم میکنید، باید رنگ محتوای مناسبی نیز مشخص کنید. از LocalContentColor برای بازیابی رنگ محتوای ترجیحی
برای پسزمینه فعلی، در موقعیت معینی در سلسله مراتب استفاده کنید.
محتوای آلفا
اغلب میخواهید میزان تأکید بر محتوا را برای انتقال اهمیت و ارائه سلسلهمراتب دیداری تغییر دهید. توصیههای خوانایی نوشتار «طراحی مواد» توصیه میکنند از سطوح مختلف کدری برای انتقال سطوح مختلف اهمیت استفاده شود.
Jetpack Compose این کار را بااستفاده از LocalContentAlpha پیادهسازی میکند. با ارائه مقدار برای این
CompositionLocal میتوانید
یک محتوای آلفا برای سلسلهمراتب مشخص کنید. ترکیبهای تو در تو میتوانند از این مقدار برای اعمال کردن
پردازش آلفا روی محتوایشان استفاده کنند. برای مثال، Text و Icon بهطور پیشفرض از ترکیب LocalContentColor تنظیمشده برای استفاده از LocalContentAlpha استفاده میکنند. محتوا مقادیر آلفای استاندارد خاصی را مشخص میکند
(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.زمینه تیره
در «ترکیب»، با ارائه مجموعههای مختلفی از
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" )
رونهادهای ارتفاع
در «ماتریال»، سطوح در زمینههای تیره با ارتفاع بالاتر رنگهای رونهاد ارتفاع دریافت میکنند که پسزمینه آنها را روشنتر میکند. هرچه ارتفاع سطح بالاتر باشد (یعنی به منبع نور فرضی نزدیکتر باشد)، آن سطح روشنتر میشود.
ترکیبپذیر Surface این رونهادها را بهطور خودکار هنگام استفاده از
رنگهای تیره اعمال میکند، و هر ترکیبپذیر Material دیگری که از سطح استفاده میکند نیز همین کار را انجام میدهد:
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 } }
رنگهای محدود
«متریال» توصیه میکند برای زمینههای تیره، با ترجیح دادن استفاده از رنگ 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 )
شکلها
«جنس» سیستم شکل را تعریف میکند و به شما امکان میدهد شکلهای عناصر بزرگ، متوسط، و کوچک را تعریف کنید.
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 ) }
رونهادهای زمینه
با تودرتو کردن عناصر ترکیبی MaterialTheme میتوانید به معادل رونهادهای زمینه از Android
Views در Compose دست یابید. چون
MaterialTheme رنگها، حروفچینی، و شکلها را به مقدار
موضوع کنونی پیشفرض میکند، وقتی موضوعی فقط یکی از این پارامترها را تنظیم میکند،
همه پارامترهای دیگر مقادیر پیشفرض خود را حفظ میکنند.
علاوهبراین، هنگام انتقال صفحههای مبتنی بر View به Compose، مراقب استفادههای
از مشخصه android:theme باشید. احتمالاً به MaterialTheme جدیدی
در آن بخش از درخت «واسط کاربر نوشتن» نیاز دارید.
در این مثال، صفحه جزئیات از 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 (راست)، با مقادیر رنگ و ارتفاع اصلاحشده.امواج
عناصر «طراحی مواد» از موجک برای نشان دادن تعامل با آنها استفاده میکنند. اگر از 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