{"id":13765312,"url":"https://github.com/imandolatkia/Android-Animated-Theme-Manager","last_synced_at":"2025-05-10T20:31:55.732Z","repository":{"id":42060490,"uuid":"395971708","full_name":"imandolatkia/Android-Animated-Theme-Manager","owner":"imandolatkia","description":"create your custom themes and change them dynamically with ripple animation","archived":false,"fork":false,"pushed_at":"2024-07-10T15:01:32.000Z","size":943,"stargazers_count":703,"open_issues_count":10,"forks_count":64,"subscribers_count":13,"default_branch":"main","last_synced_at":"2024-11-17T01:32:47.676Z","etag":null,"topics":["android","android-library","animation","java","kotlin","ripple","ripple-animation","theme","thememanager"],"latest_commit_sha":null,"homepage":"","language":"Kotlin","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/imandolatkia.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":["imandolatkia"]}},"created_at":"2021-08-14T10:22:28.000Z","updated_at":"2024-11-13T19:27:09.000Z","dependencies_parsed_at":"2024-08-03T16:03:57.297Z","dependency_job_id":"1b9a57b6-294f-40a9-8bcd-017a39b471fd","html_url":"https://github.com/imandolatkia/Android-Animated-Theme-Manager","commit_stats":null,"previous_names":[],"tags_count":6,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/imandolatkia%2FAndroid-Animated-Theme-Manager","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/imandolatkia%2FAndroid-Animated-Theme-Manager/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/imandolatkia%2FAndroid-Animated-Theme-Manager/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/imandolatkia%2FAndroid-Animated-Theme-Manager/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/imandolatkia","download_url":"https://codeload.github.com/imandolatkia/Android-Animated-Theme-Manager/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":253480654,"owners_count":21915249,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["android","android-library","animation","java","kotlin","ripple","ripple-animation","theme","thememanager"],"created_at":"2024-08-03T16:00:36.867Z","updated_at":"2025-05-10T20:31:50.719Z","avatar_url":"https://github.com/imandolatkia.png","language":"Kotlin","funding_links":["https://github.com/sponsors/imandolatkia"],"categories":["Personalisation"],"sub_categories":["2FA and TOTP"],"readme":"# Android Animated Theme Manager   [![Tweet](https://img.shields.io/twitter/url/http/shields.io.svg?style=social)](https://twitter.com/intent/tweet?text=Android%20Animated%20Theme%20Manager%20Library\u0026url=https://github.com/imandolatkia/Android-Animated-Theme-Manager\u0026hashtags=Android,Theme,Ripple,kotlin,java,lbrary)\n[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)   [![Maven Central](https://maven-badges.herokuapp.com/maven-central/com.dolatkia/animated-theme-manager/badge.svg)](https://maven-badges.herokuapp.com/maven-central/com.dolatkia/animated-theme-manager)\n[![Generic badge](https://img.shields.io/badge/Repo_Size-26_kb-orange.svg)](https://search.maven.org/remotecontent?filepath=io/github/imandolatkia/animatedThemeManager/1.1.2/animatedThemeManager-1.1.2.aar)\n[![Generic badge](https://img.shields.io/badge/kotlin-100-blue.svg)](https://github.com/imandolatkia/Android-Animated-Theme-Manager/search?l=kotlin)\n[![Generic badge](https://img.shields.io/badge/support-java_\u0026_kotlin-green.svg)](https://github.com/imandolatkia/Android-Animated-Theme-Manager/search?l=kotlin)\n[![CodeFactor](https://www.codefactor.io/repository/github/imandolatkia/android-animated-theme-manager/badge)](https://www.codefactor.io/repository/github/imandolatkia/android-animated-theme-manager)\n[![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=imandolatkia_Android-Animated-Theme-Manager\u0026metric=alert_status)](https://sonarcloud.io/dashboard?id=imandolatkia_Android-Animated-Theme-Manager)\n\nCreate custom themes and change them dynamically with the ripple animation\n\n**✅ We are open to any new feature request, bug fix request, and pull request.**\n\u003c/br\u003e\u003c/br\u003e\n\n# Demo\n![animation-ripple-android-theme](https://user-images.githubusercontent.com/6734608/129915453-b57a1618-2d20-42a3-85a7-57bd1c425522.gif)\n\u003c/br\u003e\u003c/br\u003e\n\n\n\n# Features\n* support **java** and **kotlin** projects.\n* change theme **without recreating** activities and fragments.\n* support multi fragments apps.\n* ripple animation.\n* **reverse animation**.\n* changeable animation duration.\n* changeable animation position.\n* animation listener.\n* observe changes of themes for custom actions with Livedata.\n* easy to use, 5 or 7 tiny steps.\n* **support any android APIs** (animation works on API\u003e20).\n\n\u003c/br\u003e\u003c/b\u003e\n\n# How to install? [![Maven Central](https://maven-badges.herokuapp.com/maven-central/com.dolatkia/animated-theme-manager/badge.svg)](https://maven-badges.herokuapp.com/maven-central/com.dolatkia/animated-theme-manager)\n\nAdd the following line to **app-level** build.gradle file, in dependencies scope:\n```gradle\ndependencies {\n    ...\n    implementation \"com.dolatkia:animated-theme-manager:1.1.4\"\n}\n```\n\u003c/br\u003e\n\n# How to use?\n1- Create an abstract class that inherits from **AppTheme**. In this class create abstract methods to return related color for all UI element that you want to change them on each theme. For example, if you want to change the background color, text colors and icon colors in your **firstActivity**, do the following:\n\n```kotlin\ninterface MyAppTheme : AppTheme {\n    fun firstActivityBackgroundColor(context: Context): Int\n    fun firstActivityTextColor(context: Context): Int\n    fun firstActivityIconColor(context: Context): Int\n    // any other methods for other elements\n}\n```\n\n\u003cdetails\u003e\u003csummary\u003ejava\u003c/summary\u003e\n\u003cp\u003e\n\n```java\ninterface MyAppTheme extends AppTheme {\n    int firstActivityBackgroundColor(@NotNull Context context);\n    int firstActivityTextColor(@NotNull Context context);\n    int firstActivityIconColor(@NotNull Context context);\n    // any other methods for other elements\n}\n```\n\u003c/details\u003e\n\n2- For each theme that you want in your app, create a class that extends from  **the class that was created in step 1 (MyAppTheme)**, and implement methods with related colors or resources, for example, if you want to have 3 themes, you should create 3 class and implement methods:\n\n```kotlin\nclass LightTheme : MyAppTheme {\n\n    override fun id(): Int { // set unique iD for each theme \n        return 0\n    }\n\n    override fun firstActivityBackgroundColor(context: Context): Int {\n        return ContextCompat.getColor(context, R.color.background_light)\n    }\n\n    override fun firstActivityTextColor(context: Context): Int {\n        return ContextCompat.getColor(context, R.color.text_light)\n    }\n    \n     override fun firstActivityIconColor(context: Context): Int {\n        return ContextCompat.getColor(context, R.color.icon_light)\n    }\n    \n    ...\n}\n\nclass NightTheme : MyAppTheme {...}\nclass PinkTheme : MyAppTheme {...}\n\n```\n\n\u003cdetails\u003e\u003csummary\u003ejava\u003c/summary\u003e\n\u003cp\u003e\n\n```java\npublic class LightTheme implements MyAppTheme {\n    public int id() { // set unique iD for each theme \n        return 0;\n    }\n\n    public int firstActivityBackgroundColor(@NotNull Context context) {\n        return ContextCompat.getColor(context, R.color.background_light);\n    }\n\n    public int firstActivityTextColor(@NotNull Context context) {\n        return ContextCompat.getColor(context,  R.color.text_light);\n    }\n\n    public int firstActivityIconColor(@NotNull Context context) {\n        return ContextCompat.getColor(context, R.color.icon_light);\n    }\n    \n    ...\n}\n    \npublic class NightTheme implements MyAppTheme {...}\npublic class PinkTheme implements MyAppTheme {...}\n\n```\n\u003c/details\u003e\n\n\n3- Extend your activity from **ThemeActivity**:\n```kotlin\nMainActivity : ThemeActivity() {\n...\n}\n```\n\u003cdetails\u003e\u003csummary\u003ejava\u003c/summary\u003e\n\u003cp\u003e\n\n```java\npublic class MainActivity implements ThemeActivity {\n...\n}\n\n```\n\u003c/details\u003e\n\n4- Implement ThemeActivity's **2 abstract methods**:\n\n```kotlin\n// to sync ui with selected theme\noverride fun syncTheme(appTheme: AppTheme) {\n    // change ui colors with new appThem here\n\n    val myAppTheme = appTheme as MyAppTheme\n    // set background color\n    binder.root.setBackgroundColor(myAppTheme.firstActivityBackgroundColor(this))\n\n    //set text color\n    binder.text.setTextColor(myAppTheme.activityTextColor(this))\n        \n    // set icons color\n    binder.share.setColorFilter(myAppTheme.firstActivityIconColor(this))\n    binder.gift.setColorFilter(myAppTheme.firstActivityIconColor(this))        \n    ...\n}\n\n// to save the theme for the next time, save it in onDestroy() (exp: in pref or DB) and return it here.\n// it just used for the first time (first activity).\noverride fun getStartTheme(): AppTheme {\n    return LightTheme()\n}\n\n```\n\n\u003cdetails\u003e\u003csummary\u003ejava\u003c/summary\u003e\n\u003cp\u003e\n\n```java\n// to sync ui with selected theme\n@Override\npublic void syncTheme(@NotNull AppTheme appTheme) {\n    // change ui colors with new appThem here\n\n    MyAppTheme myAppTheme = (MyAppTheme) appTheme;\n\n    // set background color\n    binder.getRoot().setBackgroundColor(myAppTheme.activityBackgroundColor(this));\n\n    //set text color\n    binder.text.setTextColor(myAppTheme.activityTextColor(this));\n\n    // set icons color\n    binder.share.setColorFilter(myAppTheme.activityBackgroundColor(this));\n    binder.gift.setColorFilter(myAppTheme.activityBackgroundColor(this));\n}\n\n// to get start theme\n@NotNull\n@Override\npublic AppTheme getStartTheme() {\n    return new LightTheme();\n}\n```\n\u003c/details\u003e\n\n5- Change theme with the ```ThemeManager.instance.changeTheme()``` method:\n```kotlin\n// set change theme click listener\nbinder.lightButton.setOnClickListener {\n  ThemeManager.instance.changeTheme(LightTheme(), it)\n}\n```\n\u003cdetails\u003e\u003csummary\u003ejava\u003c/summary\u003e\n\u003cp\u003e\n\n```java\nbinder.lightButton.setOnClickListener(new View.OnClickListener() {\n    @Override\n    public void onClick(View v) {\n      ThemeManager.Companion.getInstance().changeTheme(new LightTheme(), v, 600);\n    }\n});\n```\n\u003c/details\u003e\n\nThe first argument is the selected theme.\n\nThe second argument is the view that animation starts from the center of it.\n\u003c/br\u003e\u003c/br\u003e\n\n# How to use in multi fragments app?\nRepeat all previous 5 steps, and then:\n\n\n6- Extend your fragments from **ThemeFragment**:\n```kotlin\nMyFragment : ThemeFragment() {\n...\n}\n```\n\n\u003cdetails\u003e\u003csummary\u003ejava\u003c/summary\u003e\n\u003cp\u003e\n\n```java\npublic class MyFragment implements ThemeFragment {\n...\n}\n```\n\u003c/details\u003e\n\n7- Implement ThemeFragment **syncTheme abstract methods**:\n\n```kotlin\n// to sync ui with selected theme\noverride fun syncTheme(appTheme: AppTheme) {\n    // change ui colors with new appThem here\n    ...\n}\n```\n\n\u003cdetails\u003e\u003csummary\u003ejava\u003c/summary\u003e\n\u003cp\u003e\n\n```java\n@Override\npublic void syncTheme(@NotNull AppTheme appTheme) {\n    // change ui colors with new appThem here\n    ...\n}\n```\n\u003c/details\u003e\n\u003c/br\u003e\n\n# Some other settings and customization:\n###  ✔️ reverse animation\nIf you want to use the reverse animation, call `reverseChangeTheme()` instead of `changeTheme()`:\n\n```kotline\n   binder.lightButton.setOnClickListener {\n        ThemeManager.instance.reverseChangeTheme(LightTheme(), it)\n   }\n```\n![reverse ripple theme animation](https://user-images.githubusercontent.com/6734608/130370446-1218d53d-9c25-4dc9-8d6b-f7e8a1056731.gif)\n\n###  ✔️ change animation duration\nIf you want to change the animation duration, add your desired duration in milliseconds as the third argument of `ThemeManager.instance.changeTheme()`. The default value is `600`:\n\n```kotlin\n   binder.lightButton.setOnClickListener {\n        ThemeManager.instance.changeTheme(LightTheme(), it, 800)\n   }\n```\n\n###  ✔️ change animation center position\nIf you want to start animation somewhere other than the view that clicked, send a Coordinate object instead of a View in `ThemeManager.instance.changeTheme()`\n```kotlin\n   binder.lightButton.setOnClickListener {\n          binder.nightButton.setOnClickListener {\n            ThemeManager.instance.changeTheme(NightTheme(), Coordinate(10, 20)\n        }\n   }\n```\n\nwhere the Coordinate is:\n```kotlin\n Coordinate(var x: Int, var y: Int) \n```\n\n### ✔️ observe changes of themes yourself\nIf you want to observe changes of themes and do some custom action, you can use theme Livedata in any fragment or activity:\n\n```kotlin\n    ThemeManager.instance.getCurrentLiveTheme().observe(this) {\n        Toast.makeText(this, \"on Theme changed to ${it.id()}\", Toast.LENGTH_SHORT).show()\n    }\n```\n\n\n### ✔️ set animation listener\nIf you want to set an animation listener, use `setThemeAnimationListener()` method in your activity\n\n```kotlin\n     setThemeAnimationListener(MyThemeAnimationListener(this))\n```\nwhere the MyThemeAnimationListener is:\n\n```kotlin\n    class MyThemeAnimationListener(var context: Context) : ThemeAnimationListener{\n        override fun onAnimationStart(animation: Animator) {\n           Toast.makeText(context, \"onAnimationStart\", Toast.LENGTH_SHORT).show()\n        }\n\n        override fun onAnimationEnd(animation: Animator) {\n            Toast.makeText(context, \"onAnimationEnd\", Toast.LENGTH_SHORT).show()\n        }\n\n        override fun onAnimationCancel(animation: Animator) {\n            Toast.makeText(context, \"onAnimationCancel\", Toast.LENGTH_SHORT).show()\n        }\n\n        override fun onAnimationRepeat(animation: Animator) {\n            Toast.makeText(context, \"onAnimationRepeat\", Toast.LENGTH_SHORT).show()\n        }\n    }\n\n```\n# Stargazers\n[![Stargazers repo roster for @imandolatkia/Android-Animated-Theme-Manager](https://reporoster.com/stars/imandolatkia/Android-Animated-Theme-Manager)](https://github.com/imandolatkia/Android-Animated-Theme-Manager/stargazers)\n\n# Forkers\n[![Forkers repo roster for @imandolatkia/Android-Animated-Theme-Manager](https://reporoster.com/forks/imandolatkia/Android-Animated-Theme-Manager)](https://github.com/imandolatkia/Android-Animated-Theme-Manager/network/members)\n\n\n[![Quality gate](https://sonarcloud.io/api/project_badges/quality_gate?project=imandolatkia_Android-Animated-Theme-Manager)](https://sonarcloud.io/dashboard?id=imandolatkia_Android-Animated-Theme-Manager)\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fimandolatkia%2FAndroid-Animated-Theme-Manager","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fimandolatkia%2FAndroid-Animated-Theme-Manager","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fimandolatkia%2FAndroid-Animated-Theme-Manager/lists"}