🎨 UI – Views और Layouts · Lesson 19
Material 3 Theme, Colors और Dark Mode
Theme vs style
Theme
- पूरी app या Activity पर लागू
- Colour roles, fonts, shapes define करती है
- android:theme="@style/Theme.StudentDiary"
Style
- एक view पर लागू
- Attributes group करती है (size, padding)
- style="@style/StatNumber"
Material 3 colour roles
| Role | कहाँ use |
|---|---|
| colorPrimary / colorOnPrimary | Main buttons, FAB, active tab · उन पर text |
| colorPrimaryContainer / colorOnPrimaryContainer | Tonal buttons, chips, highlighted cards |
| colorSecondary / colorTertiary | Accents |
| colorSurface / colorOnSurface | Screen और card background · normal text |
| colorError | Error text और icons |
App theme
XML – res/values/colors.xml (Student Diary)
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="brand">#16A34A</color>
<color name="brand_dark">#15803D</color>
<color name="brand_light">#DCFCE7</color>
<color name="accent">#F59E0B</color>
<color name="star">#F59E0B</color>
<color name="priority_high">#EF4444</color>
<color name="priority_medium">#F59E0B</color>
<color name="priority_low">#22C55E</color>
</resources>XML – res/values/themes.xml (Student Diary)
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- Material 3, light + dark (DayNight). We use our own Toolbar, so NoActionBar. -->
<style name="Theme.StudentDiary" parent="Theme.Material3.DayNight.NoActionBar">
<item name="colorPrimary">@color/brand</item>
<item name="colorOnPrimary">@android:color/white</item>
<item name="colorPrimaryContainer">@color/brand_light</item>
<item name="colorOnPrimaryContainer">@color/brand_dark</item>
<item name="colorSecondary">@color/accent</item>
<item name="colorOnSecondary">@android:color/black</item>
</style>
<style name="StatCard" parent="Widget.Material3.CardView.Filled">
<item name="cardCornerRadius">16dp</item>
</style>
<style name="StatBox">
<item name="android:layout_width">match_parent</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:orientation">vertical</item>
<item name="android:gravity">center</item>
<item name="android:padding">16dp</item>
</style>
<style name="StatNumber">
<item name="android:layout_width">wrap_content</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:textSize">28sp</item>
<item name="android:textStyle">bold</item>
<item name="android:textColor">?attr/colorPrimary</item>
<item name="android:text">0</item>
</style>
<style name="StatLabel">
<item name="android:layout_width">wrap_content</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:textAppearance">?attr/textAppearanceLabelLarge</item>
</style>
</resources>values-night से dark mode
values-night/ में उसी नाम की file dark mode on होने पर theme override करती है।
XML – res/values-night/themes.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- Dark mode: lighter green looks better on a dark background -->
<style name="Theme.StudentDiary" parent="Theme.Material3.DayNight.NoActionBar">
<item name="colorPrimary">#4ADE80</item>
<item name="colorOnPrimary">#052E16</item>
<item name="colorPrimaryContainer">#14532D</item>
<item name="colorOnPrimaryContainer">#DCFCE7</item>
<item name="colorSecondary">@color/accent</item>
<item name="colorOnSecondary">@android:color/black</item>
</style>
</resources>Fixed colours नहीं, theme attributes
XML
<!-- ❌ fixed colour – stays white in dark mode --> <LinearLayout android:background="#FFFFFF" /> <!-- ✅ theme attributes – change automatically --> <LinearLayout android:background="?attr/colorSurface" /> <TextView android:textColor="?attr/colorOnSurface" /> <TextView android:textColor="?attr/colorPrimary" /> <TextView android:textAppearance="?attr/textAppearanceTitleMedium" />
Reusable styles
ऊपर की theme file की StatCard, StatBox, StatNumber और StatLabel styles Progress screen पर तीन बार use होती हैं — एक बार बदलो, हर जगह update।
Dark mode switch
Kotlin – data/SettingsStore.kt
package com.codingeasily.studentdiary.data
import android.content.Context
import androidx.appcompat.app.AppCompatDelegate
import androidx.core.content.edit
/** Small key-value settings saved with SharedPreferences. */
class SettingsStore(context: Context) {
private val prefs = context.getSharedPreferences("settings", Context.MODE_PRIVATE)
var userName: String
get() = prefs.getString(KEY_NAME, "Student") ?: "Student"
set(value) = prefs.edit { putString(KEY_NAME, value) }
var darkMode: Boolean
get() = prefs.getBoolean(KEY_DARK, false)
set(value) = prefs.edit { putBoolean(KEY_DARK, value) }
var remindersEnabled: Boolean
get() = prefs.getBoolean(KEY_REMINDERS, true)
set(value) = prefs.edit { putBoolean(KEY_REMINDERS, value) }
fun applyTheme() {
AppCompatDelegate.setDefaultNightMode(
if (darkMode) AppCompatDelegate.MODE_NIGHT_YES else AppCompatDelegate.MODE_NIGHT_NO
)
}
companion object {
private const val KEY_NAME = "user_name"
private const val KEY_DARK = "dark_mode"
private const val KEY_REMINDERS = "reminders"
}
}Kotlin – use करना
// From Student Diary – SettingsFragment
binding.switchDark.isChecked = settings.darkMode
binding.switchDark.setOnCheckedChangeListener { _, checked ->
settings.darkMode = checked
settings.applyTheme() // the activity is recreated with the new theme
}
// StudentDiaryApp.onCreate() – apply the saved choice when the app starts
SettingsStore(this).applyTheme()Dynamic colour (Android 12+)
Kotlin
// app module: Application class
class StudentDiaryApp : Application() {
override fun onCreate() {
super.onCreate()
DynamicColors.applyToActivitiesIfAvailable(this) // wallpaper colours on Android 12+
}
}Optional: Android 12+ पर app user के wallpaper से colours लेती है, और पुराने phones पर आपके colours use करती है।
आम गलतियाँ
- Hard-coded
#FFFFFFbackgrounds और#000000text → dark mode में पढ़ा नहीं जाता। - MaterialComponents (M2) parent theme के साथ Material3 widget styles → गलत shapes/colours।
- Custom colour का night version भूलना → dark mode में भी वही चमकीला colour।
सारांश
- Theme = पूरी app (colour roles); style = एक view।
Theme.Material3.DayNight.NoActionBar+values-night/= automatic dark mode।- Layouts में
?attr/colorSurface,?attr/colorPrimaryवगैरह use करें। - User की choice save करके
AppCompatDelegate.setDefaultNightModecall करें।
✅ Practice
Material Theme Builder में अपने पसंदीदा colour से scheme बनाइए, app में paste कीजिए, और तीन options वाला dialog जोड़िए: Light / Dark / System।
अक्सर पूछे जाने वाले प्रश्न (FAQ)
पूरा Material 3 colour scheme कैसे बनाएँ?
Material Theme Builder (m3.material.io/theme-builder) use करें: seed colour चुनें और Android XML export करें। यह light और dark दोनों themes के सारे colour roles बनाता है।
Dark mode बदलने पर activity restart क्यों होती है?
AppCompatDelegate.setDefaultNightMode activities को दोबारा बनाता है ताकि नए resources load हों। Data ViewModel में रखें ताकि कुछ न खोए।
क्या phone की dark mode setting follow कर सकते हैं?
हाँ। MODE_NIGHT_FOLLOW_SYSTEM use करें। setDefaultNightMode कभी call न करें तो यही default है।
