{"id":19820334,"url":"https://github.com/faltenreich/skeletonlayout","last_synced_at":"2025-05-15T04:02:39.550Z","repository":{"id":39594059,"uuid":"122861982","full_name":"Faltenreich/SkeletonLayout","owner":"Faltenreich","description":"Skeleton view pattern for Android","archived":false,"fork":false,"pushed_at":"2025-01-30T19:45:24.000Z","size":5302,"stargazers_count":540,"open_issues_count":20,"forks_count":68,"subscribers_count":4,"default_branch":"develop","last_synced_at":"2025-04-06T23:11:17.571Z","etag":null,"topics":["android","progress","recyclerview","shimmer","skeleton","skeletonview"],"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/Faltenreich.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"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}},"created_at":"2018-02-25T18:08:04.000Z","updated_at":"2025-04-05T08:19:10.000Z","dependencies_parsed_at":"2024-12-13T16:12:17.569Z","dependency_job_id":"412d23cc-f982-488c-9bef-9c0c19ce1184","html_url":"https://github.com/Faltenreich/SkeletonLayout","commit_stats":null,"previous_names":[],"tags_count":9,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Faltenreich%2FSkeletonLayout","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Faltenreich%2FSkeletonLayout/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Faltenreich%2FSkeletonLayout/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Faltenreich%2FSkeletonLayout/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Faltenreich","download_url":"https://codeload.github.com/Faltenreich/SkeletonLayout/tar.gz/refs/heads/develop","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248819379,"owners_count":21166477,"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","progress","recyclerview","shimmer","skeleton","skeletonview"],"created_at":"2024-11-12T10:22:53.224Z","updated_at":"2025-04-14T03:58:46.622Z","avatar_url":"https://github.com/Faltenreich.png","language":"Kotlin","funding_links":[],"categories":[],"sub_categories":[],"readme":"# SkeletonLayout\n\n[![MavenCentral](https://maven-badges.herokuapp.com/maven-central/com.faltenreich/skeletonlayout/badge.svg?style=flat)](https://mvnrepository.com/artifact/com.faltenreich/skeletonlayout)\n\n*Make your app feel faster*\n\n\u003cimg src=\"./images/preview.gif\" alt=\"Animated showcase that illustrates alternating between normal view and skeleton\"\u003e\n\nUsers are time-sensitive and may skip an app due to long loading times and missing visual feedback. \nInstagram, Facebook, Google and other services tackled this problem with the so-called Skeleton View.\nThis view is being displayed during the process of fetching or requesting data asynchronously which leads to a perceivedly\nmore responsive app.\n\nThis library implements the Skeleton View pattern and provides an easy way for other developers to enable it in their apps. \n\n## Demo\n\n\u003ca href='https://play.google.com/store/apps/details?id=com.faltenreich.skeletonlayout\u0026pcampaignid=MKT-Other-global-all-co-prtnr-py-PartBadge-Mar2515-1'\u003e\u003cimg alt='Get it on Google Play' src='https://play.google.com/intl/en_us/badges/images/generic/en_badge_web_generic.png' width=\"250\"/\u003e\u003c/a\u003e\n\n## Preview\n\n\u003cimg src=\"./images/preview.png\" alt=\"Showcase that illustrates alternating between normal view and skeleton\"\u003e\n\nThe SkeletonLayout mimics the design of established implementations per default, but you are free to get creative. \nCreate your own skeleton view with custom shapes, colors and shimmers.\n\n\u003cimg src=\"./images/mask_square.png\" alt=\"Square mask\"\u003e\u0026nbsp;\n\u003cimg src=\"./images/mask_round.png\" alt=\"Rounded mask\"\u003e\u0026nbsp;\n\u003cimg src=\"./images/mask_color.png\" alt=\"Colored mask\"\u003e\n\n## Features\n\n- **Make your app feel faster:** Immediate visual feedback long before your data has been fetched or requested\n- **Support any View:** Apply to any type of View or ViewGroup\n- **RecyclerView on speed:** Convenience adapter for RecyclerView as it is the main use case\n- **ViewPager2 support:** Convenience adapter for ViewPager2 as it uses a RecyclerView under the hood\n- **Customization:** Adjust shimmer, color and shape of the skeleton to set you apart from other apps\n- **Minimum effort:** A fistful lines of code to use the SkeletonLayout\n- **Minimum footprint:** org.jetbrains.kotlin:kotlin-stdlib-jdk7, androidx.recyclerview:recyclerview and androidx.viewpager2.widget.ViewPager2 are the only dependencies\n\n### Getting Started\n\n##### Gradle\n```gradle\nbuildscript {\n    repositories {\n        mavenCentral()\n    }\n}\n```\n```gradle\ndependencies {\n    implementation 'com.faltenreich:skeletonlayout:\u003cversion\u003e'\n}\n```\n\n##### XML\n```xml\n\u003ccom.faltenreich.skeletonlayout.SkeletonLayout\n    android:id=\"@+id/skeletonLayout\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"wrap_content\"\u003e\n    \n    \u003c!-- Views to mask --\u003e\n    \n\u003c/com.faltenreich.skeletonlayout.SkeletonLayout\u003e\n```\n\n##### Kotlin\n```kotlin\nclass MainActivity : AppCompatActivity() {\n\n    private lateinit var skeleton: Skeleton\n\n    override fun onCreate(savedInstanceState: Bundle?) {\n        super.onCreate(savedInstanceState)\n        setContentView(R.layout.activity_main)\n\n        // Either use an existing Skeletonlayout\n        skeleton = findViewById(R.id.skeletonLayout)\n\n        // or create a new SkeletonLayout from a given View\n        skeleton = view.createSkeleton()\n\n        // and customize every detail including the layout used for the skeleton mask\n        skeleton = view.createSkeleton(config = SkeletonConfig.default(this, maskLayout = R.layout.custom_mask))\n        \n        // support ViewPager2\n        skeleton = viewPager2.applySkeleton(R.layout.list_item_viewpager2)\n\n        // support RecyclerView\n        skeleton = recyclerView.applySkeleton(R.layout.list_item_recyclerview)\n        \n        skeleton.showSkeleton()\n    }\n\n    // Example callback that hides skeleton\n    private fun onDataLoaded() {\n        skeleton.showOriginal()\n    }\n}\n```\n\n##### Java\n```java\npublic class MainActivity extends AppCompatActivity {\n    \n    private Skeleton skeleton;\n    \n    @Override\n    public void onCreate(@Nullable Bundle savedInstanceState) {\n        super.onCreate(savedInstanceState);\n        setContentView(R.layout.activity_main);\n        \n        // Either use an existing SkeletonLayout\n        skeleton = findViewById(R.id.skeletonLayout);\n        \n        // or create a new SkeletonLayout from a given View\n        skeleton = SkeletonLayoutUtils.createSkeleton(view);\n\n        // and customize every detail including the layout used for the skeleton mask\n        skeleton = SkeletonLayoutUtils.createSkeleton(view, SkeletonConfig.Companion.defaults(this, R.layout.custom_mask));\n\n        // support ViewPager2\n        skeleton = SkeletonLayoutUtils.applySkeleton(viewPager2, R.layout.list_item_viewpager2);\n\n        // support RecyclerView\n        skeleton = SkeletonLayoutUtils.applySkeleton(recyclerView, R.layout.list_item_recyclerview);\n\n        skeleton.showSkeleton();\n    }\n    \n    // Example callback that hides skeleton\n    private void onDataLoaded() {\n        skeleton.showOriginal();\n    }\n}\n```\n\n### Configuration\n\n| Property                | Type      | Description                                                                                                               |\n|-------------------------|-----------|---------------------------------------------------------------------------------------------------------------------------|\n| maskLayout              | reference | Optional reference to layout resource that should be masked when skeleton is applied (defaults to wrapped view if null)   |\n| maskColor               | color     | Color of the mask that fills the original view bounds (defaults to #E0E0E0)                                               |\n| maskCornerRadius        | dimension | The x- and y-radius of the oval used to round the mask corners (defaults to 25)                                           |\n| showShimmer             | boolean   | Animate shimmer if set to true (defaults to true)                                                                         |\n| shimmerColor            | color     | Color of the animated shimmer (defaults to #d5d5d5)                                                                       |\n| shimmerDurationInMillis | integer   | Duration in milliseconds for one shimmer animation interval (defaults to 2000)                                            |\n| shimmerDirection        | enum      | Direction of animated shimmer (defaults to LEFT_TO_RIGHT)                                                                 |\n| shimmerAngle            | integer   | Angle in degrees for animated shimmer (defaults to 0)                                                                     |\n| itemCount               | integer   | Item count for Skeleton adapter (RecyclerView and ViewPager2 only, defaults to 3)                                         |\n\n### FAQ\n\n**When and how is the skeleton created?**\nThe skeleton gets created after the original view's onLayout(), since we rely on it to be fully rendered in order to mask its bounds.\n\n**How does the masking work?**\nThe mask is drawn onto a single Bitmap by iterating once through the given Views and their bounds.\n\n**May properties of the SkeletonLayout be changed at runtime?**\nYes. Any change to the skeleton leads to a redraw, since the whole content of the SkeletonLayout gets drawn onto a single bitmap.\n\n**Will the shimmer eat my users' battery?**\nThe shimmer is a shader (LinearGradient) whose local matrix is updated according to the frame rate of the target device, \nso no redrawing is required and processing time is kept to an absolute minimum. \nAdditionally the shimmer gets inactive onWindowFocusChanged() and onDetachedFromWindow().\n\n### Third-party licenses\n\nThis software uses following technologies with great appreciation:\n\n* [AndroidX](https://developer.android.com/jetpack/androidx)\n* [ColorSlider](https://github.com/naz013/ColorSlider)\n* [gradle-maven-publish-plugin](https://github.com/vanniktech/gradle-maven-publish-plugin)\n* [Material Components for Android](https://material.io/components)\n\n### License\n\nCopyright 2025 Philipp Fahlteich\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n    http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n\n\u003cimg src=\"./images/android.png\" alt=\"\"\u003e ","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffaltenreich%2Fskeletonlayout","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffaltenreich%2Fskeletonlayout","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffaltenreich%2Fskeletonlayout/lists"}