১. ভূমিকা
এই কোডল্যাবে, আপনি জেটপ্যাক কম্পোজে ম্যাটেরিয়াল ডিজাইন ৩ ব্যবহার করে আপনার অ্যাপ থিমিং করা শিখবেন। এছাড়াও আপনি ম্যাটেরিয়াল ডিজাইন ৩-এর মূল উপাদান—কালার স্কিম, টাইপোগ্রাফি এবং শেপ—সম্পর্কে জানতে পারবেন, যা আপনাকে আপনার অ্যাপ্লিকেশনকে ব্যক্তিগতকৃত এবং অ্যাক্সেসিবল উপায়ে থিম করতে সাহায্য করবে।
এছাড়াও, আপনি ডাইনামিক থিমিং এবং বিভিন্ন এমফাসিস লেভেলের সাপোর্ট সম্পর্কে জানতে পারবেন।
আপনি যা শিখবেন
এই কোডল্যাবে আপনি শিখবেন:
- উপাদান ৩-এর থিমিং-এর মূল দিকগুলি
- ম্যাটেরিয়াল ৩ কালার স্কিম এবং আপনার অ্যাপের জন্য থিম তৈরি করার পদ্ধতি
- আপনার অ্যাপে কীভাবে ডাইনামিক এবং লাইট/ডার্ক থিমিং সমর্থন করবেন
- আপনার অ্যাপকে ব্যক্তিগত রূপ দিতে টাইপোগ্রাফি এবং আকার
- আপনার অ্যাপকে স্টাইল করতে ম্যাটেরিয়াল ৩-এর উপাদানসমূহ এবং কাস্টমাইজেশন।
আপনি যা তৈরি করবেন
এই কোডল্যাবে, আপনি 'Reply' নামের একটি ইমেল ক্লায়েন্ট অ্যাপ থিম করবেন। আপনি বেসলাইন থিম ব্যবহার করে একটি স্টাইলবিহীন অ্যাপ্লিকেশন দিয়ে শুরু করবেন এবং যা শিখবেন তা প্রয়োগ করে অ্যাপ্লিকেশনটি থিম করবেন ও ডার্ক থিম সমর্থন করবেন।

বেসলাইন থিম সহ আমাদের অ্যাপের ডিফল্ট প্রারম্ভিক অবস্থা।
আপনি কালার স্কিম, টাইপোগ্রাফি এবং শেপ ব্যবহার করে আপনার থিম তৈরি করবেন এবং তারপর সেটি আপনার অ্যাপের ইমেল লিস্ট ও ডিটেইল পেজে প্রয়োগ করবেন। এছাড়াও আপনি অ্যাপটিতে ডাইনামিক থিম সাপোর্ট যুক্ত করবেন। এই কোডল্যাবের শেষে, আপনার অ্যাপে কালার এবং ডাইনামিক উভয় ধরনের থিমের সাপোর্ট থাকবে।

হালকা রঙের থিমিং এবং হালকা ডাইনামিক থিমিং সহ থিমিং কোডল্যাবের শেষ বিন্দু।

ডার্ক কালার থিমিং এবং ডার্ক ডাইনামিক থিমিং সহ থিমিং কোডল্যাবের শেষ বিন্দু।
আপনার যা যা প্রয়োজন হবে
- অ্যান্ড্রয়েড স্টুডিওর সর্বশেষ সংস্করণ
- কোটলিন ভাষায় প্রাথমিক অভিজ্ঞতা
- জেটপ্যাক কম্পোজ সম্পর্কে প্রাথমিক ধারণা
- কম্পোজ লেআউট, যেমন রো , কলাম এবং মডিফায়ার সম্পর্কে প্রাথমিক ধারণা থাকা।
২. প্রস্তুতি গ্রহণ
এই ধাপে, আপনি রিপ্লাই অ্যাপের সম্পূর্ণ কোডটি ডাউনলোড করবেন, যেটিকে আপনি এই কোডল্যাবে স্টাইল করবেন।
কোডটি নিন
এই কোডল্যাবের কোডটি android-compose-codelabs গিটহাব রিপোজিটরিতে পাওয়া যাবে। এটি ক্লোন করতে, চালান:
$ git clone https://github.com/googlecodelabs/android-compose-codelabs
বিকল্পভাবে, আপনি দুটি জিপ ফাইল ডাউনলোড করতে পারেন:
নমুনা অ্যাপটি দেখুন
আপনি এইমাত্র যে কোডটি ডাউনলোড করেছেন, তাতে উপলব্ধ সমস্ত কম্পোজ কোডল্যাবের কোড রয়েছে। এই কোডল্যাবটি সম্পূর্ণ করতে, অ্যান্ড্রয়েড স্টুডিওর ভিতরে থিমিংকোডল্যাব (ThemingCodelab) প্রজেক্টটি খুলুন।
আমরা আপনাকে মেইন ব্রাঞ্চের কোড দিয়ে শুরু করার এবং নিজের গতিতে ধাপে ধাপে কোডল্যাবটি অনুসরণ করার পরামর্শ দিচ্ছি। যেকোনো সময়, প্রজেক্টের গিট ব্রাঞ্চ পরিবর্তন করে আপনি অ্যান্ড্রয়েড স্টুডিওতে যেকোনো সংস্করণ চালাতে পারবেন।
স্টার্ট কোড অন্বেষণ করা
মূল কোডে একটি UI প্যাকেজ রয়েছে, যার মধ্যে নিম্নলিখিত প্রধান প্যাকেজ এবং ফাইলগুলো আছে, যেগুলোর সাথে আপনি কাজ করবেন:
-
MainActivity.kt– এটি হলো এন্ট্রি পয়েন্ট অ্যাক্টিভিটি, যেখান থেকে আপনি রিপ্লাই অ্যাপটি চালু করেন। -
com.example.reply.ui.theme– এই প্যাকেজটিতে থিম, টাইপোগ্রাফি এবং কালার স্কিম রয়েছে। আপনি এই প্যাকেজটিতে ম্যাটেরিয়াল থিমিং যোগ করবেন। -
com.example.reply.ui.components– এতে অ্যাপের কাস্টম কম্পোনেন্টগুলো থাকে, যেমন লিস্ট আইটেম, অ্যাপ বার ইত্যাদি। আপনি এই কম্পোনেন্টগুলোতে থিম প্রয়োগ করবেন। -
ReplyApp.kt– এটি আমাদের প্রধান কম্পোজেবল ফাংশন, যেখান থেকে UI ট্রি শুরু হবে। আপনি এই ফাইলে টপ লেভেল থিমিং প্রয়োগ করবেন।
এই কোডল্যাবটি ui প্যাকেজ ফাইলগুলোর উপর আলোকপাত করবে।
৩. উপাদান ৩ থিমিং
জেটপ্যাক কম্পোজ ম্যাটেরিয়াল ডিজাইনের একটি বাস্তবায়ন প্রদান করে—যা ডিজিটাল ইন্টারফেস তৈরির জন্য একটি ব্যাপক ডিজাইন সিস্টেম। ম্যাটেরিয়াল ডিজাইনের উপাদানগুলো (বাটন, কার্ড, সুইচ ইত্যাদি) ম্যাটেরিয়াল থিমিং- এর উপর ভিত্তি করে নির্মিত, যা আপনার পণ্যের ব্র্যান্ডকে আরও ভালোভাবে প্রতিফলিত করার জন্য ম্যাটেরিয়াল ডিজাইনকে কাস্টমাইজ করার একটি পদ্ধতিগত উপায়।
আপনার অ্যাপে থিমিং যোগ করার জন্য ম্যাটেরিয়াল ৩ থিমে নিম্নলিখিত সাবসিস্টেমগুলো রয়েছে: কালার স্কিম , টাইপোগ্রাফি এবং শেপস । আপনি যখন এই ভ্যালুগুলো কাস্টমাইজ করেন, তখন আপনার অ্যাপ তৈরির জন্য ব্যবহৃত M3 কম্পোনেন্টগুলোতে পরিবর্তনগুলো স্বয়ংক্রিয়ভাবে প্রতিফলিত হয়। চলুন প্রতিটি সাবসিস্টেম বিস্তারিতভাবে আলোচনা করা যাক এবং স্যাম্পল অ্যাপে তা প্রয়োগ করা যাক।

উপাদান ৩ হলো রঙ, টাইপোগ্রাফি এবং আকারের উপ-ব্যবস্থা।
৪. রঙের পরিকল্পনা
একটি কালার স্কিমের ভিত্তি হলো পাঁচটি মূল রঙের একটি সেট, যার প্রতিটি ১৩টি টোনের একটি টোনাল প্যালেটের সাথে সম্পর্কিত এবং যা ম্যাটেরিয়াল ৩-এর উপাদানগুলিতে ব্যবহৃত হয়।

এম৩ থিমিং তৈরির জন্য পাঁচটি মূল বেসলাইন রঙ।
এরপর প্রতিটি অ্যাকসেন্ট কালার (প্রাথমিক, দ্বিতীয় এবং তৃতীয়) জোড়া মেলানো, জোর দেওয়া এবং দৃশ্যগত অভিব্যক্তির জন্য বিভিন্ন টোনের চারটি সামঞ্জস্যপূর্ণ রঙে সরবরাহ করা হয়।

প্রাথমিক, মাধ্যমিক এবং তৃতীয় পর্যায়ের বেসলাইন অ্যাকসেন্ট রঙের চারটি টোন।
একইভাবে, নিরপেক্ষ রঙগুলোকেও পৃষ্ঠতল এবং পটভূমির জন্য ব্যবহৃত চারটি সামঞ্জস্যপূর্ণ টোনে ভাগ করা হয়। যেকোনো পৃষ্ঠতলে স্থাপন করার সময় টেক্সট আইকনগুলোকে ফুটিয়ে তোলার জন্য এগুলোও গুরুত্বপূর্ণ।

ভিত্তিগত নিরপেক্ষ রঙগুলোর চারটি টোনাল রঙ।
রঙের বিন্যাস এবং রঙের ভূমিকা সম্পর্কে আরও পড়ুন।
রঙের স্কিম তৈরি করা
যদিও আপনি ম্যানুয়ালি একটি কাস্টম ColorScheme তৈরি করতে পারেন, তবে আপনার ব্র্যান্ডের সোর্স কালার ব্যবহার করে এটি তৈরি করা প্রায়শই সহজ হয়। ম্যাটেরিয়াল থিম বিল্ডার টুল আপনাকে এই কাজটি করতে দেয় এবং ঐচ্ছিকভাবে কম্পোজ থিমিং কোড এক্সপোর্ট করার সুযোগও দেয়।
আপনি আপনার পছন্দমতো যেকোনো রং বেছে নিতে পারেন, কিন্তু আমাদের ব্যবহারের ক্ষেত্রে আপনি ডিফল্ট রিপ্লাই প্রাইমারি কালার #825500 ব্যবহার করবেন। বাম দিকের কোর কালারস সেকশনে প্রাইমারি কালার-এ ক্লিক করুন এবং কালার পিকার-এ কোডটি যোগ করুন।

ম্যাটেরিয়াল থিম বিল্ডারে প্রাইমারি কালার কোড যোগ করা।
ম্যাটেরিয়াল থিম বিল্ডারে প্রাইমারি কালার যোগ করার পর, আপনি নিচের থিমটি এবং উপরের ডান কোণায় এক্সপোর্ট করার অপশনটি দেখতে পাবেন। এই কোডল্যাবের জন্য, আপনি জেটপ্যাক কম্পোজে থিমটি এক্সপোর্ট করবেন।

ম্যাটেরিয়াল থিম বিল্ডার, যার উপরের ডান কোণায় এক্সপোর্ট করার অপশন রয়েছে।
প্রাথমিক রঙ #825500 নিম্নলিখিত থিমটি তৈরি করে যা আপনি অ্যাপে যোগ করবেন। ম্যাটেরিয়াল ৩ একটি কম্পোনেন্টের অবস্থা, প্রাধান্য এবং গুরুত্ব নমনীয়ভাবে প্রকাশ করার জন্য বিভিন্ন ধরণের কালার রোল প্রদান করে।

প্রাথমিক রঙ থেকে হালকা ও গাঢ় রঙের স্কিম রপ্তানি করা হয়েছে।
তৈরি হওয়া The Color.kt ফাইলটিতে আপনার থিমের রঙগুলো রয়েছে এবং হালকা ও গাঢ় উভয় থিমের রঙের জন্য সমস্ত ভূমিকা সংজ্ঞায়িত করা আছে।
রঙ.কেটি
package com.example.reply.ui.theme
import androidx.compose.ui.graphics.Color
val md_theme_light_primary = Color(0xFF825500)
val md_theme_light_onPrimary = Color(0xFFFFFFFF)
val md_theme_light_primaryContainer = Color(0xFFFFDDB3)
val md_theme_light_onPrimaryContainer = Color(0xFF291800)
val md_theme_light_secondary = Color(0xFF6F5B40)
val md_theme_light_onSecondary = Color(0xFFFFFFFF)
val md_theme_light_secondaryContainer = Color(0xFFFBDEBC)
val md_theme_light_onSecondaryContainer = Color(0xFF271904)
val md_theme_light_tertiary = Color(0xFF51643F)
val md_theme_light_onTertiary = Color(0xFFFFFFFF)
val md_theme_light_tertiaryContainer = Color(0xFFD4EABB)
val md_theme_light_onTertiaryContainer = Color(0xFF102004)
val md_theme_light_error = Color(0xFFBA1A1A)
val md_theme_light_errorContainer = Color(0xFFFFDAD6)
val md_theme_light_onError = Color(0xFFFFFFFF)
val md_theme_light_onErrorContainer = Color(0xFF410002)
val md_theme_light_background = Color(0xFFFFFBFF)
val md_theme_light_onBackground = Color(0xFF1F1B16)
val md_theme_light_surface = Color(0xFFFFFBFF)
val md_theme_light_onSurface = Color(0xFF1F1B16)
val md_theme_light_surfaceVariant = Color(0xFFF0E0CF)
val md_theme_light_onSurfaceVariant = Color(0xFF4F4539)
val md_theme_light_outline = Color(0xFF817567)
val md_theme_light_inverseOnSurface = Color(0xFFF9EFE7)
val md_theme_light_inverseSurface = Color(0xFF34302A)
val md_theme_light_inversePrimary = Color(0xFFFFB951)
val md_theme_light_shadow = Color(0xFF000000)
val md_theme_light_surfaceTint = Color(0xFF825500)
val md_theme_light_outlineVariant = Color(0xFFD3C4B4)
val md_theme_light_scrim = Color(0xFF000000)
val md_theme_dark_primary = Color(0xFFFFB951)
val md_theme_dark_onPrimary = Color(0xFF452B00)
val md_theme_dark_primaryContainer = Color(0xFF633F00)
val md_theme_dark_onPrimaryContainer = Color(0xFFFFDDB3)
val md_theme_dark_secondary = Color(0xFFDDC2A1)
val md_theme_dark_onSecondary = Color(0xFF3E2D16)
val md_theme_dark_secondaryContainer = Color(0xFF56442A)
val md_theme_dark_onSecondaryContainer = Color(0xFFFBDEBC)
val md_theme_dark_tertiary = Color(0xFFB8CEA1)
val md_theme_dark_onTertiary = Color(0xFF243515)
val md_theme_dark_tertiaryContainer = Color(0xFF3A4C2A)
val md_theme_dark_onTertiaryContainer = Color(0xFFD4EABB)
val md_theme_dark_error = Color(0xFFFFB4AB)
val md_theme_dark_errorContainer = Color(0xFF93000A)
val md_theme_dark_onError = Color(0xFF690005)
val md_theme_dark_onErrorContainer = Color(0xFFFFDAD6)
val md_theme_dark_background = Color(0xFF1F1B16)
val md_theme_dark_onBackground = Color(0xFFEAE1D9)
val md_theme_dark_surface = Color(0xFF1F1B16)
val md_theme_dark_onSurface = Color(0xFFEAE1D9)
val md_theme_dark_surfaceVariant = Color(0xFF4F4539)
val md_theme_dark_onSurfaceVariant = Color(0xFFD3C4B4)
val md_theme_dark_outline = Color(0xFF9C8F80)
val md_theme_dark_inverseOnSurface = Color(0xFF1F1B16)
val md_theme_dark_inverseSurface = Color(0xFFEAE1D9)
val md_theme_dark_inversePrimary = Color(0xFF825500)
val md_theme_dark_shadow = Color(0xFF000000)
val md_theme_dark_surfaceTint = Color(0xFFFFB951)
val md_theme_dark_outlineVariant = Color(0xFF4F4539)
val md_theme_dark_scrim = Color(0xFF000000)
val seed = Color(0xFF825500)
তৈরি হওয়া The Theme.kt ফাইলটিতে হালকা ও গাঢ় রঙের স্কিম এবং অ্যাপ থিমের সেটআপ থাকে। এছাড়াও এতে প্রধান থিমিং কম্পোজেবল ফাংশন, AppTheme() , থাকে।
থিম.কেটি
package com.example.reply.ui.theme
import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.lightColorScheme
import androidx.compose.material3.darkColorScheme
import androidx.compose.runtime.Composable
private val LightColors = lightColorScheme(
primary = md_theme_light_primary,
onPrimary = md_theme_light_onPrimary,
primaryContainer = md_theme_light_primaryContainer,
onPrimaryContainer = md_theme_light_onPrimaryContainer,
secondary = md_theme_light_secondary,
onSecondary = md_theme_light_onSecondary,
secondaryContainer = md_theme_light_secondaryContainer,
onSecondaryContainer = md_theme_light_onSecondaryContainer,
tertiary = md_theme_light_tertiary,
onTertiary = md_theme_light_onTertiary,
tertiaryContainer = md_theme_light_tertiaryContainer,
onTertiaryContainer = md_theme_light_onTertiaryContainer,
error = md_theme_light_error,
errorContainer = md_theme_light_errorContainer,
onError = md_theme_light_onError,
onErrorContainer = md_theme_light_onErrorContainer,
background = md_theme_light_background,
onBackground = md_theme_light_onBackground,
surface = md_theme_light_surface,
onSurface = md_theme_light_onSurface,
surfaceVariant = md_theme_light_surfaceVariant,
onSurfaceVariant = md_theme_light_onSurfaceVariant,
outline = md_theme_light_outline,
inverseOnSurface = md_theme_light_inverseOnSurface,
inverseSurface = md_theme_light_inverseSurface,
inversePrimary = md_theme_light_inversePrimary,
surfaceTint = md_theme_light_surfaceTint,
outlineVariant = md_theme_light_outlineVariant,
scrim = md_theme_light_scrim,
)
private val DarkColors = darkColorScheme(
primary = md_theme_dark_primary,
onPrimary = md_theme_dark_onPrimary,
primaryContainer = md_theme_dark_primaryContainer,
onPrimaryContainer = md_theme_dark_onPrimaryContainer,
secondary = md_theme_dark_secondary,
onSecondary = md_theme_dark_onSecondary,
secondaryContainer = md_theme_dark_secondaryContainer,
onSecondaryContainer = md_theme_dark_onSecondaryContainer,
tertiary = md_theme_dark_tertiary,
onTertiary = md_theme_dark_onTertiary,
tertiaryContainer = md_theme_dark_tertiaryContainer,
onTertiaryContainer = md_theme_dark_onTertiaryContainer,
error = md_theme_dark_error,
errorContainer = md_theme_dark_errorContainer,
onError = md_theme_dark_onError,
onErrorContainer = md_theme_dark_onErrorContainer,
background = md_theme_dark_background,
onBackground = md_theme_dark_onBackground,
surface = md_theme_dark_surface,
onSurface = md_theme_dark_onSurface,
surfaceVariant = md_theme_dark_surfaceVariant,
onSurfaceVariant = md_theme_dark_onSurfaceVariant,
outline = md_theme_dark_outline,
inverseOnSurface = md_theme_dark_inverseOnSurface,
inverseSurface = md_theme_dark_inverseSurface,
inversePrimary = md_theme_dark_inversePrimary,
surfaceTint = md_theme_dark_surfaceTint,
outlineVariant = md_theme_dark_outlineVariant,
scrim = md_theme_dark_scrim,
)
@Composable
fun AppTheme(
useDarkTheme: Boolean = isSystemInDarkTheme(),
content: @Composable() () -> Unit
) {
val colors = if (!useDarkTheme) {
LightColors
} else {
DarkColors
}
MaterialTheme(
colorScheme = colors,
content = content
)
}
Jetpack Compose-এ থিমিং বাস্তবায়নের মূল উপাদান হলো MaterialTheme কম্পোজেবল।
আপনি MaterialTheme() কম্পোজেবলটিকে AppTheme() ফাংশনের মধ্যে র্যাপ করেন, যা দুটি প্যারামিটার গ্রহণ করে:
-
useDarkTheme- এই প্যারামিটারটিisSystemInDarkTheme()ফাংশনের সাথে যুক্ত, যা সিস্টেমের থিমিং সেটিংস পর্যবেক্ষণ করে লাইট বা ডার্ক থিম প্রয়োগ করে। আপনি যদি আপনার অ্যাপটিকে ম্যানুয়ালি লাইট বা ডার্ক থিমে রাখতে চান, তাহলেuseDarkThemeএ একটি বুলিয়ান ভ্যালু পাস করতে পারেন। -
content- যে কন্টেন্টের উপর থিমটি প্রয়োগ করা হবে।
থিম.কেটি
@Composable
fun AppTheme(
useDarkTheme: Boolean = isSystemInDarkTheme(),
content: @Composable() () -> Unit
) {
val colors = if (!useDarkTheme) {
LightColors
} else {
DarkColors
}
MaterialTheme(
colorScheme = colors,
content = content
)
}
আপনি এখন অ্যাপটি চালানোর চেষ্টা করলে দেখবেন যে এটি আগের মতোই দেখাচ্ছে। যদিও আপনি নতুন থিমিং কালারসহ আমাদের নতুন কালার স্কিমটি ইম্পোর্ট করেছেন, তবুও আপনি বেসলাইন থিমিং দেখতে পাচ্ছেন, কারণ আপনি কম্পোজ অ্যাপে থিমটি প্রয়োগ করেননি।

কোনো থিম প্রয়োগ করা না হলে অ্যাপটিতে বেসলাইন থিমিং দেখা যায়।
নতুন থিমটি প্রয়োগ করতে, MainActivity.kt এর মধ্যে থাকা প্রধান কম্পোজেবল ReplyApp টিকে মূল থিমিং ফাংশন AppTheme() দিয়ে র্যাপ করুন।
MainActivity.kt
setContent {
val uiState by viewModel.uiState.collectAsStateWithLifecycle()
AppTheme {
ReplyApp(/*..*/)
}
}
অ্যাপ প্রিভিউতে থিমটি প্রয়োগ হতে দেখার জন্য আপনাকে প্রিভিউ ফাংশনগুলোও আপডেট করতে হবে। প্রিভিউগুলোতে থিমিং প্রয়োগ করতে ReplyApp কম্পোজেবলটিকে ReplyAppPreview() এর ভিতরে AppTheme দিয়ে র্যাপ করুন।
প্রিভিউ প্যারামিটারে আপনি লাইট এবং ডার্ক উভয় সিস্টেম থিমই নির্ধারণ করে রেখেছেন, তাই আপনি উভয় প্রিভিউই দেখতে পাবেন।
MainActivity.kt
@Preview(
uiMode = Configuration.UI_MODE_NIGHT_YES,
name = "DefaultPreviewDark"
)
@Preview(
uiMode = Configuration.UI_MODE_NIGHT_NO,
name = "DefaultPreviewLight"
)
@Composable
fun ReplyAppPreview() {
AppTheme {
ReplyApp(
replyHomeUIState = ReplyHomeUIState(
emails = LocalEmailsDataProvider.allEmails
)
)
}
}
আপনি এখন অ্যাপটি চালালে, বেসলাইন থিমের পরিবর্তে ইম্পোর্ট করা থিমের রঙসহ অ্যাপ প্রিভিউ দেখতে পাবেন।


বেসলাইন থিম সহ অ্যাপ (বাম)।
আমদানিকৃত কালার থিম সহ অ্যাপ (ডানদিকে)।

আমদানিকৃত কালার থিম সহ হালকা এবং গাঢ় অ্যাপ প্রিভিউ।
ম্যাটেরিয়াল ৩ হালকা এবং গাঢ় উভয় রঙের স্কিমই সমর্থন করে। আপনি শুধুমাত্র ইম্পোর্ট করা থিম দিয়ে অ্যাপটিকে র্যাপ করেছেন; ম্যাটেরিয়াল ৩ কম্পোনেন্টগুলো ডিফল্ট কালার রোল ব্যবহার করছে।
অ্যাপে রঙ যোগ করা শুরু করার আগে, চলুন রঙের ভূমিকা ও ব্যবহার সম্পর্কে জেনে নিই।
রঙের ভূমিকা এবং প্রবেশগম্যতা
উপাদানটির অবস্থা, গুরুত্ব এবং তাৎপর্যের ওপর নির্ভর করে প্রতিটি রঙের ভূমিকা বিভিন্ন স্থানে ব্যবহার করা যেতে পারে।

প্রাথমিক, মাধ্যমিক ও তৃতীয় পর্যায়ের রঙের ভূমিকা।
প্রাইমারি হলো ভিত্তি রঙ, যা প্রধান উপাদান যেমন সুস্পষ্ট বাটন এবং সক্রিয় অবস্থাগুলোর জন্য ব্যবহৃত হয়।
UI-এর কম গুরুত্বপূর্ণ উপাদান, যেমন ফিল্টার চিপ, বোঝাতে সেকেন্ডারি কী কালার ব্যবহার করা হয়।
বৈসাদৃশ্যপূর্ণ বৈশিষ্ট্য ফুটিয়ে তোলার জন্য টারশিয়ারি কী কালার এবং অ্যাপের ব্যাকগ্রাউন্ড ও সারফেসের জন্য নিউট্রাল কালার ব্যবহার করা হয়।
উপাদানটির কালার সিস্টেম স্ট্যান্ডার্ড টোন ভ্যালু এবং পরিমাপ প্রদান করে যা ব্যবহারোপযোগী কনট্রাস্ট রেশিও পূরণের জন্য ব্যবহার করা যেতে পারে। ব্যবহারকারীর জন্য ব্যবহারোপযোগী কনট্রাস্ট নিশ্চিত করতে প্রাইমারি রঙের উপরে প্রাইমারি রঙ, প্রাইমারি কন্টেইনারের উপরে প্রাইমারি কন্টেইনার এবং অন্যান্য অ্যাকসেন্ট ও নিউট্রাল রঙের ক্ষেত্রেও একই পদ্ধতি অনুসরণ করুন।
আরও তথ্যের জন্য, রঙের ভূমিকা এবং প্রবেশগম্যতা দেখুন।
টোনাল এবং ছায়া উচ্চতা
উপাদান ৩ মূলত টোনাল রঙের প্রলেপ ব্যবহার করে উচ্চতা উপস্থাপন করে। পাত্র এবং পৃষ্ঠতলকে একে অপরের থেকে আলাদা করার এটি একটি নতুন উপায় — ছায়ার পাশাপাশি, টোনাল উচ্চতা বাড়ানোর জন্য আরও সুস্পষ্ট টোন ব্যবহার করা হয়।
লেভেল ২-এ টোনের উচ্চতা বৃদ্ধি, যা প্রাথমিক রঙের স্থান থেকে রঙ গ্রহণ করে।
ম্যাটেরিয়াল ডিজাইন ৩-এ ডার্ক থিমের এলিভেশন ওভারলেগুলোও টোনাল কালার ওভারলেতে পরিবর্তিত হয়েছে। ওভারলের রঙটি প্রাইমারি কালার স্লট থেকে আসে।
এম৩ সারফেস — যা বেশিরভাগ এম৩ কম্পোনেন্টের নেপথ্যে সুরসৃষ্টিযোগ্য আবহ সঙ্গীত — টোনাল এবং শ্যাডো এলিভেশন উভয়ের জন্যই সমর্থন অন্তর্ভুক্ত করে:
Surface(
modifier = modifier,
tonalElevation = {..}
shadowElevation = {..}
) {
Column(content = content)
}
অ্যাপে রং যোগ করা
আপনি অ্যাপটি চালালে দেখতে পাবেন যে, কম্পোনেন্টগুলো ডিফল্ট রঙ ব্যবহার করার পাশাপাশি অ্যাপটিতে এক্সপোর্ট করা রঙগুলোও দেখা যাচ্ছে। এখন যেহেতু আমরা রঙের ভূমিকা এবং এর ব্যবহার সম্পর্কে জানি, চলুন সঠিক রঙের ভূমিকাগুলো ব্যবহার করে অ্যাপটিকে থিম করি।

কালার থিম এবং কম্পোনেন্টগুলো ডিফল্ট কালার রোল গ্রহণ করা একটি অ্যাপ।
পৃষ্ঠের রঙ
হোম স্ক্রিনে, অ্যাপের কন্টেন্ট রাখার জন্য ভিত্তি হিসেবে মূল অ্যাপ কম্পোজেবলটিকে একটি Surface() দিয়ে র্যাপ করে শুরু করতে হবে। MainActivity.kt খুলুন এবং ReplyApp() কম্পোজেবলটিকে Surface দিয়ে র্যাপ করুন।
সারফেসটিকে প্রাইমারি স্লটের টোনাল কালার দেওয়ার জন্য আপনাকে 5.dp-এর একটি টোনাল এলিভেশনও প্রদান করতে হবে, যা লিস্ট আইটেম এবং এর উপরের সার্চ বারের সাথে কনট্রাস্ট তৈরি করতে সাহায্য করে। ডিফল্টভাবে, সারফেসটির টোনাল এবং শ্যাডো এলিভেশন 0.dp থাকে।
MainActivity.kt
AppTheme {
Surface(tonalElevation = 5.dp) {
ReplyApp(
replyHomeUIState = uiState,
// other parameters
)
}
}
আপনি যদি এখন আপনার অ্যাপ্লিকেশনটি চালান এবং তালিকা ও বিস্তারিত উভয় পৃষ্ঠা দেখেন, তাহলে দেখবেন যে টোনাল সারফেসটি পুরো অ্যাপটিতে প্রয়োগ করা হয়েছে।


পৃষ্ঠতল এবং টোনাল রঙ ছাড়া অ্যাপের ব্যাকগ্রাউন্ড (বাম)।
অ্যাপের ব্যাকগ্রাউন্ডে পৃষ্ঠতল এবং টোনাল রঙ প্রয়োগ করা হয়েছে (ডানদিকে)।
অ্যাপ বারের রঙ
ডিজাইনের অনুরোধ অনুযায়ী, উপরে থাকা আমাদের কাস্টম সার্চ বারের কোনো স্বচ্ছ ব্যাকগ্রাউন্ড নেই। ডিফল্টরূপে, এটি ডিফল্ট বেস সারফেসে ফিরে আসে। একটি সুস্পষ্ট বিভাজন দেওয়ার জন্য আপনি একটি ব্যাকগ্রাউন্ড প্রদান করতে পারেন।

পটভূমিবিহীন কাস্টম সার্চ বার (বাম)।
ব্যাকগ্রাউন্ড সহ কাস্টম সার্চ বার (ডানদিকে)।
এখন আপনি ui/components/ReplyAppBars.kt ফাইলটি সম্পাদনা করবেন, যেটিতে অ্যাপ বারটি রয়েছে। আপনি Row Composable-এর Modifier এ MaterialTheme.colorScheme.background যোগ করবেন।
ReplyAppBars.kt
@Composable
fun ReplySearchBar(modifier: Modifier = Modifier) {
Row(
modifier = modifier
.fillMaxWidth()
.padding(16.dp)
.background(MaterialTheme.colorScheme.background),
verticalAlignment = Alignment.CenterVertically
) {
// Search bar content
}
}
এখন আপনি টোনাল সারফেস এবং ব্যাকগ্রাউন্ড কালারসহ অ্যাপ বারের মধ্যে একটি স্পষ্ট বিভাজন দেখতে পাবেন।

টোনাল সারফেসের উপরে ব্যাকগ্রাউন্ড রঙ সহ সার্চ বার।
ভাসমান অ্যাকশন বোতামের রঙ

কোনো থিমিং প্রয়োগ ছাড়া বড় FAB (বাম)।
তৃতীয় রঙের থিমযুক্ত বড় ফ্যাব্রিক (ডানদিকে)।
হোম স্ক্রিনে, আপনি ফ্লোটিং অ্যাকশন বাটন (FAB)-এর চেহারা উন্নত করতে পারেন, যাতে এটি একটি কল টু অ্যাকশন বাটন হিসেবে আলাদাভাবে চোখে পড়ে। এটি করার জন্য, আপনাকে এতে একটি টারশিয়ারি অ্যাকসেন্ট কালার প্রয়োগ করতে হবে।
ReplyListContent.kt ফাইলে, অ্যাক্সেসিবিলিটি এবং কালার কনট্রাস্ট বজায় রাখতে FAB-এর containerColor tertiaryContainer color-এ এবং content color-কে onTertiaryContainer এ আপডেট করুন।
ReplyListContent.kt
ReplyInboxScreen(/*..*/) {
// Email list content
LargeFloatingActionButton(
containerColor = MaterialTheme.colorScheme.tertiaryContainer,
contentColor = MaterialTheme.colorScheme.onTertiaryContainer
){
/*..*/
}
}
আপনার FAB থিমটি দেখতে অ্যাপটি চালান। এই কোডল্যাবের জন্য, আপনি একটি LargeFloatingActionButton ব্যবহার করছেন।
কার্ডের রং
হোম স্ক্রিনের ইমেল লিস্টে একটি কার্ড কম্পোনেন্ট ব্যবহার করা হয়। ডিফল্টভাবে, এটি একটি Filled কার্ড যা কন্টেইনার কালার হিসেবে সারফেস ভ্যারিয়েন্ট কালার ব্যবহার করে, যাতে সারফেস এবং কার্ড কালারের মধ্যে একটি স্পষ্ট বিভাজন তৈরি হয়। Compose এছাড়াও ElevatedCard এবং OutlinedCard এর ইমপ্লিমেন্টেশন প্রদান করে।
আপনি দ্বিতীয় রঙের টোন ব্যবহার করে কিছু গুরুত্বপূর্ণ আইটেমকে আরও হাইলাইট করতে পারেন। গুরুত্বপূর্ণ ইমেলগুলির জন্য, আপনাকে CardDefaults.cardColors() ব্যবহার করে কার্ড কন্টেইনারের রঙ আপডেট করার মাধ্যমে ui/components/ReplyEmailListItem.kt ফাইলটি পরিবর্তন করতে হবে:
ReplyEmailListItem.kt
Card(
modifier = modifier
.padding(horizontal = 16.dp, vertical = 4.dp)
.semantics { selected = isSelected }
.clickable { navigateToDetail(email.id) },
colors = CardDefaults.cardColors(
containerColor = if (email.isImportant)
MaterialTheme.colorScheme.secondaryContainer
else MaterialTheme.colorScheme.surfaceVariant
)
){
/*..*/
}


টোনাল সারফেসে সেকেন্ডারি কন্টেইনার কালার ব্যবহার করে তালিকার আইটেমটি হাইলাইট করুন।
বিস্তারিত তালিকার আইটেমের রঙ
এখন, আপনি আপনার হোম স্ক্রিনটি থিম করেছেন। ইমেল তালিকার যেকোনো আইটেমে ক্লিক করে বিস্তারিত পৃষ্ঠাটি দেখুন।


থিমযুক্ত তালিকা আইটেম ছাড়া ডিফল্ট বিস্তারিত পৃষ্ঠা (বাম)।
ব্যাকগ্রাউন্ড থিমিং প্রয়োগ করা বিস্তারিত তালিকার আইটেম (ডানদিকে)।
আপনার তালিকার আইটেমটিতে কোনো রঙ প্রয়োগ করা নেই, তাই এটি ডিফল্ট টোনাল সারফেস কালার ব্যবহার করছে। আপনি তালিকার আইটেমটিতে একটি বিভাজন তৈরি করতে ব্যাকগ্রাউন্ড কালার প্রয়োগ করবেন এবং আমাদের ব্যাকগ্রাউন্ডের চারপাশে ফাঁকা জায়গা দেওয়ার জন্য প্যাডিং যোগ করবেন।
ReplyEmailThreadItem.kt
@Composable
fun ReplyEmailThreadItem(
email: Email,
modifier: Modifier = Modifier
) {
Column(
modifier = modifier
.fillMaxWidth()
.padding(16.dp)
.background(MaterialTheme.colorScheme.background)
.padding(20.dp)
) {
// List item content
}
}
আপনি দেখতে পাচ্ছেন যে, শুধু প্রেক্ষাপট প্রদানের মাধ্যমেই স্বরতল এবং তালিকার আইটেমটির মধ্যে একটি স্পষ্ট বিভাজন তৈরি করা হয়েছে।
আপনার হোম এবং ডিটেইল পেজ দুটিতেই এখন রঙের সঠিক ভূমিকা ও ব্যবহার রয়েছে। চলুন দেখি, আপনার অ্যাপ কীভাবে ডাইনামিক কালার ব্যবহার করে আরও বেশি পার্সোনালাইজড এবং সুসংহত অভিজ্ঞতা প্রদান করতে পারে।
৫. অ্যাপে ডাইনামিক রং যোগ করা
ডাইনামিক কালার হলো ম্যাটেরিয়াল ৩-এর মূল অংশ, যেখানে একটি অ্যালগরিদম ব্যবহারকারীর ওয়ালপেপার থেকে নিজস্ব রঙ তৈরি করে তা তাদের অ্যাপ এবং সিস্টেম ইউআই-তে প্রয়োগ করে।
ডাইনামিক থিমিং আপনার অ্যাপগুলোকে আরও ব্যক্তিগতকৃত করে তোলে। এটি ব্যবহারকারীদের সিস্টেম থিমের সাথে একটি সুসংহত এবং নির্বিঘ্ন অভিজ্ঞতাও প্রদান করে।
অ্যান্ড্রয়েড ১২ এবং তার পরবর্তী সংস্করণগুলোতে ডাইনামিক কালার পাওয়া যায়। যদি ডাইনামিক কালার সুবিধাটি থাকে, তবে আপনি dynamicDarkColorScheme() অথবা dynamicLightColorScheme() ব্যবহার করে একটি ডাইনামিক কালার স্কিম সেট করতে পারেন। অন্যথায়, আপনাকে ডিফল্ট লাইট বা ডার্ক ColorScheme ব্যবহার করতে হবে।
Theme.kt ফাইলের AppTheme ফাংশনের কোডটি নিচের কোড দিয়ে প্রতিস্থাপন করুন:
থিম.কেটি
@Composable
fun AppTheme(
useDarkTheme: Boolean = isSystemInDarkTheme(),
content: @Composable () -> Unit
) {
val context = LocalContext.current
val colors = when {
(Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) -> {
if (useDarkTheme) dynamicDarkColorScheme(context)
else dynamicLightColorScheme(context)
}
useDarkTheme -> DarkColors
else -> LightColors
}
MaterialTheme(
colorScheme = colors,
content = content
)
}

অ্যান্ড্রয়েড ১৩ ওয়ালপেপার থেকে নেওয়া ডাইনামিক থিম।
এখন অ্যাপটি চালালে, আপনি ডিফল্ট অ্যান্ড্রয়েড ১৩ ওয়ালপেপার ব্যবহার করে ডাইনামিক থিমিং প্রয়োগ হতে দেখবেন।
আপনার অ্যাপের থিমে ব্যবহৃত কালার স্কিমের ওপর নির্ভর করে স্ট্যাটাস বারটি গতিশীলভাবে স্টাইল হোক, এমনটাও আপনি চাইতে পারেন।

স্ট্যাটাস বারে রঙ প্রয়োগ করা হয়নি এমন অ্যাপ (বাম)।
স্ট্যাটাস বারের রঙ প্রয়োগ করা অ্যাপ (ডানদিকে)।
আপনার থিমের প্রধান রঙের উপর ভিত্তি করে স্ট্যাটাস বারের রঙ আপডেট করতে, AppTheme কম্পোজেবলে কালার স্কিম নির্বাচনের পরে স্ট্যাটাস বারের রঙটি যোগ করুন:
থিম.কেটি
@Composable
fun AppTheme(
useDarkTheme: Boolean = isSystemInDarkTheme(),
content: @Composable () -> Unit
) {
// color scheme selection code
// Add primary status bar color from chosen color scheme.
val view = LocalView.current
if (!view.isInEditMode) {
SideEffect {
val window = (view.context as Activity).window
window.statusBarColor = colors.primary.toArgb()
WindowCompat
.getInsetsController(window, view)
.isAppearanceLightStatusBars = useDarkTheme
}
}
MaterialTheme(
colorScheme = colors,
content = content
)
}
যখন আপনি অ্যাপটি চালাবেন, তখন দেখবেন স্ট্যাটাস বারটি আপনার প্রধান রঙের থিমিং গ্রহণ করেছে। এছাড়াও, আপনি সিস্টেমের ডার্ক থিম পরিবর্তন করে লাইট ও ডার্ক উভয় ডাইনামিক থিমিং চেষ্টা করে দেখতে পারেন।

অ্যান্ড্রয়েড ১৩-এর ডিফল্ট ওয়ালপেপারের সাথে ডাইনামিক লাইট (বামে) এবং ডার্ক (ডানে) থিম প্রয়োগ করা হয়েছে।
এখন পর্যন্ত, আপনি আপনার অ্যাপে এমন কিছু রঙ প্রয়োগ করেছেন যা অ্যাপটির চেহারাকে আরও আকর্ষণীয় করে তুলেছে। তবে, আপনি দেখতে পাচ্ছেন যে অ্যাপের সমস্ত লেখা একই আকারের, তাই আপনি এখন অ্যাপটিতে টাইপোগ্রাফি যোগ করতে পারেন।
৬. মুদ্রণশৈলী
ম্যাটেরিয়াল ডিজাইন ৩ একটি টাইপ স্কেল সংজ্ঞায়িত করে। এর নামকরণ ও গ্রুপিংকে সরল করে ডিসপ্লে, হেডলাইন, টাইটেল, বডি এবং লেবেল করা হয়েছে, এবং প্রতিটির জন্য বড়, মাঝারি ও ছোট আকার রয়েছে।

উপকরণ ৩ প্রকারের স্কেল।
টাইপোগ্রাফির সংজ্ঞা
ম্যাটেরিয়াল ৩ টাইপ স্কেল মডেল করার জন্য, কম্পোজ বিদ্যমান TextStyle এবং font-related ক্লাসগুলোর পাশাপাশি M3 Typography ক্লাসটিও প্রদান করে।
টাইপোগ্রাফি কনস্ট্রাক্টর প্রতিটি স্টাইলের জন্য ডিফল্ট মান প্রদান করে, ফলে আপনি যে প্যারামিটারগুলো কাস্টমাইজ করতে চান না, সেগুলো বাদ দিতে পারেন। আরও তথ্যের জন্য, টাইপোগ্রাফি স্টাইল এবং তাদের ডিফল্ট মানগুলো দেখুন।
আপনি আপনার অ্যাপে পাঁচটি টাইপোগ্রাফি স্টাইল ব্যবহার করবেন: headlineSmall , titleLarge , bodyLarge , bodyMedium এবং labelMedium । এই স্টাইলগুলো হোম স্ক্রিন এবং ডিটেইল স্ক্রিন উভয়ের জন্যই ব্যবহৃত হবে।

স্ক্রিনটিতে টাইটেল, লেবেল এবং বডি স্টাইলের টাইপোগ্রাফি ব্যবহার দেখানো হচ্ছে।
এরপর, ui/theme প্যাকেজে যান এবং Type.kt খুলুন। কিছু টেক্সট স্টাইলের জন্য ডিফল্ট মানের পরিবর্তে আপনার নিজস্ব ইমপ্লিমেন্টেশন দিতে নিম্নলিখিত কোডটি যোগ করুন:
টাইপ.কেটি
val typography = Typography(
headlineSmall = TextStyle(
fontWeight = FontWeight.SemiBold,
fontSize = 24.sp,
lineHeight = 32.sp,
letterSpacing = 0.sp
),
titleLarge = TextStyle(
fontWeight = FontWeight.Normal,
fontSize = 18.sp,
lineHeight = 28.sp,
letterSpacing = 0.sp
),
bodyLarge = TextStyle(
fontWeight = FontWeight.Normal,
fontSize = 16.sp,
lineHeight = 24.sp,
letterSpacing = 0.15.sp
),
bodyMedium = TextStyle(
fontWeight = FontWeight.Medium,
fontSize = 14.sp,
lineHeight = 20.sp,
letterSpacing = 0.25.sp
),
labelMedium = TextStyle(
fontWeight = FontWeight.SemiBold,
fontSize = 12.sp,
lineHeight = 16.sp,
letterSpacing = 0.5.sp
)
)
আপনার টাইপোগ্রাফি এখন সংজ্ঞায়িত করা হয়েছে। এটিকে আপনার থিমে যোগ করতে, AppTheme ভিতরে MaterialTheme() কম্পোজেবলে এটি পাস করুন:
থিম.কেটি
@Composable
fun AppTheme(
useDarkTheme: Boolean = isSystemInDarkTheme(),
content: @Composable() () -> Unit
) {
// dynamic theming content
MaterialTheme(
colorScheme = colors,
typography = typography,
content = content
)
}
টাইপোগ্রাফি নিয়ে কাজ করা
রঙের মতোই, আপনি MaterialTheme.typography ব্যবহার করে বর্তমান থিমের টাইপোগ্রাফি স্টাইল অ্যাক্সেস করতে পারবেন। এটি আপনাকে Type.k t-তে সংজ্ঞায়িত সমস্ত টাইপোগ্রাফি ব্যবহার করার জন্য টাইপোগ্রাফি ইনস্ট্যান্সটি প্রদান করে।
Text(
text = "Hello M3 theming",
style = MaterialTheme.typography.titleLarge
)
Text(
text = "you are learning typography",
style = MaterialTheme.typography.bodyMedium
)
আপনার পণ্যের জন্য সম্ভবত ম্যাটেরিয়াল ডিজাইন টাইপ স্কেল-এর ১৫টি ডিফল্ট স্টাইলের সবগুলোর প্রয়োজন হবে না। এই কোডল্যাবে পাঁচটি সাইজ বেছে নেওয়া হয়েছে এবং বাকিগুলো বাদ দেওয়া হয়েছে।
যেহেতু আপনি Text( ) কম্পোজেবলগুলিতে টাইপোগ্রাফি প্রয়োগ করেননি, তাই ডিফল্টরূপে সমস্ত টেক্সট Typography.bodyLarge এ ফিরে যায়।
হোম তালিকার টাইপোগ্রাফি
এরপরে, টাইটেল এবং লেবেলের মধ্যে পার্থক্য তৈরি করতে ui/components/ReplyEmailListItem.kt এ থাকা ReplyEmailListItem ফাংশনে টাইপোগ্রাফি প্রয়োগ করুন:
ReplyEmailListItem.kt
Text(
text = email.sender.firstName,
style = MaterialTheme.typography.labelMedium
)
Text(
text = email.createdAt,
style = MaterialTheme.typography.labelMedium
)
Text(
text = email.subject,
style = MaterialTheme.typography.titleLarge,
modifier = Modifier.padding(top = 12.dp, bottom = 8.dp),
)
Text(
text = email.body,
maxLines = 2,
style = MaterialTheme.typography.bodyLarge,
overflow = TextOverflow.Ellipsis
)


টাইপোগ্রাফি প্রয়োগ ছাড়া হোম স্ক্রিন (বাম)।
টাইপোগ্রাফি প্রয়োগ করা হোম স্ক্রিন (ডানদিকে)।
বিস্তারিত তালিকার টাইপোগ্রাফি
একইভাবে, আপনি u i/components/ReplyEmailThreadItem.kt এ থাকা ReplyEmailThreadItem এর সমস্ত টেক্সট কম্পোজেবল আপডেট করার মাধ্যমে ডিটেইল স্ক্রিনে টাইপোগ্রাফি যোগ করবেন:
ReplyEmailThreadItem.kt
Text(
text = email.sender.firstName,
style = MaterialTheme.typography.labelMedium
)
Text(
text = stringResource(id = R.string.twenty_mins_ago),
style = MaterialTheme.typography.labelMedium
)
Text(
text = email.subject,
style = MaterialTheme.typography.bodyMedium,
modifier = Modifier.padding(top = 12.dp, bottom = 8.dp),
)
Text(
text = email.body,
style = MaterialTheme.typography.bodyLarge,
color = MaterialTheme.colorScheme.onSurfaceVariant
)


টাইপোগ্রাফি প্রয়োগ ছাড়া বিস্তারিত স্ক্রিন (বাম)।
টাইপোগ্রাফি প্রয়োগ করা বিস্তারিত স্ক্রিন (ডানদিকে)।
টাইপোগ্রাফি কাস্টমাইজ করা
Compose-এর সাহায্যে আপনার টেক্সট স্টাইল কাস্টমাইজ করা বা নিজস্ব ফন্ট ব্যবহার করা খুবই সহজ। আপনি ফন্ট টাইপ, ফন্ট ফ্যামিলি, লেটার স্পেসিং ইত্যাদি কাস্টমাইজ করতে TextStyle পরিবর্তন করতে পারেন।
আপনি theme/Type.kt ফাইলে টেক্সট স্টাইল পরিবর্তন করবেন, যা এটি ব্যবহারকারী সমস্ত কম্পোনেন্টে প্রতিফলিত হবে।
তালিকার আইটেমের বিষয়ের জন্য ব্যবহৃত titleLarge এর fontWeight SemiBold এবং lineHeight 32.sp তে আপডেট করুন। এটি বিষয়ের উপর আরও জোর দেবে এবং স্পষ্ট বিভাজন তৈরি করবে।
টাইপ.কেটি
...
titleLarge = TextStyle(
fontWeight = FontWeight.SemiBold,
fontSize = 18.sp,
lineHeight = 32.sp,
letterSpacing = 0.0.sp
),
...

বিষয় পাঠ্যে নিজস্ব টাইপোগ্রাফি প্রয়োগ করা।
৭. আকৃতি
বস্তুগত পৃষ্ঠতল বিভিন্ন আকৃতিতে প্রদর্শন করা যেতে পারে। আকৃতি মনোযোগ আকর্ষণ করে, উপাদান শনাক্ত করে, অবস্থা প্রকাশ করে এবং ব্র্যান্ডকে তুলে ধরে।
আকার নির্ধারণ
Compose নতুন M3 শেপ বাস্তবায়নের জন্য Shapes ক্লাসকে বর্ধিত প্যারামিটার প্রদান করে। M3 শেপ স্কেল, যা টাইপ স্কেলের অনুরূপ, UI জুড়ে বিভিন্ন ধরনের শেপের অভিব্যক্তি প্রকাশে সক্ষম করে।
আকৃতির স্কেলে বিভিন্ন মাপের আকৃতি রয়েছে:
- অতিরিক্ত ছোট
- ছোট
- মাঝারি
- বড়
- অতিরিক্ত বড়
ডিফল্টরূপে, প্রতিটি শেপের একটি ডিফল্ট মান থাকে যা পরিবর্তন করা যায়। আপনার অ্যাপের জন্য, আপনি তালিকার আইটেমটি পরিবর্তন করতে মিডিয়াম শেপ ব্যবহার করবেন, তবে আপনি অন্যান্য শেপও ঘোষণা করতে পারেন। ui/theme প্যাকেজে Shape.kt নামে একটি নতুন ফাইল তৈরি করুন এবং শেপের জন্য কোডটি যোগ করুন:
Shape.kt
package com.example.reply.ui.theme
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Shapes
import androidx.compose.ui.unit.dp
val shapes = Shapes(
extraSmall = RoundedCornerShape(4.dp),
small = RoundedCornerShape(8.dp),
medium = RoundedCornerShape(16.dp),
large = RoundedCornerShape(24.dp),
extraLarge = RoundedCornerShape(32.dp)
)
এখন যেহেতু আপনি আপনার shapes সংজ্ঞায়িত করেছেন, রঙ এবং টাইপোগ্রাফির মতোই এটি M3 MaterialTheme এ পাঠান:
থিম.কেটি
@Composable
fun AppTheme(
useDarkTheme: Boolean = isSystemInDarkTheme(),
content: @Composable() () -> Unit
) {
// dynamic theming content
MaterialTheme(
colorScheme = colors,
typography = typography,
shapes = shapes
content = content
)
}
আকৃতি নিয়ে কাজ করা
রঙ এবং টাইপোগ্রাফির মতোই, আপনি MaterialTheme.shape ব্যবহার করে Material কম্পোনেন্টগুলিতে আকার প্রয়োগ করতে পারেন, যা আপনাকে Material আকারগুলি অ্যাক্সেস করার জন্য Shape ইনস্ট্যান্সটি প্রদান করে।
অনেক ম্যাটেরিয়াল কম্পোনেন্টে আগে থেকেই ডিফল্ট আকার প্রয়োগ করা থাকে, কিন্তু উপলব্ধ স্লটগুলোর মাধ্যমে আপনি কম্পোনেন্টগুলোতে আপনার নিজস্ব আকার প্রদান ও প্রয়োগ করতে পারেন।
Card(shape = MaterialTheme.shapes.medium) { /* card content */ }
FloatingActionButton(shape = MaterialTheme.shapes.large) { /* fab content */}
বিভিন্ন ধরনের আকৃতি ব্যবহার করে উপাদানের অংশসমূহের মানচিত্রায়ন।
আপনি শেপ ডকুমেন্টেশনে সমস্ত কম্পোনেন্টের শেপগুলোর ম্যাপিং দেখতে পারেন।
ব্যবহারের জন্য আরও দুটি আকৃতি রয়েছে — RectangleShape এবং CircleShape — যেগুলো Compose-এর অংশ। Rectangle আকৃতির কোনো বর্ডার রেডিয়াস নেই, এবং Circle আকৃতির কিনারাগুলো সম্পূর্ণ বৃত্তাকার হয়।
আপনি Modifier.clip , Modifier.background , এবং Modifier.border মতো আকার গ্রহণকারী Modifiers ব্যবহার করেও আপনার কম্পোনেন্টগুলিতে আকার প্রয়োগ করতে পারেন।
অ্যাপ বারের আকৃতি
আমরা চাই অ্যাপ বারের ব্যাকগ্রাউন্ডের কোণাগুলো গোলাকার হোক:

TopAppBar টি ব্যাকগ্রাউন্ড কালারসহ একটি Row ব্যবহার করছে। গোলাকার কোণার ব্যাকগ্রাউন্ড পেতে, ব্যাকগ্রাউন্ড মডিফায়ারে CircleShape পাস করে ব্যাকগ্রাউন্ডের আকৃতি নির্ধারণ করুন:
ReplyAppBars.kt
@Composable
fun ReplySearchBar(modifier: Modifier = Modifier) {
Row(
modifier = modifier
.fillMaxWidth()
.padding(16.dp)
.background(
MaterialTheme.colorScheme.background,
CircleShape
),
verticalAlignment = Alignment.CenterVertically
) {
// Search bar content
}
}

বিস্তারিত তালিকার আইটেমের আকৃতি
হোম স্ক্রিনে আপনি একটি কার্ড ব্যবহার করছেন, যেটি ডিফল্টভাবে Shape.Medium ব্যবহার করছে। কিন্তু আমাদের ডিটেইল পেজের জন্য, আপনি এর পরিবর্তে ব্যাকগ্রাউন্ড কালারসহ একটি কলাম ব্যবহার করেছেন। একটি সামঞ্জস্যপূর্ণ তালিকার মতো চেহারা দেওয়ার জন্য, এতে একটি মিডিয়াম শেপ প্রয়োগ করুন।


তালিকার আইটেমের বিস্তারিত কলাম, যেখানে আইটেমটির কোনো আকৃতি নেই (বামদিকে) এবং তালিকার আইটেমটির মাঝারি আকৃতি রয়েছে (ডানদিকে)।
ReplyEmailThreadItem.kt
@Composable
fun ReplyEmailThreadItem(
email: Email,
modifier: Modifier = Modifier
) {
Column(
modifier = modifier
.fillMaxWidth()
.padding(8.dp)
.background(
MaterialTheme.colorScheme.background,
MaterialTheme.shapes.medium
)
.padding(16.dp)
) {
// List item content
}
}
এখন, আপনার অ্যাপটি চালালে medium আকারের একটি বিস্তারিত স্ক্রিন লিস্ট আইটেম দেখা যায়।
৮. গুরুত্বারোপ
UI-তে এমফাসিস আপনাকে কোনো একটি কন্টেন্টকে অন্যটির চেয়ে বেশি হাইলাইট করতে সাহায্য করে, যেমন যখন আপনি শিরোনামকে উপ-শিরোনাম থেকে আলাদা করতে চান। M3-তে এমফাসিস বিভিন্ন রঙের বৈচিত্র্য এবং এর নিজস্ব রঙের সংমিশ্রণ ব্যবহার করে। এমফাসিস যোগ করার দুটি উপায় আছে:
- সম্প্রসারিত M3 কালার সিস্টেম থেকে সারফেস, সারফেস-ভেরিয়েন্ট এবং ব্যাকগ্রাউন্ডের পাশাপাশি অন-সারফেস ও অন-সারফেস-ভেরিয়েন্টস কালার ব্যবহার করা।
উদাহরণস্বরূপ, জোর দেওয়ার বিভিন্ন মাত্রা প্রদানের জন্য 'surface'-কে 'on-surface-variant'-এর সাথে এবং 'surface-variant'-কে 'on-surface'-এর সাথে ব্যবহার করা যেতে পারে।
অন-অ্যাকসেন্ট কালারের তুলনায় কম গুরুত্ব দেওয়ার জন্য, কিন্তু তারপরও সহজগম্য থাকতে এবং কনট্রাস্ট রেশিও অনুসরণ করতে, সারফেস ভ্যারিয়েন্টগুলো অ্যাকসেন্ট কালারের সাথেও ব্যবহার করা যেতে পারে।

পৃষ্ঠতল, পটভূমি এবং পৃষ্ঠতলের বিভিন্ন রঙের ভূমিকা।
- টেক্সটের জন্য বিভিন্ন ফন্ট ওয়েট ব্যবহার করা। টাইপোগ্রাফি বিভাগে যেমন দেখেছেন, বিভিন্ন জোর দেওয়ার জন্য আপনি আপনার টাইপ স্কেলে কাস্টম ওয়েট যোগ করতে পারেন।
এরপরে, সারফেস ভ্যারিয়েন্ট ব্যবহার করে একটি সুস্পষ্ট পার্থক্য তৈরি করতে ReplyEmailListItem.kt আপডেট করুন। ডিফল্টরূপে, কার্ডের কন্টেন্টটি ব্যাকগ্রাউন্ডের উপর নির্ভর করে ডিফল্ট কন্টেন্ট কালার গ্রহণ করে।
আপনি টাইম টেক্সট এবং বডি টেক্সট কম্পোজেবলের রঙ onSurfaceVariant এ আপডেট করবেন। এটি onContainerColors এর তুলনায় এর গুরুত্ব কমিয়ে দেয়, যা ডিফল্টরূপে সাবজেক্ট এবং টাইটেল টেক্সট কম্পোজেবলে প্রয়োগ করা হয়।


বিষয় এবং শিরোনামের তুলনায় সময় এবং মূল লেখায় একই রকম গুরুত্ব দেওয়া হয়েছে (বাম দিকে)।
বিষয় এবং শিরোনামের তুলনায় সময় এবং মূল অংশের ওপর কম গুরুত্ব দেওয়া হয়েছে (ডানদিকে)।
ReplyEmailListItem.kt
Text(
text = email.createdAt,
style = MaterialTheme.typography.labelMedium,
color = MaterialTheme.colorScheme.onSurfaceVariant
)
Text(
text = email.body,
maxLines = 2,
style = MaterialTheme.typography.bodyLarge,
color = MaterialTheme.colorScheme.onSurfaceVariant
overflow = TextOverflow.Ellipsis
)
সেকেন্ডারি secondaryContainer ব্যাকগ্রাউন্ডযুক্ত গুরুত্বপূর্ণ ইমেল কার্ডের ক্ষেত্রে, ডিফল্টরূপে সমস্ত টেক্সটের রঙ onSecondaryContainer রঙ হয়। অন্যান্য ইমেলগুলির ব্যাকগ্রাউন্ড surfaceVariant, সমস্ত টেক্সট ডিফল্টরূপে onSurfaceVariant রঙ ধারণ করে।
৯. অভিনন্দন
অভিনন্দন! আপনি সফলভাবে এই কোডল্যাবটি সম্পন্ন করেছেন! আপনি আপনার অ্যাপ্লিকেশনটিকে থিম করতে এবং একটি ব্যক্তিগতকৃত অভিজ্ঞতা প্রদান করতে, কম্পোজ (Compose) ব্যবহার করে রঙ, টাইপোগ্রাফি, এবং আকারের পাশাপাশি ডাইনামিক রঙ প্রয়োগ করে ম্যাটেরিয়াল থিমিং বাস্তবায়ন করেছেন।



ডাইনামিক কালার এবং কালার থিম প্রয়োগের পর থিমিং-এর চূড়ান্ত ফলাফল।
এরপর কী?
Compose পাথওয়েতে আমাদের অন্যান্য কোডল্যাবগুলোও দেখে নিন:
আরও পড়ুন
- কম্পোজ থিমিং গাইড
- কম্পোজের জন্য উপাদান থিমিং
নমুনা অ্যাপ
- সম্পূর্ণ ম্যাটেরিয়াল ৩ থিমিং সহ রিপ্লাই স্যাম্পল অ্যাপ
- জেটচ্যাট ডাইনামিক থিমিং প্রদর্শন করছে