# Colorful Android Theme Switching Through View Setters

> Colorful is a Java library for changing selected Android UI properties between day and night themes without recreating the Activity. It uses custom Theme attributes, View ID bindings, and setter objects for container children.

**hehonghui/Colorful** — 基于Theme的Android动态换肤库，无需重启Activity、无需自定义View，方便的实现日间、夜间模式。

- Repository: https://github.com/hehonghui/Colorful
- Stars: 1,400 · Forks: 265
- Language: Java
- License: MIT
- Published: 2026-10-16 · Updated: 2026-10-16 · Language: en
- Canonical page: https://hysenlabs.com/projects/hehonghui-colorful

## Colorful's Targeted Android Skinning Boundary

Colorful addresses a specific Android UI problem: changing selected appearance properties after an Activity has started without recreating that Activity. It is intended for Java developers who want a screen, or a controlled set of screens, to use different color and drawable resources for day and night presentation. The library does not treat a visual style as an opaque package. Instead, the developer declares Android Theme attributes, assigns those attributes to layout properties, and registers the relevant Views with a `Colorful` object.

That design gives the developer control, but it also defines the boundary of the library. A layout property must use a custom attribute such as `?attr/text_color`, and the corresponding View must be associated with that attribute through `Colorful.Builder`. The README does not say that Colorful scans every View in an Activity or automatically handles every possible custom View implementation. Its documented examples use explicit View IDs, explicit property calls, and an explicit `ViewGroupSetter` for children of a `ListView`.

The practical audience is therefore an Android application that already organizes day and night resources and accepts a registration step for each replaceable property. It is a focused skinning mechanism, not a documented full night-mode system for every Android component. The amount of integration work depends on how many properties the application wants to change and how its Views are created.

## How Theme Attributes Drive Colorful View Updates

The documented data flow begins with custom attributes. The README defines values such as `root_view_bg`, `btn_bg`, and `text_color` with the format `reference|color`. Layouts use those attributes in properties. The root layout assigns `?attr/root_view_bg` to `android:background`, while a `TextView` and a `Button` assign `?attr/text_color` to `android:textColor`.

The Themes supply the actual resources. `DayTheme` assigns `root_view_bg` to `@drawable/bg_day`, `btn_bg` to `@color/white_btn_color`, and `text_color` to `@color/black_tx_color`. `NightTheme` assigns the same attribute names to `@drawable/bg_night`, `@color/black_btn_color`, and `@color/white_tx_color`. The attribute name remains the same while its Theme-specific value changes.

Colorful is then connected to the Views. The builder call `backgroundDrawable(R.id.root_view, R.attr.root_view_bg)` associates the root View's background with the `root_view_bg` attribute. `backgroundColor(R.id.change_btn, R.attr.btn_bg)` does the same for the button background, and `textColor(R.id.textview, R.attr.text_color)` associates the TextView text color with `text_color`.

The final operation is `setTheme(R.style.DayTheme)` or `setTheme(R.style.NightTheme)`. According to the README, this updates the registered properties without restarting the Activity. The description is limited to those registered properties. It does not establish that an unregistered child, a programmatically created View, or an unlisted property will change.

## Declaring Attributes and Themes for Day and Night

Start by adding custom attributes in the application's `res/values/attrs.xml`. The README gives these definitions. The format allows an attribute to resolve either to a drawable reference or to a color resource.

```xml
<resources>
    <attr name="root_view_bg" format="reference|color" />
    <attr name="btn_bg" format="reference|color" />
    <attr name="text_color" format="reference|color" />
</resources>
```

Next, define separate Themes that inherit from the application's existing theme hierarchy. The README uses `Theme.AppCompat.Light` as the base for the example application and creates `DayTheme` and `NightTheme` beneath `AppTheme`. The custom items map each attribute to a resource.

```xml
<style name="DayTheme" parent="AppTheme">
    <item name="root_view_bg">@drawable/bg_day</item>
    <item name="btn_bg">@color/white_btn_color</item>
    <item name="text_color">@color/black_tx_color</item>
</style>
<style name="NightTheme" parent="AppTheme">
    <item name="root_view_bg">@drawable/bg_night</item>
    <item name="btn_bg">@color/black_btn_color</item>
    <item name="text_color">@color/white_tx_color</item>
</style>
```

The corresponding color values can be placed in `colors.xml`. The exact color names and values shown in the README are examples rather than requirements. The important contract is that each Theme provides a value for every attribute that a registered View property depends on.

## Binding Colorful Properties to Android Views

The first real use is to reference the custom attributes from the layout, then build a `Colorful` object for the Activity. In the README layout, the root `RelativeLayout` uses `android:background="?attr/root_view_bg"`, the main `TextView` uses `android:textColor="?attr/text_color"`, and the button that changes the Theme uses the same text color attribute. The layout also includes a `ListView` whose items contain a `news_title` View.

The Java binding identifies the Views by ID and chooses the property operation for each one:

```java
ListView mNewsListView = (ListView) findViewById(R.id.listview);
ViewGroupSetter listViewSetter =
        new ViewGroupSetter(mNewsListView, 0);
listViewSetter.childViewTextColor(
        R.id.news_title, R.attr.text_color);

Colorful mColorful = new Colorful.Builder(this)
        .backgroundDrawable(R.id.root_view, R.attr.root_view_bg)
        .backgroundColor(R.id.change_btn, R.attr.btn_bg)
        .textColor(R.id.textview, R.attr.text_color)
        .setter(listViewSetter)
        .create();
```

The `backgroundDrawable` call changes the root background drawable. The `backgroundColor` call changes the button's background color. The `textColor` call changes the text color of the main TextView. `ViewGroupSetter` handles the different case created by a `ListView`, where the target `news_title` View belongs to an item rather than directly to the Activity layout.

This registration step is the main integration cost. It is also where the library's scope becomes visible. The example can update a known root View, a known button, a known TextView, and a known child in ListView items. It does not demonstrate registration for every Android widget, an adapter-generated View hierarchy beyond the supplied setter, or a View created after `Colorful` is created.

## Switching Themes Without Recreating the Activity

After creating the `Colorful` instance, keep it available to the code that changes the Theme. The README example uses a boolean flag named `isNight` and switches between the two style resources in opposite branches.

```java
boolean isNight = false;

private void changeThemeWithColorful() {
    if (!isNight) {
        mColorful.setTheme(R.style.DayTheme);
    } else {
        mColorful.setTheme(R.style.NightTheme);
    }
    isNight = !isNight;
}
```

The first call selects `DayTheme`, and the next selects `NightTheme`, depending on the current flag. The documented result is that the registered background, color, and text properties change without restarting the Activity. The example also demonstrates a second Activity in the layout, but the README does not describe how that second Activity shares or synchronizes the selected Theme. It would therefore be incorrect to assume that creating a `Colorful` instance in one Activity automatically applies it to every Activity.

There is a separate persistence question. The example stores `isNight` as an Activity field. The README does not document saving this value in `SharedPreferences`, restoring it after process death, or applying it before the first layout inflation. The sample therefore demonstrates a runtime switch, not a complete preference or startup flow.

## ListView Items and Explicit Setter Scope

The `ViewGroupSetter` example is the clearest indication of how Colorful handles descendants. A `ListView` does not expose each item's child View as a direct member of the Activity layout in the same way as `R.id.textview`. The README creates a `ViewGroupSetter` for `R.id.listview` and calls `childViewTextColor(R.id.news_title, R.attr.text_color)`. During a Theme change, the setter is documented as traversing the ListView's item Views and modifying each bound `news_title` control.

This solves a concrete propagation problem, but it does not make child handling universal. The target child ID must be known, and the setter must be added to the `Colorful.Builder`. If an item contains several themed properties, or if different item layouts use different child IDs, the application needs the corresponding setter registrations. The README does not state that Colorful discovers those variations automatically.

The same limitation applies to other containers. The repository description says the library does not require custom Views, which is compatible with using standard Views such as `TextView`, `Button`, and `ListView`. However, “no custom View required” is not the same as “all custom View properties are handled automatically.” For a screen that creates Views dynamically or nests additional containers, the developer should treat setter coverage as part of the integration design and verify the exact child registration required by the library API.

## Installation, Maintenance, and License Considerations

The README does not provide a Gradle dependency declaration, Maven coordinate, version number, or step-by-step installation command. It directs users to the repository and says that the Demo depends on support v7, which users must add themselves. The repository contains a Gradle project with `app/` and `colorful/` entries, but the README does not explain how to publish or consume the library as a packaged dependency. A first use therefore starts by inspecting the project structure and integrating the source or following an undocumented module import path, rather than by copying a documented package installation line.

There are no GitHub releases in the repository information, and the repository is not archived. The last push was on 2026-08-07, so the project has a recent recorded change. That fact does not establish a release cadence, compatibility policy, or long-term support commitment. The MIT license permits use, modification, and distribution under its terms, subject to the license text. It does not answer Android API compatibility, Gradle compatibility, or whether the source remains compatible with current Android tooling.

The missing installation and release documentation matters for adoption. A team must determine how to include the library, which Android support versions its own project uses, and whether the source can be maintained locally when the library changes.

## Colorful Compared with Activity Theme Replacement

A conventional Android Theme change can be initiated by applying a different Activity Theme, but the README does not describe the behavior or limits of that approach in this repository. The useful comparison is architectural. Colorful keeps the Activity in place and explicitly maps Theme attributes to selected View properties through a builder object. The documented operation is `setTheme`, followed by updates to registered Views.

This differs from relying on Android's normal resource and Theme lifecycle. Colorful requires the application to replace fixed references such as `@color/black_tx_color` with custom attributes in layouts and to register the Views whose properties should change. The trade-off is precise control over the update path. The cost is an explicit mapping that can become incomplete when screens add Views, adapters, or nested containers.

For a small, fixed UI with a controlled set of color changes, the explicit model may be easier to reason about. For a large application with many Activities and resource-driven widgets, the amount of registration work is the central adoption question. The README does not provide a comparison with AppCompat DayNight behavior, configuration-change handling, or automatic persistence, so those subjects should not be treated as documented Colorful features.

## Conclusion

Colorful fits existing Android applications that already use Theme attributes and can register every affected View property. It is unsuitable when the application needs automatic discovery of arbitrary Views, packaged installation instructions, or a complete Theme replacement model. Before adoption, verify that `Colorful.Builder` reaches every relevant View, that setters cover ListView items and other containers, and how the application will preserve the selected Theme across process restarts.

## FAQ

### Does Colorful support installing it in an Android project?

The README does not provide a package installation command or dependency declaration. It points users to the repository and says that the Demo depends on support v7, which must be added separately.

### How does Colorful change ListView item text colors?

The README uses `ViewGroupSetter` to bind `news_title` inside ListView items to `R.attr.text_color`. During a Theme change, the documented setter traverses the ListView item Views and updates that child text color.

### Does Colorful automatically discover every View in an Activity?

The documented builder calls register specific View IDs and property changes. The README also shows an explicit `ViewGroupSetter` for ListView children, but it does not document automatic discovery of every View or custom View property.

## Sources

- [hehonghui/Colorful on GitHub](https://github.com/hehonghui/Colorful)
- [Issues](https://github.com/hehonghui/Colorful/issues)
- [License: MIT](https://github.com/hehonghui/Colorful/blob/master/LICENSE)
- [README](https://github.com/hehonghui/Colorful/blob/master/README.md)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/hehonghui-colorful
