Material Design 2 در Compose

Jetpack Compose پیاده سازی Material Design را ارائه می دهد، یک سیستم طراحی جامع برای ایجاد رابط های دیجیتال. اجزای طراحی متریال (دکمه‌ها، کارت‌ها، سوئیچ‌ها و غیره) بر روی Material Theming ساخته شده‌اند، که روشی سیستماتیک برای سفارشی‌سازی متریال دیزاین است تا برند محصول شما را بهتر منعکس کند. یک تم متریال شامل ویژگی‌های رنگ ، تایپوگرافی و شکل است. وقتی این ویژگی ها را سفارشی می کنید، تغییرات شما به طور خودکار در مؤلفه هایی که برای ساختن برنامه خود استفاده می کنید منعکس می شود.

Jetpack Compose این مفاهیم را با MaterialTheme composable پیاده سازی می کند:

MaterialTheme(
    colors = // ...
    typography = // ...
    shapes = // ...
) {
    // app content
}

پارامترهایی را که به MaterialTheme می‌دهید تا برنامه‌تان را قالب‌بندی کنید، پیکربندی کنید.

دو اسکرین شات متضاد اولی از استایل پیش‌فرض MaterialTheme استفاده می‌کند، اسکرین شات دوم از استایل اصلاح‌شده استفاده می‌کند.

شکل 1. تصویر اول برنامه‌ای را نشان می‌دهد که MaterialTheme پیکربندی نمی‌کند، و بنابراین از استایل پیش‌فرض استفاده می‌کند. اسکرین شات دوم برنامه ای را نشان می دهد که پارامترهایی را به MaterialTheme برای سفارشی کردن استایل ارسال می کند.

رنگ

رنگ‌ها در Compose با کلاس Color مدل‌سازی می‌شوند، یک کلاس ساده نگهدارنده داده.

val Red = Color(0xffff0000)
val Blue = Color(red = 0f, green = 0f, blue = 1f)

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

نمونه ای از پالت رنگ تم

شکل 2. سیستم رنگ مواد.

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),
    // ...
) { /* ... */ }

این به شما امکان می‌دهد نه تنها رنگ یک کامپوزیشن را تنظیم کنید، بلکه یک رنگ پیش‌فرض برای محتوا، ترکیب‌بندی‌های موجود در آن نیز ارائه کنید. بسیاری از composable ها به طور پیش فرض از این رنگ محتوا استفاده می کنند. به عنوان مثال، Text رنگ خود را بر اساس رنگ محتوای والد خود قرار می دهد و Icon از آن رنگ برای تنظیم رنگ خود استفاده می کند.

دو نمونه از یک بنر، با رنگ های مختلف

شکل 3. تنظیم رنگ های مختلف پس زمینه، رنگ های متن و نماد متفاوتی را تولید می کند.

متد 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 بررسی کنید.

عکس صفحه عنوان یک مقاله، سطوح مختلف تاکید متن را نشان می دهد

شکل 4. سطوح مختلف تاکید را بر روی متن اعمال کنید تا به صورت بصری سلسله مراتب اطلاعات را منتقل کنید. خط اول متن عنوان است و دارای مهمترین اطلاعات است و بنابراین از 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"
)

پوشش های ارتفاعی

در متریال، سطوح دارای تم‌های تیره با ارتفاع بالاتر، پوشش‌های ارتفاعی دریافت می‌کنند که پس‌زمینه آن‌ها را روشن می‌کند. هر چه ارتفاع یک سطح بیشتر باشد (آن را به منبع نور ضمنی نزدیکتر می کند)، آن سطح سبک تر می شود.

این پوشش‌ها به‌طور خودکار توسط Surface Composable هنگام استفاده از رنگ‌های تیره و برای هر ماده دیگری که از یک سطح استفاده می‌کند اعمال می‌شود:

Surface(
    elevation = 2.dp,
    color = MaterialTheme.colors.surface, // color will be adjusted for elevation
    /*...*/
) { /*...*/ }

اسکرین شات یک برنامه، رنگ‌های متفاوت مورد استفاده برای عناصر در سطوح مختلف ارتفاع را نشان می‌دهد

شکل 5. کارت ها و ناوبری پایین هر دو از رنگ 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 در بیشتر موارد توصیه می کند. مواد قابل ترکیب مانند TopAppBar و BottomNavigation این رفتار را به طور پیش فرض پیاده سازی می کنند.

شکل 6. تم تیره متریال با لهجه های رنگی محدود. نوار برنامه بالا از رنگ اصلی در طرح زمینه روشن و رنگ سطح در تم تیره استفاده می کند.

برای سناریوهای سفارشی، از ویژگی افزونه primarySurface استفاده کنید:

Surface(
    // Switches between primary in light theme and surface in dark theme
    color = MaterialTheme.colors.primarySurface,
    /*...*/
) { /*...*/ }

تایپوگرافی

متریال یک سیستم نوع را تعریف می‌کند و شما را تشویق می‌کند که از تعداد کمی از سبک‌های با نام معنایی استفاده کنید.

نمونه ای از چند تایپ فیس مختلف در سبک های مختلف

شکل 7. سیستم نوع مواد.

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 parameter را مشخص کنید و fontFamily هر عنصر TextStyle را حذف کنید:

val typography = Typography(defaultFontFamily = raleway)
MaterialTheme(typography = typography, /*...*/) {
    /*...*/
}

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

TextStyle از طریق MaterialTheme.typography قابل دسترسی است. بازیابی TextStyle به این صورت:

Text(
    text = "Subtitle2 styled",
    style = MaterialTheme.typography.subtitle2
)

اسکرین شات ترکیبی از حروف مختلف را برای اهداف مختلف نشان می دهد

شکل 8. از مجموعه ای از حروف و سبک ها برای بیان نام تجاری خود استفاده کنید.

شکل

متریال یک سیستم شکل را تعریف می کند و به شما این امکان را می دهد که اشکال را برای اجزای بزرگ، متوسط ​​و کوچک تعریف کنید.

انواع اشکال طراحی متریال را نشان می دهد

شکل 9. سیستم شکل مواد.

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 s از طریق MaterialTheme.shapes قابل دسترسی است. Shape s را با کد زیر بازیابی کنید:

Surface(
    shape = MaterialTheme.shapes.medium, /*...*/
) {
    /*...*/
}

تصویری از برنامه‌ای که از اشکال مواد استفاده می‌کند تا نشان دهد یک عنصر در چه وضعیتی است

شکل 10. از اشکال برای بیان برند یا حالت استفاده کنید.

سبک های پیش فرض

هیچ مفهومی معادل در Compose of styles default from 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 نیاز دارید.

در نمونه Owl ، صفحه جزئیات از PinkTheme برای بیشتر صفحه و سپس BlueTheme برای بخش مربوطه استفاده می‌کند. اسکرین شات و کد زیر را ببینید.

شکل 11. تم های تو در تو در نمونه جغد.

@Composable
fun DetailsScreen(/* ... */) {
    PinkTheme {
        // other content
        RelatedSection()
    }
}

@Composable
fun RelatedSection(/* ... */) {
    BlueTheme {
        // content
    }
}

حالت های جزء

اجزای موادی که می توان با آنها تعامل کرد (کلیک کرد، تغییر داد و غیره) می تواند در حالت های بصری مختلف باشد. حالت ها شامل فعال، غیرفعال، فشرده و غیره است.

Composable ها اغلب یک پارامتر enabled دارند. تنظیم آن بر روی false از تعامل جلوگیری می کند و ویژگی هایی مانند رنگ و ارتفاع را تغییر می دهد تا حالت جزء را به صورت بصری منتقل کند.

شکل 12. دکمه با 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
    )
) { /* ... */ }

شکل 13. دکمه با 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
    )
}

alt_text

شکل 14. دکمه هایی با مقادیر ریپل متفاوت از طریق RippleTheme ارائه شده است.

بیشتر بدانید

برای کسب اطلاعات بیشتر در مورد Material Theming در Compose، به منابع اضافی زیر مراجعه کنید.

Codelabs

فیلم های

{% کلمه به کلمه %} {% آخر کلمه %} {% کلمه به کلمه %} {% آخر کلمه %}