Material হল আমাদের সাজেস্ট করা ডিজাইন সিস্টেম এবং Jetpack Compose-এ Material-এর ইমপ্লিমেন্টেশন থাকলেও, আপনাকে এটি ব্যবহার করতে বাধ্য করা হয় না। Material সম্পূর্ণভাবে পাবলিক API-এর উপর ভিত্তি করে তৈরি করা হয়েছে, তাই একই পদ্ধতিতে আপনার নিজস্ব ডিজাইন সিস্টেম তৈরি করা সম্ভব।
আপনি বিভিন্ন উপায়ে এটি করতে পারেন:
- অতিরিক্ত থিমিং ভ্যালু সহ
MaterialThemeএক্সটেন্ড করুন। - এক বা একাধিক মেটেরিয়াল সিস্টেম —
ColorScheme,Typography, বাShapes— কাস্টম ইমপ্লিমেন্টেশনের মাধ্যমে পরিবর্তন করুন এবং অন্যগুলি রেখে দিন। MaterialTheme-এর পরিবর্তে সম্পূর্ণ কাস্টম ডিজাইন সিস্টেম প্রয়োগ করুন।
এছাড়াও, আপনি কাস্টম ডিজাইন সিস্টেমের সাথে মেটেরিয়াল কম্পোনেন্ট ব্যবহার করা চালিয়ে যেতে চাইবেন। এটি করা সম্ভব, তবে আপনি যে পদ্ধতি অবলম্বন করেছেন তার সাথে মানানসই কিছু বিষয় মাথায় রাখতে হবে।
MaterialTheme
এবং কাস্টম ডিজাইন সিস্টেমের মাধ্যমে ব্যবহৃত লোয়ার-লেভেল কনস্ট্রাক্ট এবং API সম্পর্কে আরও জানতে, Compose-এ থিমের অ্যানাটমি গাইড চেক করুন।
মেটিরিয়াল থিমিং এক্সটেন্ড করা
Compose Material, Material Theming-এর কাছাকাছি মডেল তৈরি করে যাতে Material নির্দেশিকা অনুসরণ করা সহজ এবং টাইপ-নিরাপদ হয়। তবে, অতিরিক্ত ভ্যালু সহ রঙ, টাইপোগ্রাফি এবং আকৃতির সেট বাড়ানো সম্ভব। সবচেয়ে সহজ উপায় হল এক্সটেনশন প্রপার্টি যোগ করা:
// Use with MaterialTheme.colorScheme.snackbarAction val ColorScheme.snackbarAction: Color @Composable get() = if (isSystemInDarkTheme()) Red300 else Red700 // Use with MaterialTheme.typography.textFieldInput val Typography.textFieldInput: TextStyle get() = TextStyle(/* ... */) // Use with MaterialTheme.shapes.card val Shapes.card: Shape get() = RoundedCornerShape(size = 20.dp)
এটি MaterialTheme ব্যবহার API-এর সাথে সামঞ্জস্য প্রদান করে। Compose-এর মাধ্যমে
নির্ধারিত এর একটি উদাহরণ হল
surfaceColorAtElevation,
যা এলিভেশনের উপর নির্ভর করে সারফেসের কোন রঙ ব্যবহার করা উচিত তা নির্ধারণ করে।
আরেকটি পদ্ধতি হল, একটি এক্সটেন্ডেড থিমকে সংজ্ঞায়িত করা যা MaterialTheme এবং
তার ভ্যালুকে "র্যাপ" করে।
ধরুন, আপনি দুটি অতিরিক্ত রঙ যোগ করতে চান — caution এবং onCaution, একটি
হলুদ রঙ যা আধা-বিপজ্জনক অ্যাকশনের জন্য ব্যবহৃত হয় — তবে আগে থেকে থাকা
মেটেরিয়াল রঙগুলি রেখে:
@Immutable data class ExtendedColors( val caution: Color, val onCaution: Color ) val LocalExtendedColors = staticCompositionLocalOf { ExtendedColors( caution = Color.Unspecified, onCaution = Color.Unspecified ) } @Composable fun ExtendedTheme( /* ... */ content: @Composable () -> Unit ) { val extendedColors = ExtendedColors( caution = Color(0xFFFFCC02), onCaution = Color(0xFF2C2D30) ) CompositionLocalProvider(LocalExtendedColors provides extendedColors) { MaterialTheme( /* colors = ..., typography = ..., shapes = ... */ content = content ) } } // Use with eg. ExtendedTheme.colors.caution object ExtendedTheme { val colors: ExtendedColors @Composable get() = LocalExtendedColors.current }
এটি MaterialTheme ব্যবহারের API-এর মতো। এছাড়াও, এটি একাধিক থিম সাপোর্ট করে
কারণ আপনি MaterialTheme-এর মতো একইভাবে ExtendedTheme নেস্ট করতে পারবেন।
মেটেরিয়াল কম্পোনেন্ট ব্যবহার করুন
মেটিরিয়াল থিমিং এক্সটেন্ড করার সময়, আগে থেকে থাকা MaterialTheme ভ্যালু বজায় রাখা হয়
এবং মেটিরিয়াল কম্পোনেন্টের এখনও যুক্তিসঙ্গত ডিফল্ট থাকে।
আপনি যদি কম্পোনেন্টে এক্সটেন্ডেড ভ্যালু ব্যবহার করতে চান, তাহলে সেগুলিকে আপনার নিজের কম্পোজেবল ফাংশনে র্যাপ করুন, আপনি যে ভ্যালু পরিবর্তন করতে চান তা সরাসরি সেট করুন এবং অন্যগুলিকে কম্পোজেবল ধারণ করার প্যারামিটার হিসেবে দেখান:
@Composable fun ExtendedButton( onClick: () -> Unit, modifier: Modifier = Modifier, content: @Composable RowScope.() -> Unit ) { Button( colors = ButtonDefaults.buttonColors( containerColor = ExtendedTheme.colors.caution, contentColor = ExtendedTheme.colors.onCaution /* Other colors use values from MaterialTheme */ ), onClick = onClick, modifier = modifier, content = content ) }
তারপর আপনি যেখানে উপযুক্ত সেখানে Button-এর ব্যবহার ExtendedButton দিয়ে প্রতিস্থাপন করবেন।
@Composable fun ExtendedApp() { ExtendedTheme { /*...*/ ExtendedButton(onClick = { /* ... */ }) { /* ... */ } } }
মেটেরিয়াল সাবসিস্টেম পরিবর্তন করুন
মেটিরিয়াল থিমিং বাড়ানোর পরিবর্তে, আপনি এক বা একাধিক
সিস্টেম — ColorScheme, Typography, বা Shapes — কাস্টম
ইমপ্লিমেন্টেশনের মাধ্যমে পরিবর্তন করতে চাইতে পারেন, তবে বাকিগুলি একই থাকবে।
ধরুন, আপনি রঙ সিস্টেম রেখে টাইপ ও শেপ সিস্টেম পরিবর্তন করতে চান:
@Immutable data class ReplacementTypography( val body: TextStyle, val title: TextStyle ) @Immutable data class ReplacementShapes( val component: Shape, val surface: Shape ) val LocalReplacementTypography = staticCompositionLocalOf { ReplacementTypography( body = TextStyle.Default, title = TextStyle.Default ) } val LocalReplacementShapes = staticCompositionLocalOf { ReplacementShapes( component = RoundedCornerShape(ZeroCornerSize), surface = RoundedCornerShape(ZeroCornerSize) ) } @Composable fun ReplacementTheme( /* ... */ content: @Composable () -> Unit ) { val replacementTypography = ReplacementTypography( body = TextStyle(fontSize = 16.sp), title = TextStyle(fontSize = 32.sp) ) val replacementShapes = ReplacementShapes( component = RoundedCornerShape(percent = 50), surface = RoundedCornerShape(size = 40.dp) ) CompositionLocalProvider( LocalReplacementTypography provides replacementTypography, LocalReplacementShapes provides replacementShapes ) { MaterialTheme( /* colors = ... */ content = content ) } } // Use with eg. ReplacementTheme.typography.body object ReplacementTheme { val typography: ReplacementTypography @Composable get() = LocalReplacementTypography.current val shapes: ReplacementShapes @Composable get() = LocalReplacementShapes.current }
মেটেরিয়াল কম্পোনেন্ট ব্যবহার করুন
MaterialTheme-এর এক বা একাধিক সিস্টেম পরিবর্তন করা হলে, Material কম্পোনেন্ট
যেমন আছে তেমন ব্যবহার করলে, অবাঞ্ছিত Material কালার, টাইপ বা শেপ ভ্যালু দেখা যেতে পারে।
আপনি যদি কম্পোনেন্টে রিপ্লেসমেন্ট ভ্যালু ব্যবহার করতে চান, তাহলে সেগুলিকে আপনার নিজের কম্পোজেবল ফাংশনে র্যাপ করুন, প্রাসঙ্গিক সিস্টেমের জন্য সরাসরি ভ্যালু সেট করুন এবং অন্যগুলিকে কন্টেনিং কম্পোজেবলের প্যারামিটার হিসেবে দেখান।
@Composable fun ReplacementButton( onClick: () -> Unit, modifier: Modifier = Modifier, content: @Composable RowScope.() -> Unit ) { Button( shape = ReplacementTheme.shapes.component, onClick = onClick, modifier = modifier, content = { ProvideTextStyle( value = ReplacementTheme.typography.body ) { content() } } ) }
তারপর আপনি যেখানে উপযুক্ত সেখানে Button-এর ব্যবহার ReplacementButton দিয়ে প্রতিস্থাপন করবেন।
@Composable fun ReplacementApp() { ReplacementTheme { /*...*/ ReplacementButton(onClick = { /* ... */ }) { /* ... */ } } }
সম্পূর্ণ কাস্টম ডিজাইন সিস্টেম প্রয়োগ করুন
আপনি হয়ত মেটিরিয়াল থিমিংয়ের পরিবর্তে সম্পূর্ণ কাস্টম ডিজাইন সিস্টেম ব্যবহার করতে চাইবেন।
মনে রাখবেন যে MaterialTheme নিম্নলিখিত সিস্টেম প্রদান করে:
ColorScheme,TypographyএবংShapes: মেটিরিয়াল থিমিং সিস্টেমTextSelectionColors:TextএবংTextField-এর দ্বারা টেক্সট বেছে নেওয়ার জন্য ব্যবহৃত রঙripple,LocalIndicationহিসেবে প্রদান করা হয়েছে:Indication-এর মেটেরিয়াল ইমপ্লিমেন্টেশন
আপনি যদি মেটেরিয়াল কম্পোনেন্ট ব্যবহার করা চালিয়ে যেতে চান, তাহলে আপনার কাস্টম থিমে এইসব সিস্টেমের কিছু অংশ পরিবর্তন করতে হবে অথবা অবাঞ্ছিত আচরণ এড়াতে আপনার কম্পোনেন্টে সিস্টেম ম্যানেজ করতে হবে।
তবে, ডিজাইন সিস্টেমগুলি মেটেরিয়াল যে ধারণার উপর নির্ভর করে তার মধ্যে সীমাবদ্ধ নয়। আপনি আগে থেকে থাকা সিস্টেম পরিবর্তন করতে এবং সম্পূর্ণ নতুন সিস্টেম — নতুন ক্লাস ও প্রকার সহ — চালু করতে পারবেন যাতে অন্যান্য কনসেপ্ট থিমের সাথে মানানসই হয়।
নিম্নলিখিত কোডে, আমরা একটি কাস্টম কালার সিস্টেম মডেল করি যার মধ্যে গ্রেডিয়েন্ট (List<Color>) অন্তর্ভুক্ত থাকে,
একটি টাইপ সিস্টেম অন্তর্ভুক্ত থাকে, একটি নতুন এলিভেশন সিস্টেম চালু করা হয়
এবং MaterialTheme দ্বারা প্রদত্ত অন্যান্য সিস্টেম বাদ দেওয়া হয়:
@Immutable data class CustomColors( val content: Color, val component: Color, val background: List<Color> ) @Immutable data class CustomTypography( val body: TextStyle, val title: TextStyle ) @Immutable data class CustomElevation( val default: Dp, val pressed: Dp ) val LocalCustomColors = staticCompositionLocalOf { CustomColors( content = Color.Unspecified, component = Color.Unspecified, background = emptyList() ) } val LocalCustomTypography = staticCompositionLocalOf { CustomTypography( body = TextStyle.Default, title = TextStyle.Default ) } val LocalCustomElevation = staticCompositionLocalOf { CustomElevation( default = Dp.Unspecified, pressed = Dp.Unspecified ) } @Composable fun CustomTheme( /* ... */ content: @Composable () -> Unit ) { val customColors = CustomColors( content = Color(0xFFDD0D3C), component = Color(0xFFC20029), background = listOf(Color.White, Color(0xFFF8BBD0)) ) val customTypography = CustomTypography( body = TextStyle(fontSize = 16.sp), title = TextStyle(fontSize = 32.sp) ) val customElevation = CustomElevation( default = 4.dp, pressed = 8.dp ) CompositionLocalProvider( LocalCustomColors provides customColors, LocalCustomTypography provides customTypography, LocalCustomElevation provides customElevation, content = content ) } // Use with eg. CustomTheme.elevation.small object CustomTheme { val colors: CustomColors @Composable get() = LocalCustomColors.current val typography: CustomTypography @Composable get() = LocalCustomTypography.current val elevation: CustomElevation @Composable get() = LocalCustomElevation.current }
মেটেরিয়াল কম্পোনেন্ট ব্যবহার করুন
কোনও MaterialTheme না থাকলে, মেটিরিয়াল কম্পোনেন্ট যেমন আছে তেমন ব্যবহার করলে
অবাঞ্ছিত মেটিরিয়াল কালার, টাইপ ও শেপ ভ্যালু এবং ইঙ্গিত সংক্রান্ত আচরণ দেখা যাবে।
আপনি কম্পোনেন্টে কাস্টম ভ্যালু ব্যবহার করতে চাইলে, প্রাসঙ্গিক সিস্টেমের জন্য সরাসরি ভ্যালু সেট করে এবং কন্টেনিং কম্পোজেবলে প্যারামিটার হিসেবে অন্যদের এক্সপোজ করে, আপনার নিজস্ব কম্পোজেবল ফাংশনে সেগুলি র্যাপ করুন।
আপনার কাস্টম থিম থেকে সেট করা ভ্যালু অ্যাক্সেস করার জন্য আমরা সাজেস্ট করি।
অন্যথায়, আপনার থিমে Color, TextStyle, Shape বা
অন্য সিস্টেম না থাকলে, আপনি সেগুলি হার্ডকোড করতে পারেন।
@Composable fun CustomButton( onClick: () -> Unit, modifier: Modifier = Modifier, content: @Composable RowScope.() -> Unit ) { Button( colors = ButtonDefaults.buttonColors( containerColor = CustomTheme.colors.component, contentColor = CustomTheme.colors.content, disabledContainerColor = CustomTheme.colors.content .copy(alpha = 0.12f) .compositeOver(CustomTheme.colors.component), disabledContentColor = CustomTheme.colors.content .copy(alpha = 0.38f) ), shape = ButtonShape, elevation = ButtonDefaults.elevatedButtonElevation( defaultElevation = CustomTheme.elevation.default, pressedElevation = CustomTheme.elevation.pressed /* disabledElevation = 0.dp */ ), onClick = onClick, modifier = modifier, content = { ProvideTextStyle( value = CustomTheme.typography.body ) { content() } } ) } val ButtonShape = RoundedCornerShape(percent = 50)
আপনি যদি নতুন ধরনের ক্লাস নিয়ে আসেন — যেমন গ্রেডিয়েন্ট দেখানোর জন্য List<Color> — তাহলে
সেগুলিকে র্যাপ করার পরিবর্তে একদম শুরু থেকে কম্পোনেন্ট প্রয়োগ করা আরও ভালো হতে পারে। উদাহরণ হিসেবে, Jetsnack স্যাম্পেল থেকে
JetsnackButton
দেখুন।
আপনার জন্য সাজেস্ট করা হয়েছে
- মনে রাখবেন: জাভাস্ক্রিপ্ট বন্ধ থাকলে লিঙ্ক টেক্সট দেখানো হয়
- Compose-এ Material Design 3
- Compose-এ Material 2 থেকে Material 3-এ মাইগ্রেট করা
- Compose-এ থিমের অ্যানাটমি