[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"project-7554":3},{"id":4,"name":5,"fullName":6,"owner":7,"repo":5,"description":8,"homepage":9,"htmlUrl":10,"language":11,"languages":10,"totalLinesOfCode":10,"stars":12,"forks":13,"watchers":14,"openIssues":15,"contributorsCount":16,"subscribersCount":16,"size":16,"stars1d":16,"stars7d":16,"stars30d":16,"stars90d":16,"forks30d":16,"starsTrendScore":16,"compositeScore":17,"rankGlobal":10,"rankLanguage":10,"license":18,"archived":19,"fork":20,"defaultBranch":21,"hasWiki":20,"hasPages":20,"topics":22,"createdAt":10,"pushedAt":10,"updatedAt":34,"readmeContent":35,"aiSummary":36,"trendingCount":16,"starSnapshotCount":16,"syncStatus":37,"lastSyncTime":38,"discoverSource":39},7554,"aesthetic","afollestad\u002Faesthetic","afollestad","[DEPRECATED]","https:\u002F\u002Faf.codes",null,"Kotlin",1974,213,1976,14,0,54.99,"Apache License 2.0",true,false,"master",[23,24,25,26,27,28,29,30,31,32,33],"android","androidx","dynamic","engine","kotlin","reactive","runtime","rx","theme","theme-color","theme-properties","2026-06-12 04:00:34","# Aesthetic\n\n\u002FesˈTHedik\u002F: *adjective*, concerned with beauty or the appreciation of beauty. \n\n[ ![jCenter](https:\u002F\u002Fapi.bintray.com\u002Fpackages\u002Fdrummer-aidan\u002Fmaven\u002Faesthetic\u002Fimages\u002Fdownload.svg) ](https:\u002F\u002Fbintray.com\u002Fdrummer-aidan\u002Fmaven\u002Faesthetic\u002F_latestVersion)\n[![Build Status](https:\u002F\u002Ftravis-ci.org\u002Fafollestad\u002Faesthetic.svg)](https:\u002F\u002Ftravis-ci.org\u002Fafollestad\u002Faesthetic)\n[![Codacy Badge](https:\u002F\u002Fapi.codacy.com\u002Fproject\u002Fbadge\u002FGrade\u002Fb085aa9e67d441bd960f1c6abce5764c)](https:\u002F\u002Fwww.codacy.com\u002Fapp\u002Fdrummeraidan_50\u002Faesthetic?utm_source=github.com&amp;utm_medium=referral&amp;utm_content=afollestad\u002Faesthetic&amp;utm_campaign=Badge_Grade)\n[![License](https:\u002F\u002Fimg.shields.io\u002Fbadge\u002Flicense-Apache%202-4EB1BA.svg?style=flat)](https:\u002F\u002Fwww.apache.org\u002Flicenses\u002FLICENSE-2.0.html)\n\nYou can download an \u003Ca href=\"https:\u002F\u002Fraw.githubusercontent.com\u002Fafollestad\u002Faesthetic\u002Fmaster\u002Fsample.apk\">APK of the sample project\u003C\u002Fa>.\n\n\u003Cimg src=\"https:\u002F\u002Fraw.githubusercontent.com\u002Fafollestad\u002Faesthetic\u002Fmaster\u002Fimages\u002F1.jpg\" width=\"800\" \u002F>\n\n---\n\n# Table of Contents\n\n1. [Gradle Dependency](#gradle-dependency)\n2. [Integration](#integration)\n3. [Configuration](#configuration)\n4. [Attributes](#attributes)\n    1. [Base Values](#base-values)\n    2. [Standard Colors](#standard-colors)\n    3. [Standard Text Colors](#standard-text-colors)\n    4. [Custom Attributes](#custom-attributes)\n5. [Advanced Views](#advanced-views)\n    1. [Toolbars](#toolbars)\n    2. [Snackbars](#snackbars)\n    3. [CardViews](#cardviews)\n    4. [TabLayouts](#tablayouts)\n    5. [BottomNavigationViews](#bottomnavigationviews)\n    6. [NavigationViews](#navigationviews)\n    7. [SwipeRefreshLayouts](#swiperefreshlayouts)\n6. [Custom Views and Manual Application](#custom-views-and-manual-application)\n7. [Ignoring Views](#ignoring-views)\n\n---\n\n# Gradle Dependency\n\nAdd this to your app module's `build.gradle` file:\n\n```gradle\ndependencies {\n  \n  implementation 'com.afollestad:aesthetic:1.0.0-beta05'\n}\n```\n\n---\n\n# Integration\n\nAesthetic is integrated at a per-Activity level. The simplest way is \nto have your Activities extend `AestheticActivity`.\n\n```kotlin\nclass MyActivity : AestheticActivity() {\n\n  override fun onCreate(savedInstanceState: Bundle?) {\n    super.onCreate(savedInstanceState)\n  }\n}\n```\n\nIf you *don't want to or cannot extend this class*, you can manually \ntell Aesthetic about lifecycle events:\n\n```kotlin\nclass MyActivity : AppCompatActivity() {\n\n  override fun onCreate(savedInstanceState: Bundle?) {\n    Aesthetic.attach(this)  \u002F\u002F MUST come before super.onCreate(...)\n    super.onCreate(savedInstanceState)\n  }\n\n  override fun onResume() {\n    super.onResume()\n    Aesthetic.resume(this)\n  }\n\n  override fun onPause() {\n    Aesthetic.pause(this)\n    super.onPause()\n  }\n}\n```\n\n---\n\n# Configuration\n\nAesthetic provides a `isFirstTime` field which returns true until \nyou apply theme configuration at least once.\n\nYou can use this to setup defaults on app launch.\n\n```kotlin\nclass MyActivity : AestheticActivity() {\n\n  override fun onCreate(savedInstanceState: Bundle?) {\n    super.onCreate(savedInstanceState)\n    \n    \u002F\u002F If we haven't set any defaults, do that now\n    if (Aesthetic.isFirstTime) {\n        Aesthetic.config {\n          ...\n        }\n    }\n  }\n}\n```\n\nThere are two ways to \"configure\" Aesthetic, with the `config` method:\n\n```kotlin\nAesthetic.config {\n  colorPrimaryRes(R.color.blue)\n  ...\n}\n```\n\nOr by chaining the setters and calling `apply()`:\n\n```kotlin\nAesthetic.get()\n  .colorPrimaryRes(R.color.blue)\n  ...\n  .apply() \u002F\u002F don't forget apply() with this way\n```\n\n*If you are using Java*, you cannot use the `config` method.\n\n---\n\n# Attributes\n\nAttributes are the foundation of this library. They link your UI to dynamically changing colors.\n\nAttributes exist natively on Android, but they are not dynamic - they are rather set in your Activity \nthemes and are pre-determined at compile-time. This library gets around that.\n\n### Base Values\n\n```kotlin\nAesthetic.config {\n  \u002F\u002F Set to false for light themes, true for dark.\n  \u002F\u002F By default, is based on whether textColorPrimary is light\u002Fdark.\n  isDark(false)\n  \n  \u002F\u002F Causes an Activity recreate, calls setTheme(Int) on it.\n  activityTheme(R.style.MyActivityTheme)\n  \n  \u002F\u002F ON makes status bar icons black, and vice versa. AUTO bases it on \n  \u002F\u002F the status bar color, e.g. white -> light mode, black -> normal mode.\n  \u002F\u002F This has no effect below API 23 (Marshmallow). \n  lightStatusBarMode(AutoSwitchMode.AUTO)\n  \n  \u002F\u002F ON makes navigation bar icons black, and vice versa. AUTO bases it on \n  \u002F\u002F the navigation bar color, e.g. white -> light mode, black -> normal mode.\n  \u002F\u002F This has no effect below API 26 (Oreo).\n  lightNavigationBarMode(AutoSwitchMode.AUTO)\n}\n```\n\n---\n\n### Standard Colors\n\n```kotlin\nAesthetic.config {\n  \u002F\u002F ?colorPrimary, used for Toolbars, etc.\n  colorPrimaryRes(R.color.blue)\n  \u002F\u002F ?colorPrimaryDark, used for status bars, etc.\n  colorPrimaryDark(R.color.blue)\n  \u002F\u002F ?colorAccent, used for input fields, buttons, etc.\n  colorAccentRes(R.color.blue)\n  \n  \u002F\u002F Defaults to colorPrimaryDark.\n  colorStatusBarRes(R.color.blue)\n  \u002F\u002F Sets to colorPrimaryDark. \n  colorStatusBarAuto() \n  \n  \u002F\u002F Defaults to the value in your activity theme, or black.\n  colorNavigationBarRes(R.color.blue)\n  \u002F\u002F Sets nav bar color to match ?colorPrimaryDark. \n  \u002F\u002F If the color is light and light nav bar mode is disabled, it is forced to black.\n  colorNavigationBarAuto()\n  \n  \u002F\u002F Defaults to the value in your activity theme.\n  colorWindowBackgroundRes(R.color.blue)\n}\n```\n\nThe methods which end with `Res` take a color resource. Remove `Res` to \npass a literal (hardcoded) color integer.\n\n---\n\n### Standard Text Colors\n\n```kotlin\nAesthetic.config {\n  \u002F\u002F ?android:textColorPrimary\n  textColorPrimaryRes(R.color.black)\n  \u002F\u002F ?android:textColorSecondary\n  textColorSecondaryRes(R.color.dark_gray)\n  \n  \u002F\u002F ?android:textColorPrimaryInverse\n  textColorPrimaryInverseRes(R.color.white)\n  \u002F\u002F ?android:textColorSecondaryInverse\n  textColorSecondaryInverseRes(R.color.light_gray)\n}\n```\n\nThe methods which end with `Res` take a color resource. Remove `Res` to \npass a literal (hardcoded) color integer.\n\n---\n\n### Custom Attributes\n\nAll of the \"attributes\" shown and used in examples above are shown with shortcut methods that \nassign a color to a specific pre-existing attribute, such as `colorPrimary` from AndroidX.\n\nYou can define custom attributes that are usable in layouts. You can \nassign colors to theme like you would the predefined attributes above.\n\nFirst, you need to define the attribute in `\u002Fvalues\u002Fattrs.xml`:\n\n```xml\n\u003Cresources>\n  \u003Cattr format=\"color\" name=\"my_custom_attr\"\u002F>\n\u003C\u002Fresources>\n```\n\nThen you need to define a default in your Activity's theme so that \nAndroid's LayoutInflater can resolve something initially:\n\n```xml\n\u003Cstyle name=\"MyActivityTheme\" parent=\"Theme.AppCompat.Light\">\n  \u003Citem name=\"my_custom_attr\">#000000\u003C\u002Fitem>\n\u003C\u002Fstyle>\n```\n\nYou can use this attribute in your layouts:\n\n```xml\n\u003CTextView\n  android:layout_width=\"match_parent\"\n  android:layout_height=\"wrap_content\"\n  android:text=\"Hello, World!\"\n  android:textColor=\"?my_custom_attr\"\n  \u002F>\n```\n\nAnd you can assign dynamic values to it with Aesthetic:\n\n```kotlin\nAesthetic.config {\n\n   attributeRes(R.attr.your_attribute, R.color.blue)\n}\n```\n\nThe methods which end with `Res` take a color resource. Remove `Res` to \npass a literal (hardcoded) color integer.\n\n---\n\n# Advanced Views\n\nTo make Aesthetic a bit more plug-and-play, and to support views that \ncan't necessarily be color-themed from XML, additional options are \navailable for certain types of views.\n\n### Toolbars\n\nSpecial properties are provided for Toolbar icons (navigation icon, overflow icon, etc.) and the \ntitle and subtitle colors, so that they don't have to be paired with `textColorPrimary`, etc.\n\n```kotlin\nAesthetic.config {\n\n  \u002F\u002F Defaults to black or white based on the darkness of ?colorPrimary.\n  toolbarIconColorRes(R.color.white)\n   \n  \u002F\u002F Defaults to black or white based on the darkness of ?colorPrimary. \n  toolbarTitleColorRes(R.color.white)\n  \u002F\u002F Defaults to a faded version of the title color.\n  toolbarSubtitleColorRes(R.color.light_gray)\n}\n```\n\nYou can override these (not including the icon color) at a per-layout basis as well:\n\n```xml\n\u003Candroidx.appcompat.widget.Toolbar\n  ...\n  android:background=\"?some_color\"\n  app:titleTextColor=\"?some_color\"\n  app:subtitleTextColor=\"?some_color\"\n  \u002F>\n```\n\nIf you **do not** manually override background, the Toolbar will automatically \ndefault to the value of `?colorPrimary`.\n\n---\n\n### Snackbars\n\n\u003Cimg src=\"https:\u002F\u002Fraw.githubusercontent.com\u002Fafollestad\u002Faesthetic\u002Fmaster\u002Fimages\u002F2.jpg\" width=\"400\" \u002F>\n\n```kotlin\nAesthetic.config {\n  \u002F\u002F The color of the main text on a Snackbar\n  snackbarTextColorDefault()\n  snackbarTextColorRes(R.color.white)\n  \n  \u002F\u002F The color of the action on a Snackbar, if there is one.\n  snackbarActionTextColorRes(R.color.blue)\n  \n  \u002F\u002F The background color of Snackbar.\n  snackbarBackgroundColorDefault()\n  snackbarBackgroundColorRes(R.color.dark_gray)\n}\n```\n\n---\n\n### CardViews\n\n```kotlin\nAesthetic.config {\n  \u002F\u002F The background of CardViews is different because of the \n  \u002F\u002F rounding and elevation. This supports those elements.\n  colorCardViewBackgroundRes(R.color.white)\n}\n```\n\n---\n\n### TabLayouts\n\n*Note*: the color of text and icons in tab layouts will match that of Toolbars (using the \n`toolbarIconColor` and `toolbarTitleColor` attributes).\n\n```kotlin\nAesthetic.config {  \n  \u002F\u002F The selected tab's underline will be the primary color.\n  tabLayoutIndicatorMode(ColorMode.PRIMARY)\n  \u002F\u002F The selected tab's underline will be the accent color.\n  tabLayoutIndicatorMode(ColorMode.ACCENT)\n  \n  \u002F\u002F The tab layout's background will be the primary color.\n  tabLayoutBackgroundMode(ColorMode.PRIMARY)\n  \u002F\u002F The tab layout's background will be the accent color.\n  tabLayoutBackgroundMode(ColorMode.ACCENT)\n}\n```\n---\n\n### BottomNavigationViews\n\n\u003Cimg src=\"https:\u002F\u002Fraw.githubusercontent.com\u002Fafollestad\u002Faesthetic\u002Fmaster\u002Fimages\u002F4.jpg\" width=\"400\" \u002F>\n\n```kotlin\nAesthetic.config {\n  \u002F\u002F The tabs' background will be black or white based on the darkness \n  \u002F\u002F of the overall theme.\n  bottomNavigationBackgroundMode(BottomNavBgMode.BLACK_WHITE_AUTO)\n  \u002F\u002F The tabs' background will be the primary color.\n  bottomNavigationBackgroundMode(BottomNavBgMode.PRIMARY)\n  \u002F\u002F The tabs' background will be the dark primary color.\n  bottomNavigationBackgroundMode(BottomNavBgMode.PRIMARY_DARK)\n  \u002F\u002F The tabs' background will be the accent color.\n  bottomNavigationBackgroundMode(BottomNavBgMode.ACCENT)\n  \u002F\u002F This library will not do any automatic background color theming of bottom nav views.\n  bottomNavigationBackgroundMode(BottomNavBgMode.NONE)\n  \n  \u002F\u002F The selected tab's icon will be tinted with the primary color.\n  bottomNavigationIconTextMode(BottomNavIconTextMode.SELECTED_PRIMARY)\n  \u002F\u002F The selected tab's icon will be tinted with the accent color. \n  bottomNavigationIconTextMode(BottomNavIconTextMode.SELECTED_ACCENT)\n  \u002F\u002F The selected tab's icon will be tinted black or white based on \n  \u002F\u002F the darkness of the overall theme.\n  bottomNavigationIconTextMode(BottomNavIconTextMode.BLACK_WHITE_AUTO)\n  \u002F\u002F This library will not do any automatic icon\u002Ftext theming of bottom nav views.\n  bottomNavigationIconTextMode(BottomNavBgMode.NONE)\n}\n```\n\n---\n\n### NavigationViews\n\n\u003Cimg src=\"https:\u002F\u002Fraw.githubusercontent.com\u002Fafollestad\u002Faesthetic\u002Fmaster\u002Fimages\u002F3.jpg\" width=\"400\" \u002F>\n\n```kotlin\nAesthetic.config {  \n  \u002F\u002F The selected drawer item will be tinted with the primary color.\n  navigationViewMode(NavigationViewMode.SELECTED_PRIMARY)\n  \n  \u002F\u002F The selected drawer item will be tinted with the accent color. \n  navigationViewMode(NavigationViewMode.SELECTED_ACCENT)\n  \n  \u002F\u002F This library will not apply any auto theming to NavigationViews. \n  navigationViewMode(NavigationViewMode.NONE)\n}\n```\n\n---\n\n### SwipeRefreshLayouts\n\n\u003Cimg src=\"https:\u002F\u002Fraw.githubusercontent.com\u002Fafollestad\u002Faesthetic\u002Fmaster\u002Fimages\u002F6.jpg\" width=\"400\" \u002F>\n\n```kotlin\nAesthetic.config {\n\n  \u002F\u002F You can pass one more more comma-separated colors. \n  \u002F\u002F The colors that the refreshing indicator rotates through in a loop.\n  swipeRefreshLayoutColorsRes(R.color.red, R.color.blue)\n}\n```\n\n---\n\n# Custom Views and Manual Application\n\nAesthetic will not automatically theme most custom views, with some exceptions such as background\ncolor, text color, hint text color, an image view tint (these are handled without swapping view types).\n\nAesthetic makes it easy to subscribe to color changes so that you can manually apply colors to \nviews that need them.For an example, you can subscribe to pre-defined attributes, such as `colorPrimary()`:\n\n```kotlin\nval subscription = Aesthetic.get()\n  .colorPrimary()\n  .subscribe { color ->\n      \u002F\u002F Use color (an integer)\n  }\n      \n\u002F\u002F Later, you should unsubscribe, e.g. when your Activity pauses or your View detaches from its Window\nsubscription.dispose()\n```\n\nIf you only need the latest value and no further updates:\n\n```kotlin\nAesthetic.get()\n  .colorPrimary()\n  .take(1)\n  .subscribe { color ->\n      \u002F\u002F Use color (an integer)\n  }\n```\n\nYou can do the same with custom attributes by switching `colorPrimary()` with \n`attribute(R.attr.your_attr)`.\n\n---\n\nYou can even setup an inflation delegate to auto-swap views at inflation time, like Aesthetic does\nwith a lot of stock\u002FAndroidX views. This delegate is not called for views that Aesthetic already swaps internally. \n\n```kotlin\nclass MyInflationDelegate : InflationDelegate {\n\n  override fun createView(\n    context: Context,\n    attrs: AttributeSet?,\n    name: String,\n    viewId: Int\n  ): View? = when (name) {\n    \"com.somelibrary.CustomView\" -> ThemedCustomView(context, attrs)\n    else -> null\n  }\n}\n\nAesthetic.setInflationDelegate(MyInflationDelegate())\n```\n\n---\n\n# Ignoring Views\n\nYou can make this library ignore specific views from being themed with tags:\n\n```kotlin\n\u002F\u002F Can also be set in you layout XML\nview.setTag(\":aesthetic_ignore\")\n\nview.setTag(R.id.aesthetic_ignore, \"anything other than null\")\n```\n","Aesthetic 是一个用于 Android 应用的主题管理库，支持动态更改应用主题。它使用 Kotlin 编写，提供了一种反应式的方法来改变应用的视觉风格，包括颜色、文本颜色等属性，并且能够自动应用于常见的 UI 组件如 Toolbar、Snackbar 等。该库还允许开发者为自定义视图手动应用主题设置或选择忽略特定视图。适用于需要根据用户偏好或其他条件动态调整界面外观的场景中，以提升用户体验的一致性和个性化程度。尽管项目已不再维护，但其设计理念和实现方式仍可作为参考。",2,"2026-06-11 03:13:01","top_language"]