// How It Works
Android automatically picks the right drawable and color based on two folder qualifiers:
• -v31 = Android 12+ (API 31)
• -night = system dark mode
You only need 4 drawable files in 4 folders and 4 values files in 4 folders. No Kotlin code changes. The layout just references @drawable/widget_background and @color/widget_text_primary and Android resolves the correct one at runtime.
// Folder Structure
res/
├── drawable/ # Pre-12, light (fallback)
│ └── widget_background.xml
├── drawable-night/ # Pre-12, dark
│ └── widget_background.xml
├── drawable-v31/ # Android 12+, light (Material You)
│ └── widget_background.xml
├── drawable-night-v31/ # Android 12+, dark (Material You)
│ └── widget_background.xml
├── layout/ # Just one file — no qualifiers needed
│ └── your_widget.xml
├── values/ # Pre-12, light text colors
│ └── colors.xml
├── values-night/ # Pre-12, dark text colors
│ └── colors.xml
├── values-v31/ # Android 12+, light text colors (Material You)
│ └── colors.xml
└── values-night-v31/ # Android 12+, dark text colors (Material You)
└── colors.xml
! The layout folder never needs -night or -v31 variants. Layouts only contain structure and references to @color and @drawable — the qualifier folders handle all the actual theme switching. One layout file works everywhere.
// The 4 Drawable Files
drawable/widget_background.xml — pre-12 light fallback
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
<solid android:color="#F5F5F5" />
<corners android:radius="20dp" />
</shape>
drawable-night/widget_background.xml — pre-12 dark fallback
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
<solid android:color="#212121" />
<corners android:radius="20dp" />
</shape>
drawable-v31/widget_background.xml — Android 12+ light (Material You)
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
<solid android:color="@android:color/system_accent2_50" />
<corners android:radius="20dp" />
<stroke android:width="2dp" android:color="@android:color/system_accent2_50" />
</shape>
drawable-night-v31/widget_background.xml — Android 12+ dark (Material You)
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
<solid android:color="@android:color/system_accent2_800" />
<corners android:radius="20dp" />
<stroke android:width="2dp" android:color="@android:color/system_accent2_800" />
</shape>
// The 4 Values Files
Text colors follow the same 4-folder pattern so Material You wallpaper colors apply to text too on Android 12+.
values/colors.xml — pre-12 light
<color name="widget_text_primary">#1F1F2E</color>
<color name="widget_text_secondary">#6B6B8A</color>
<color name="widget_text_sunday">#D03B3B</color>
<color name="widget_today_text">#FFFFFF</color>
<color name="widget_arrow">#FFFFFF</color>
values-night/colors.xml — pre-12 dark
<color name="widget_text_primary">#E8E8F0</color>
<color name="widget_text_secondary">#9A9AB0</color>
<color name="widget_text_sunday">#FF6B6B</color>
<color name="widget_today_text">#FFFFFF</color>
<color name="widget_arrow">#FFFFFF</color>
values-v31/colors.xml — Android 12+ light (Material You)
<color name="widget_text_primary">@android:color/system_neutral1_900</color>
<color name="widget_text_secondary">@android:color/system_neutral2_600</color>
<color name="widget_text_sunday">@android:color/system_accent3_700</color>
<color name="widget_today_text">@android:color/system_accent2_50</color>
<color name="widget_arrow">@android:color/system_accent1_900</color>
values-night-v31/colors.xml — Android 12+ dark (Material You)
<color name="widget_text_primary">@android:color/system_neutral1_50</color>
<color name="widget_text_secondary">@android:color/system_neutral2_300</color>
<color name="widget_text_sunday">@android:color/system_accent3_200</color>
<color name="widget_today_text">@android:color/system_accent2_900</color>
<color name="widget_arrow">@android:color/system_accent1_100</color>
// Layout Usage
Reference everything by name — Android resolves the right file automatically:
android:background="@drawable/widget_background"
android:textColor="@color/widget_text_primary"
android:textColor="@color/widget_text_secondary"
android:textColor="@color/widget_text_sunday"
android:textColor="@color/widget_today_text"
android:tint="@color/widget_arrow"
! android:tint works on ImageButton and ImageView only — never on TextView. For text color always use android:textColor.
// Kotlin Code
Nothing special needed. Standard RemoteViews call — Android handles everything:
val views = RemoteViews(context.packageName, R.layout.your_widget_layout)
appWidgetManager.updateAppWidget(appWidgetId, views)
! The drawable and color resolution happens entirely at the Android OS level. Your Kotlin code is completely unaware of it.
// Material You Color Tokens (API 31+)
These are the @android:color/system_* tokens available on Android 12+. Shades range from _10 (lightest) to _1000 (darkest).
| Token family |
Light shade |
Dark shade |
Best for |
| system_accent2_* |
_50 |
_800 |
Widget background |
| system_accent1_* |
_100 |
_700 |
Primary accent surface |
| system_neutral1_* |
_50 |
_900 |
Neutral background |
| system_neutral2_* |
_100 |
_800 |
Muted surface |
| system_accent3_* |
_700 |
_200 |
Accent text (e.g. sunday) |
// Quick Setup Command
Run from your res/ directory:
mkdir -p drawable-night drawable-v31 drawable-night-v31 values-night values-v31 values-night-v31 && \
cat > drawable/widget_pill_bg.xml << 'EOF'
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
<solid android:color="#5C4AE4" />
<corners android:radius="24dp" />
</shape>
EOF
cat > drawable/widget_card_bg.xml << 'EOF'
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
<solid android:color="#F3F1FF" />
<corners android:radius="16dp" />
</shape>
EOF
cat > drawable/widget_circle_today.xml << 'EOF'
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval">
<solid android:color="#5C4AE4" />
</shape>
EOF
cat > drawable/widget_circle_holiday.xml << 'EOF'
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval">
<solid android:color="#C0A78BFF" />
</shape>
EOF
cat > drawable-night/widget_pill_bg.xml << 'EOF'
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
<solid android:color="#7C6AF0" />
<corners android:radius="24dp" />
</shape>
EOF
cat > drawable-night/widget_card_bg.xml << 'EOF'
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
<solid android:color="#1E1B2E" />
<corners android:radius="16dp" />
</shape>
EOF
cat > drawable-night/widget_circle_today.xml << 'EOF'
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval">
<solid android:color="#7C6AF0" />
</shape>
EOF
cat > drawable-night/widget_circle_holiday.xml << 'EOF'
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval">
<solid android:color="#80A78BFF" />
</shape>
EOF
cat > drawable-v31/widget_pill_bg.xml << 'EOF'
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
<solid android:color="@android:color/system_accent1_200" />
<corners android:radius="24dp" />
</shape>
EOF
cat > drawable-v31/widget_card_bg.xml << 'EOF'
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
<solid android:color="@android:color/system_accent2_50" />
<corners android:radius="16dp" />
</shape>
EOF
cat > drawable-v31/widget_circle_today.xml << 'EOF'
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval">
<solid android:color="@android:color/system_accent1_300" />
</shape>
EOF
cat > drawable-v31/widget_circle_holiday.xml << 'EOF'
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval">
<solid android:color="@android:color/system_accent2_200" />
</shape>
EOF
cat > drawable-night-v31/widget_pill_bg.xml << 'EOF'
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
<solid android:color="@android:color/system_accent1_700" />
<corners android:radius="24dp" />
</shape>
EOF
cat > drawable-night-v31/widget_card_bg.xml << 'EOF'
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
<solid android:color="@android:color/system_accent2_800" />
<corners android:radius="16dp" />
</shape>
EOF
cat > drawable-night-v31/widget_circle_today.xml << 'EOF'
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval">
<solid android:color="@android:color/system_accent1_600" />
</shape>
EOF
cat > drawable-night-v31/widget_circle_holiday.xml << 'EOF'
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval">
<solid android:color="@android:color/system_accent2_700" />
</shape>
EOF
cat > values/colors.xml << 'EOF'
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="widget_text_primary">#1F1F2E</color>
<color name="widget_text_secondary">#6B6B8A</color>
<color name="widget_text_sunday">#D03B3B</color>
<color name="widget_today_text">#FFFFFF</color>
<color name="widget_arrow">#FFFFFF</color>
</resources>
EOF
cat > values-night/colors.xml << 'EOF'
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="widget_text_primary">#E8E8F0</color>
<color name="widget_text_secondary">#9A9AB0</color>
<color name="widget_text_sunday">#FF6B6B</color>
<color name="widget_today_text">#FFFFFF</color>
<color name="widget_arrow">#FFFFFF</color>
</resources>
EOF
cat > values-v31/colors.xml << 'EOF'
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="widget_text_primary">@android:color/system_neutral1_900</color>
<color name="widget_text_secondary">@android:color/system_neutral2_600</color>
<color name="widget_text_sunday">@android:color/system_accent3_700</color>
<color name="widget_today_text">@android:color/system_accent2_50</color>
<color name="widget_arrow">@android:color/system_accent1_900</color>
</resources>
EOF
cat > values-night-v31/colors.xml << 'EOF'
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="widget_text_primary">@android:color/system_neutral1_50</color>
<color name="widget_text_secondary">@android:color/system_neutral2_300</color>
<color name="widget_text_sunday">@android:color/system_accent3_200</color>
<color name="widget_today_text">@android:color/system_accent2_900</color>
<color name="widget_arrow">@android:color/system_accent1_100</color>
</resources>
EOF