├── app ├── .gitignore ├── src │ ├── main │ │ ├── res │ │ │ ├── mipmap-hdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-mdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-xhdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-xxhdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-xxxhdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-anydpi-v26 │ │ │ │ ├── ic_launcher.xml │ │ │ │ └── ic_launcher_round.xml │ │ │ ├── values │ │ │ │ ├── colors.xml │ │ │ │ ├── strings.xml │ │ │ │ └── styles.xml │ │ │ ├── drawable │ │ │ │ ├── ic_view_list_disable.xml │ │ │ │ ├── ic_view_list.xml │ │ │ │ ├── ic_view_module.xml │ │ │ │ ├── ic_view_module_disable.xml │ │ │ │ ├── view_toggle.xml │ │ │ │ └── ic_launcher_background.xml │ │ │ ├── drawable-v24 │ │ │ │ └── ic_launcher_foreground.xml │ │ │ └── layout │ │ │ │ ├── list_item_shimmer_grid.xml │ │ │ │ ├── list_item_shimmer_alternate.xml │ │ │ │ ├── list_item_shimmer.xml │ │ │ │ ├── list_item_shimmer_grid_alternate.xml │ │ │ │ ├── list_item_user_grid.xml │ │ │ │ ├── list_item_user.xml │ │ │ │ └── activity_example.xml │ │ ├── AndroidManifest.xml │ │ └── java │ │ │ └── com │ │ │ └── todkars │ │ │ ├── adapters │ │ │ ├── UserViewHolder.java │ │ │ └── UserAdapter.java │ │ │ ├── UserRetrievalTask.java │ │ │ ├── model │ │ │ └── User.java │ │ │ └── ExampleActivity.java │ ├── test │ │ └── java │ │ │ └── com │ │ │ └── todkars │ │ │ ├── ExampleTestActivity.kt │ │ │ └── ExampleUnitTest.kt │ └── androidTest │ │ └── java │ │ └── com │ │ └── todkars │ │ └── ExampleInstrumentedTest.kt ├── proguard-rules.pro └── build.gradle ├── shimmer ├── .gitignore ├── src │ └── main │ │ ├── AndroidManifest.xml │ │ ├── res │ │ ├── layout │ │ │ ├── recyclerview_shimmer_viewholder_layout.xml │ │ │ ├── recyclerview_shimmer_item_grid.xml │ │ │ └── recyclerview_shimmer_item_list.xml │ │ └── values │ │ │ └── attrs.xml │ │ └── java │ │ └── com │ │ └── todkars │ │ └── shimmer │ │ ├── ShimmerViewHolder.java │ │ ├── ShimmerAdapter.java │ │ └── ShimmerRecyclerView.java ├── proguard-rules.pro ├── build.gradle └── bintray-config.gradle ├── settings.gradle ├── demo ├── grid-demo.gif ├── list-demo.gif └── list-grid-demo.gif ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── .idea ├── compiler.xml ├── vcs.xml ├── runConfigurations.xml ├── modules.xml └── jarRepositories.xml ├── .github └── ISSUE_TEMPLATE │ ├── feature_request.md │ └── bug_report.md ├── gradle.properties ├── .travis.yml ├── RELEASES.md ├── gradlew.bat ├── .gitignore ├── gradlew ├── README.md └── LICENSE.md /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /shimmer/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app', ':shimmer' -------------------------------------------------------------------------------- /demo/grid-demo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/omtodkar/ShimmerRecyclerView/HEAD/demo/grid-demo.gif -------------------------------------------------------------------------------- /demo/list-demo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/omtodkar/ShimmerRecyclerView/HEAD/demo/list-demo.gif -------------------------------------------------------------------------------- /demo/list-grid-demo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/omtodkar/ShimmerRecyclerView/HEAD/demo/list-grid-demo.gif -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/omtodkar/ShimmerRecyclerView/HEAD/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/omtodkar/ShimmerRecyclerView/HEAD/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/omtodkar/ShimmerRecyclerView/HEAD/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /shimmer/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/omtodkar/ShimmerRecyclerView/HEAD/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/omtodkar/ShimmerRecyclerView/HEAD/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/omtodkar/ShimmerRecyclerView/HEAD/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/omtodkar/ShimmerRecyclerView/HEAD/app/src/main/res/mipmap-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/omtodkar/ShimmerRecyclerView/HEAD/app/src/main/res/mipmap-mdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/omtodkar/ShimmerRecyclerView/HEAD/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/omtodkar/ShimmerRecyclerView/HEAD/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/omtodkar/ShimmerRecyclerView/HEAD/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Wed Mar 24 21:15:20 IST 2021 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-6.5-all.zip 7 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #008577 4 | #00574B 5 | #D81B60 6 | 7 | #03CCCC 8 | #E6F5F4 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | Shimmer RecyclerView 3 | 4 | List 5 | Grid 6 | 7 | Reload 8 | 9 | Show Shimmer 10 | Hide Shimmer 11 | 12 | -------------------------------------------------------------------------------- /app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_view_list_disable.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_view_list.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_view_module.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_view_module_disable.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/test/java/com/todkars/ExampleTestActivity.kt: -------------------------------------------------------------------------------- 1 | package com.todkars 2 | 3 | import com.todkars.model.User 4 | 5 | class ExampleTestActivity : ExampleActivity() { 6 | 7 | // For test purpose only. 8 | interface TestCallback { 9 | 10 | fun onResultReceived(users: List) 11 | } 12 | 13 | var callback: TestCallback? = null 14 | 15 | // notify test cases when async task returns result. 16 | override fun onResult(users: MutableList?) { 17 | super.onResult(users) 18 | callback?.onResultReceived(users?.toList()!!) 19 | } 20 | } -------------------------------------------------------------------------------- /.idea/runConfigurations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | -------------------------------------------------------------------------------- /shimmer/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/view_toggle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /shimmer/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | apply plugin: 'com.github.dcendents.android-maven' 3 | apply plugin: 'com.jfrog.bintray' 4 | 5 | android { 6 | compileSdkVersion 30 7 | 8 | defaultConfig { 9 | minSdkVersion 14 10 | targetSdkVersion 30 11 | 12 | versionCode 1 13 | versionName "0.4.1" 14 | 15 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 16 | 17 | } 18 | 19 | buildTypes { 20 | release { 21 | minifyEnabled false 22 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' 23 | } 24 | } 25 | 26 | } 27 | 28 | dependencies { 29 | implementation fileTree(dir: 'libs', include: ['*.jar']) 30 | 31 | implementation 'androidx.annotation:annotation:1.1.0' 32 | implementation 'androidx.recyclerview:recyclerview:1.1.0' 33 | implementation 'com.facebook.shimmer:shimmer:0.5.0' 34 | } 35 | 36 | apply from: 'bintray-config.gradle' -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior: 15 | 1. Go to '...' 16 | 2. Click on '....' 17 | 3. Scroll down to '....' 18 | 4. See error 19 | 20 | **Expected behavior** 21 | A clear and concise description of what you expected to happen. 22 | 23 | **Screenshots** 24 | If applicable, add screenshots to help explain your problem. 25 | 26 | **Desktop (please complete the following information):** 27 | - OS: [e.g. iOS] 28 | - Browser [e.g. chrome, safari] 29 | - Version [e.g. 22] 30 | 31 | **Smartphone (please complete the following information):** 32 | - Device: [e.g. iPhone6] 33 | - OS: [e.g. iOS8.1] 34 | - Browser [e.g. stock browser, safari] 35 | - Version [e.g. 22] 36 | 37 | **Additional context** 38 | Add any other context about the problem here. 39 | -------------------------------------------------------------------------------- /shimmer/src/main/res/layout/recyclerview_shimmer_viewholder_layout.xml: -------------------------------------------------------------------------------- 1 | 19 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle shimmer. 2 | # IDE (e.g. Android Studio) users: 3 | # Gradle shimmer configured through the IDE *will override* 4 | # any shimmer specified in this file. 5 | 6 | # For more details on how to configure your build environment visit 7 | # http://www.gradle.org/docs/current/userguide/build_environment.html 8 | # Specifies the JVM arguments used for the daemon process. 9 | # The setting is particularly useful for tweaking memory shimmer. 10 | org.gradle.jvmargs=-Xmx1536m 11 | 12 | # When configured, Gradle will run in incubating parallel mode. 13 | # This option should only be used with decoupled projects. More details, visit 14 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 15 | # org.gradle.parallel=true 16 | 17 | # AndroidX package structure to make it clearer which packages are bundled with the 18 | # Android operating system, and which are packaged with your app's APK 19 | # https://developer.android.com/topic/libraries/support-library/androidx-rn 20 | android.useAndroidX=true 21 | 22 | # Automatically convert third-party libraries to use AndroidX 23 | android.enableJetifier=true 24 | 25 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: android 2 | sudo: required 3 | jdk: oraclejdk8 4 | dist: trusty 5 | 6 | android: 7 | components: 8 | # Use the latest revision of Android SDK Tools 9 | - tools 10 | - platform-tools 11 | 12 | # The BuildTools version used by your project 13 | - build-tools-30.0.3 14 | 15 | # The SDK version used to compile your project 16 | - android-30 17 | 18 | # Additional components 19 | - extra-google-m2repository 20 | - extra-android-m2repository 21 | licenses: 22 | - 'android-sdk-preview-license-52d11cd2' 23 | - 'android-sdk-license-.+' 24 | - 'google-gdk-license-.+' 25 | 26 | before_install: 27 | - touch $HOME/.android/repositories.cfg 28 | - yes | sdkmanager "platforms;android-30" 29 | - yes | sdkmanager "build-tools;30.0.3" 30 | 31 | before_cache: 32 | - rm -f $HOME/.gradle/caches/modules-2/modules-2.lock 33 | - rm -fr $HOME/.gradle/caches/*/plugin-resolution/ 34 | 35 | cache: 36 | directories: 37 | - $HOME/.gradle/caches/ 38 | - $HOME/.gradle/wrapper/ 39 | - $HOME/.android/build-cache 40 | 41 | before_script: 42 | - touch local.properties 43 | - chmod +x gradlew 44 | 45 | script: 46 | - ./gradlew clean build --stacktrace 47 | - ./gradlew test --info 48 | -------------------------------------------------------------------------------- /.idea/jarRepositories.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 9 | 10 | 14 | 15 | 19 | 20 | 24 | 25 | 29 | 30 | -------------------------------------------------------------------------------- /app/src/main/java/com/todkars/adapters/UserViewHolder.java: -------------------------------------------------------------------------------- 1 | /* 2 | ShimmerRecyclerView a custom RecyclerView library 3 | Copyright (C) 2019 Omkar Todkar 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see below link 17 | https://github.com/omtodkar/ShimmerRecyclerView/blob/master/LICENSE.md 18 | */ 19 | package com.todkars.adapters; 20 | 21 | import com.todkars.BR; 22 | import com.todkars.model.User; 23 | 24 | import androidx.databinding.ViewDataBinding; 25 | import androidx.recyclerview.widget.RecyclerView; 26 | 27 | class UserViewHolder extends RecyclerView.ViewHolder { 28 | 29 | private final ViewDataBinding binder; 30 | 31 | UserViewHolder(ViewDataBinding binder) { 32 | super(binder.getRoot()); 33 | this.binder = binder; 34 | } 35 | 36 | void bind(User user) { 37 | binder.setVariable(BR.user, user); 38 | binder.executePendingBindings(); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /RELEASES.md: -------------------------------------------------------------------------------- 1 | # ShimmerRecyclerView 2 | 3 | ShimmerRecyclerView is an custom RecyclerView library based on Facebook's [Shimmer](https://github.com/facebook/shimmer-android) effect for Android library 4 | 5 | ### v0.4.1 6 | - Upgrade all dependencies to latest. 7 | 8 | ### v0.4.0 9 | - Linear Horizontal Recyclerview bug fixed. 10 | 11 | ### v0.3.0 12 | Now you can set xml attributes for shimmer layout reference and number of shimmer to be shown while loading. Also now you can able to change view type of `ShimmerAdapter`. 13 | 14 | - New `ItemViewType` contract to setup viewType for `ShimmerAdapter` based on `layoutType` and `position`, use `ShimmerRecyclerView.setItemViewType`. 15 | - Use `shimmer_recycler_layout` xml attribute to set shimmer layout reference. 16 | - Use `shimmer_recycler_item_count` xml attribute to set number of shimmer items. 17 | 18 | ### v0.2.0 19 | 20 | Bug fixes and minor changes. 21 | 22 | - Now use `setLayoutManager(androidx.recyclerview.widget.RecyclerView.LayoutManager, int)` to setup layout manager and shimmer layout resource together. 23 | - `com.todkars.shimmer.ShimmerAdapter` is now accessible. 24 | - Added support for Vertical / Horizontal `GridLayoutManager`. 25 | 26 | ### v0.1.0 27 | 28 | Pre release. 29 | 30 | - use `showShimmer` and `hideShimmer` to toggle shimmer view. 31 | - Auto-detect layout type and orientation while showing shimmer. 32 | - Setup own Shimmer using `ShimmerRecyclerView#setShimmer(com.facebook.shimmer.Shimmer)` to customize for ShimmerRecyclerView. 33 | - All xml attributes are similar as facebook `ShimmerLayout`. 34 | -------------------------------------------------------------------------------- /shimmer/src/main/java/com/todkars/shimmer/ShimmerViewHolder.java: -------------------------------------------------------------------------------- 1 | /* 2 | ShimmerRecyclerView a custom RecyclerView library 3 | Copyright (C) 2019 Omkar Todkar 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see below link 17 | https://github.com/omtodkar/ShimmerRecyclerView/blob/master/LICENSE.md 18 | */ 19 | package com.todkars.shimmer; 20 | 21 | import androidx.annotation.NonNull; 22 | import androidx.recyclerview.widget.RecyclerView; 23 | 24 | import com.facebook.shimmer.Shimmer; 25 | import com.facebook.shimmer.ShimmerFrameLayout; 26 | 27 | final class ShimmerViewHolder extends RecyclerView.ViewHolder { 28 | 29 | private final ShimmerFrameLayout mShimmer; 30 | 31 | ShimmerViewHolder(@NonNull ShimmerFrameLayout itemView) { 32 | super(itemView); 33 | this.mShimmer = itemView; 34 | } 35 | 36 | /** 37 | * Updates shimmer properties 38 | */ 39 | final void bindView(Shimmer shimmer) { 40 | mShimmer.setShimmer(shimmer).startShimmer(); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /app/src/androidTest/java/com/todkars/ExampleInstrumentedTest.kt: -------------------------------------------------------------------------------- 1 | /* 2 | ShimmerRecyclerView a custom RecyclerView library 3 | Copyright (C) 2019 Omkar Todkar 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see below link 17 | https://github.com/omtodkar/ShimmerRecyclerView/blob/master/LICENSE.md 18 | */ 19 | package com.todkars 20 | 21 | import androidx.test.ext.junit.runners.AndroidJUnit4 22 | import androidx.test.platform.app.InstrumentationRegistry 23 | import org.junit.Assert.assertEquals 24 | import org.junit.Test 25 | import org.junit.runner.RunWith 26 | 27 | /** 28 | * Instrumented test, which will execute on an Android device. 29 | * 30 | * @see [Testing documentation](http://d.android.com/tools/testing) 31 | */ 32 | @RunWith(AndroidJUnit4::class) 33 | class ExampleInstrumentedTest { 34 | 35 | @Test 36 | fun useAppContext() { 37 | // Context of the app under test. 38 | val appContext = InstrumentationRegistry.getInstrumentation() 39 | .targetContext 40 | 41 | assertEquals("com.todkars", appContext.packageName) 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /shimmer/src/main/res/layout/recyclerview_shimmer_item_grid.xml: -------------------------------------------------------------------------------- 1 | 19 | 24 | 25 | 29 | 30 | 35 | 36 | 41 | 42 | 47 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-v24/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 7 | 12 | 13 | 19 | 22 | 25 | 26 | 27 | 28 | 34 | 35 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | apply plugin: 'kotlin-android' 3 | apply plugin: 'kotlin-parcelize' 4 | apply plugin: 'kotlin-kapt' 5 | 6 | android { 7 | compileSdkVersion 30 8 | 9 | defaultConfig { 10 | applicationId "com.todkars" 11 | 12 | minSdkVersion 14 13 | targetSdkVersion 30 14 | 15 | versionCode 1 16 | versionName "1.0" 17 | 18 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 19 | } 20 | 21 | buildFeatures { 22 | dataBinding = true 23 | } 24 | 25 | buildTypes { 26 | release { 27 | minifyEnabled false 28 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' 29 | } 30 | } 31 | 32 | testOptions { 33 | unitTests.includeAndroidResources = true 34 | } 35 | 36 | compileOptions { 37 | sourceCompatibility = '1.8' 38 | targetCompatibility = '1.8' 39 | } 40 | } 41 | 42 | dependencies { 43 | implementation fileTree(dir: 'libs', include: ['*.jar']) 44 | implementation project(':shimmer') 45 | 46 | implementation 'androidx.core:core-ktx:1.5.0-beta03' 47 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" 48 | 49 | implementation 'androidx.appcompat:appcompat:1.3.0-beta01' 50 | implementation 'androidx.constraintlayout:constraintlayout:2.1.0-beta01' 51 | implementation 'androidx.recyclerview:recyclerview:1.2.0-beta02' 52 | 53 | implementation 'com.google.code.gson:gson:2.8.6' 54 | 55 | implementation 'com.facebook.shimmer:shimmer:0.5.0' 56 | 57 | /* Test Dependencies */ 58 | testImplementation 'junit:junit:4.13.2' 59 | 60 | testImplementation 'androidx.test:core-ktx:1.4.0-alpha05' 61 | testImplementation 'com.google.truth:truth:1.1.2' 62 | 63 | testImplementation 'org.mockito:mockito-core:3.8.0' 64 | testImplementation 'org.robolectric:robolectric:4.5.1' 65 | 66 | androidTestImplementation 'androidx.test.ext:junit:1.1.2' 67 | 68 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0' 69 | androidTestImplementation 'androidx.test.espresso:espresso-contrib:3.3.0' 70 | } 71 | -------------------------------------------------------------------------------- /shimmer/src/main/res/layout/recyclerview_shimmer_item_list.xml: -------------------------------------------------------------------------------- 1 | 19 | 23 | 24 | 30 | 31 | 38 | 39 | 43 | 44 | 49 | 50 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /app/src/main/java/com/todkars/UserRetrievalTask.java: -------------------------------------------------------------------------------- 1 | /* 2 | ShimmerRecyclerView a custom RecyclerView library 3 | Copyright (C) 2019 Omkar Todkar 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see below link 17 | https://github.com/omtodkar/ShimmerRecyclerView/blob/master/LICENSE.md 18 | */ 19 | package com.todkars; 20 | 21 | import android.content.Context; 22 | import android.os.AsyncTask; 23 | 24 | import com.google.gson.Gson; 25 | import com.google.gson.reflect.TypeToken; 26 | import com.todkars.model.User; 27 | 28 | import java.io.BufferedReader; 29 | import java.io.InputStream; 30 | import java.io.InputStreamReader; 31 | import java.lang.ref.WeakReference; 32 | import java.util.Collections; 33 | import java.util.List; 34 | 35 | public class UserRetrievalTask extends AsyncTask> { 36 | private final WeakReference context; 37 | 38 | interface UserRetrievalResult { 39 | 40 | void onResult(List users); 41 | } 42 | 43 | private final UserRetrievalResult result; 44 | 45 | UserRetrievalTask(Context context, UserRetrievalResult result) { 46 | this.context = new WeakReference<>(context.getApplicationContext()); 47 | this.result = result; 48 | } 49 | 50 | @Override 51 | protected List doInBackground(Void... voids) { 52 | if (context.get() != null) { 53 | InputStream dataStream = context.get().getResources().openRawResource(R.raw.mock_data); 54 | BufferedReader reader = new BufferedReader(new InputStreamReader(dataStream)); 55 | List users = new Gson().fromJson(reader, new TypeToken>() { 56 | }.getType()); 57 | Collections.shuffle(users); 58 | return users; 59 | } else return Collections.emptyList(); 60 | } 61 | 62 | @Override 63 | protected void onPostExecute(List users) { 64 | super.onPostExecute(users); 65 | if (result != null) result.onResult(users); 66 | } 67 | 68 | } 69 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | set DIRNAME=%~dp0 12 | if "%DIRNAME%" == "" set DIRNAME=. 13 | set APP_BASE_NAME=%~n0 14 | set APP_HOME=%DIRNAME% 15 | 16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 17 | set DEFAULT_JVM_OPTS= 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windows variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | 53 | :win9xME_args 54 | @rem Slurp the command line arguments. 55 | set CMD_LINE_ARGS= 56 | set _SKIP=2 57 | 58 | :win9xME_args_slurp 59 | if "x%~1" == "x" goto execute 60 | 61 | set CMD_LINE_ARGS=%* 62 | 63 | :execute 64 | @rem Setup the command line 65 | 66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 67 | 68 | @rem Execute Gradle 69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 70 | 71 | :end 72 | @rem End local scope for the variables with windows NT shell 73 | if "%ERRORLEVEL%"=="0" goto mainEnd 74 | 75 | :fail 76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 77 | rem the _cmd.exe /c_ return code! 78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 79 | exit /b 1 80 | 81 | :mainEnd 82 | if "%OS%"=="Windows_NT" endlocal 83 | 84 | :omega 85 | -------------------------------------------------------------------------------- /app/src/main/java/com/todkars/adapters/UserAdapter.java: -------------------------------------------------------------------------------- 1 | /* 2 | ShimmerRecyclerView a custom RecyclerView library 3 | Copyright (C) 2019 Omkar Todkar 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see below link 17 | https://github.com/omtodkar/ShimmerRecyclerView/blob/master/LICENSE.md 18 | */ 19 | package com.todkars.adapters; 20 | 21 | import android.view.LayoutInflater; 22 | import android.view.ViewGroup; 23 | 24 | import com.todkars.R; 25 | import com.todkars.model.User; 26 | 27 | import java.util.ArrayList; 28 | import java.util.Collections; 29 | import java.util.List; 30 | 31 | import androidx.annotation.NonNull; 32 | import androidx.databinding.DataBindingUtil; 33 | import androidx.databinding.ViewDataBinding; 34 | import androidx.recyclerview.widget.RecyclerView; 35 | 36 | public class UserAdapter extends RecyclerView.Adapter { 37 | 38 | private boolean grid = false; 39 | 40 | private List users; 41 | 42 | public UserAdapter() { 43 | this.users = Collections.emptyList(); 44 | } 45 | 46 | @NonNull 47 | @Override 48 | public UserViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { 49 | ViewDataBinding binder = DataBindingUtil.inflate(LayoutInflater.from(parent.getContext()), grid 50 | ? R.layout.list_item_user_grid : R.layout.list_item_user, parent, false); 51 | return new UserViewHolder(binder); 52 | } 53 | 54 | @Override 55 | public void onBindViewHolder(@NonNull UserViewHolder holder, int position) { 56 | holder.bind(users.get(position)); 57 | } 58 | 59 | @Override 60 | public int getItemCount() { 61 | return users != null ? users.size() : 0; 62 | } 63 | 64 | public void updateData(List users) { 65 | this.users = new ArrayList<>(users); 66 | notifyDataSetChanged(); 67 | } 68 | 69 | /** 70 | * On changing layout orientation. 71 | * 72 | * @param grid change to list or grid layout. 73 | */ 74 | public void changeOrientation(boolean grid) { 75 | this.grid = grid; 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /shimmer/bintray-config.gradle: -------------------------------------------------------------------------------- 1 | ext { 2 | developerId = 'omtodkar' 3 | developerName = 'Omkar Todkar' 4 | developerEmail = 'omtodkar@gmail.com' 5 | } 6 | 7 | Properties properties = new Properties() 8 | properties.load(project.rootProject.file('local.properties').newDataInputStream()) 9 | 10 | group = properties.getProperty("bintray.group") 11 | version = properties.getProperty("bintray.version") 12 | 13 | install { 14 | repositories.mavenInstaller { 15 | pom.project { 16 | packaging 'aar' 17 | groupId properties.getProperty("bintray.group") 18 | artifactId properties.getProperty("bintray.artifact") 19 | 20 | name properties.getProperty("bintray.name") 21 | description properties.getProperty("bintray.library.description") 22 | url properties.getProperty("bintray.library.site") 23 | 24 | developers { 25 | developer { 26 | id developerId 27 | name developerName 28 | email developerEmail 29 | } 30 | } 31 | 32 | scm { 33 | connection properties.getProperty("bintray.library.repo") 34 | developerConnection properties.getProperty("bintray.library.repo") 35 | url properties.getProperty("bintray.library.site") 36 | } 37 | } 38 | } 39 | } 40 | 41 | task sourcesJar(type: Jar) { 42 | classifier = 'sources' 43 | from android.sourceSets.main.java.srcDirs 44 | } 45 | 46 | task javadoc(type: Javadoc) { 47 | source = android.sourceSets.main.java.srcDirs 48 | classpath += project.files(android.getBootClasspath().join(File.pathSeparator)) 49 | } 50 | 51 | task javadocJar(type: Jar, dependsOn: javadoc) { 52 | classifier = 'javadoc' 53 | from javadoc.destinationDir 54 | } 55 | 56 | artifacts { 57 | // archives javadocJar 58 | archives sourcesJar 59 | } 60 | 61 | bintray { 62 | user = properties.getProperty("bintray.user") 63 | key = properties.getProperty("bintray.apikey") 64 | 65 | configurations = ['archives'] 66 | 67 | pkg { 68 | repo = properties.getProperty("bintray.repo") 69 | name = properties.getProperty("bintray.name") 70 | userOrg = properties.getProperty("bintray.org") 71 | 72 | desc = properties.getProperty("bintray.library.description") 73 | websiteUrl = properties.getProperty("bintray.library.site") 74 | vcsUrl = properties.getProperty("bintray.library.repo") 75 | 76 | dryRun = false 77 | publish = true 78 | override = false 79 | publicDownloadNumbers = true 80 | 81 | version { 82 | desc = properties.getProperty("bintray.library.description") 83 | } 84 | } 85 | } -------------------------------------------------------------------------------- /shimmer/src/main/res/values/attrs.xml: -------------------------------------------------------------------------------- 1 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /app/src/main/res/layout/list_item_shimmer_grid.xml: -------------------------------------------------------------------------------- 1 | 19 | 23 | 24 | 37 | 38 | 51 | 52 | 66 | 67 | 80 | -------------------------------------------------------------------------------- /app/src/main/res/layout/list_item_shimmer_alternate.xml: -------------------------------------------------------------------------------- 1 | 19 | 24 | 25 | 33 | 34 | 46 | 47 | 60 | 61 | 74 | 75 | 88 | -------------------------------------------------------------------------------- /app/src/main/res/layout/list_item_shimmer.xml: -------------------------------------------------------------------------------- 1 | 19 | 24 | 25 | 33 | 34 | 46 | 47 | 60 | 61 | 74 | 75 | 88 | -------------------------------------------------------------------------------- /app/src/main/res/layout/list_item_shimmer_grid_alternate.xml: -------------------------------------------------------------------------------- 1 | 19 | 24 | 25 | 32 | 33 | 43 | 44 | 55 | 56 | 67 | 68 | 77 | 78 | 87 | 88 | 96 | -------------------------------------------------------------------------------- /app/src/main/java/com/todkars/model/User.java: -------------------------------------------------------------------------------- 1 | /* 2 | ShimmerRecyclerView a custom RecyclerView library 3 | Copyright (C) 2019 Omkar Todkar 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see below link 17 | https://github.com/omtodkar/ShimmerRecyclerView/blob/master/LICENSE.md 18 | */ 19 | package com.todkars.model; 20 | 21 | import com.google.gson.annotations.SerializedName; 22 | 23 | import androidx.annotation.NonNull; 24 | 25 | public class User implements Comparable { 26 | 27 | private int id; 28 | 29 | @SerializedName("first_name") 30 | private String firstName; 31 | 32 | @SerializedName("last_name") 33 | private String lastName; 34 | 35 | private String email; 36 | 37 | @SerializedName("ip_address") 38 | private String ipAddress; 39 | 40 | public User() { 41 | } 42 | 43 | public User(int id, String firstName, String lastName, String email, String ipAddress) { 44 | this.id = id; 45 | this.firstName = firstName; 46 | this.lastName = lastName; 47 | this.email = email; 48 | this.ipAddress = ipAddress; 49 | } 50 | 51 | public int getId() { 52 | return id; 53 | } 54 | 55 | public void setId(int id) { 56 | this.id = id; 57 | } 58 | 59 | public String getFirstName() { 60 | return firstName; 61 | } 62 | 63 | public void setFirstName(String firstName) { 64 | this.firstName = firstName; 65 | } 66 | 67 | public String getLastName() { 68 | return lastName; 69 | } 70 | 71 | public void setLastName(String lastName) { 72 | this.lastName = lastName; 73 | } 74 | 75 | public String getEmail() { 76 | return email; 77 | } 78 | 79 | public void setEmail(String email) { 80 | this.email = email; 81 | } 82 | 83 | public String getIpAddress() { 84 | return ipAddress; 85 | } 86 | 87 | public void setIpAddress(String ipAddress) { 88 | this.ipAddress = ipAddress; 89 | } 90 | 91 | @Override 92 | public int compareTo(User o) { 93 | //noinspection UseCompareMethod 94 | return (getId() < o.getId()) ? -1 : ((getId() == o.getId()) ? 0 : 1); 95 | } 96 | 97 | @Override 98 | public boolean equals(Object o) { 99 | if (this == o) return true; 100 | if (o == null || getClass() != o.getClass()) return false; 101 | 102 | User user = (User) o; 103 | 104 | if (id != user.id) return false; 105 | if (firstName != null ? !firstName.equals(user.firstName) : user.firstName != null) 106 | return false; 107 | if (lastName != null ? !lastName.equals(user.lastName) : user.lastName != null) 108 | return false; 109 | if (email != null ? !email.equals(user.email) : user.email != null) return false; 110 | return ipAddress != null ? ipAddress.equals(user.ipAddress) : user.ipAddress == null; 111 | } 112 | 113 | @Override 114 | public int hashCode() { 115 | int result = id; 116 | result = 31 * result + (firstName != null ? firstName.hashCode() : 0); 117 | result = 31 * result + (lastName != null ? lastName.hashCode() : 0); 118 | result = 31 * result + (email != null ? email.hashCode() : 0); 119 | result = 31 * result + (ipAddress != null ? ipAddress.hashCode() : 0); 120 | return result; 121 | } 122 | 123 | @NonNull 124 | @Override 125 | public String toString() { 126 | return "User {" + 127 | "id=" + id + 128 | ", firstName='" + firstName + '\'' + 129 | ", lastName='" + lastName + '\'' + 130 | ", email='" + email + '\'' + 131 | ", ipAddress='" + ipAddress + '\'' + 132 | '}'; 133 | } 134 | } 135 | -------------------------------------------------------------------------------- /app/src/main/res/layout/list_item_user_grid.xml: -------------------------------------------------------------------------------- 1 | 2 | 20 | 23 | 24 | 25 | 26 | 29 | 30 | 31 | 32 | 35 | 36 | 54 | 55 | 72 | 73 | 89 | 90 | 104 | 105 | -------------------------------------------------------------------------------- /app/src/main/res/layout/list_item_user.xml: -------------------------------------------------------------------------------- 1 | 19 | 22 | 23 | 24 | 25 | 28 | 29 | 30 | 33 | 34 | 52 | 53 | 70 | 71 | 88 | 89 | 103 | 104 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ### Gradle template 2 | .gradle 3 | build/ 4 | 5 | # Ignore Gradle GUI config 6 | gradle-app.setting 7 | 8 | # Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored) 9 | !/gradle/wrapper/gradle-wrapper.jar 10 | 11 | # Cache of project 12 | .gradletasknamecache 13 | 14 | # # Work around https://youtrack.jetbrains.com/issue/IDEA-116898 15 | # gradle/wrapper/gradle-wrapper.properties 16 | 17 | ### JetBrains template 18 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm 19 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 20 | 21 | # User-specific stuff: 22 | .idea/misc.xml 23 | .idea/**/workspace.xml 24 | .idea/**/tasks.xml 25 | .idea/dictionaries 26 | .idea/dbnavigator.xml 27 | .idea/inspectionProfiles/ 28 | .idea/caches 29 | .idea/codeStyles 30 | .idea/assetWizardSettings.xml 31 | .idea/encodings.xml 32 | .idea/runConfigurations 33 | 34 | # Sensitive or high-churn files: 35 | .idea/**/dataSources/ 36 | .idea/**/dataSources.ids 37 | .idea/**/dataSources.xml 38 | .idea/**/dataSources.local.xml 39 | .idea/**/sqlDataSources.xml 40 | .idea/**/dynamic.xml 41 | .idea/**/uiDesigner.xml 42 | .idea/GitScope.xml 43 | 44 | # Gradle: 45 | .idea/**/gradle.xml 46 | .idea/**/libraries 47 | 48 | # CMake 49 | cmake-build-debug/ 50 | cmake-build-release/ 51 | 52 | # Mongo Explorer plugin: 53 | .idea/**/mongoSettings.xml 54 | 55 | ## File-based project format: 56 | *.iws 57 | 58 | ## Plugin-specific files: 59 | 60 | # IntelliJ 61 | out/ 62 | 63 | # mpeltonen/sbt-idea plugin 64 | .idea_modules/ 65 | 66 | # JIRA plugin 67 | atlassian-ide-plugin.xml 68 | 69 | # Cursive Clojure plugin 70 | .idea/replstate.xml 71 | 72 | # Crashlytics plugin (for Android Studio and IntelliJ) 73 | com_crashlytics_export_strings.xml 74 | crashlytics.properties 75 | crashlytics-build.properties 76 | fabric.properties 77 | 78 | ### Android template 79 | # Built application files 80 | *.apk 81 | *.ap_ 82 | 83 | # Files for the ART/Dalvik VM 84 | *.dex 85 | 86 | # Java class files 87 | *.class 88 | 89 | # Generated files 90 | bin/ 91 | gen/ 92 | 93 | # Local configuration file (sdk path, etc) 94 | local.properties 95 | 96 | # Proguard folder generated by Eclipse 97 | proguard/ 98 | 99 | # Log Files 100 | *.log 101 | 102 | # Android Studio Navigation editor temp files 103 | .navigation/ 104 | 105 | # Android Studio captures folder 106 | captures/ 107 | 108 | # IntelliJ 109 | *.iml 110 | .idea/tasks.xml 111 | 112 | # Keystore files 113 | # Uncomment the following line if you do not want to check your keystore files in. 114 | #*.jks 115 | 116 | # External native build folder generated in Android Studio 2.2 and later 117 | .externalNativeBuild 118 | 119 | # Google Services (e.g. APIs or Firebase) 120 | google-services.json 121 | 122 | # Freeline 123 | freeline.py 124 | freeline/ 125 | freeline_project_description.json 126 | 127 | ### Linux template 128 | *~ 129 | 130 | # temporary files which can be created if a process still has a handle open of a deleted file 131 | .fuse_hidden* 132 | 133 | # KDE directory preferences 134 | .directory 135 | 136 | # Linux trash folder which might appear on any partition or disk 137 | .Trash-* 138 | 139 | # .nfs files are created when an open file is removed but is still being accessed 140 | .nfs* 141 | 142 | ### Windows template 143 | # Windows thumbnail cache files 144 | Thumbs.db 145 | ehthumbs.db 146 | ehthumbs_vista.db 147 | 148 | # Dump file 149 | *.stackdump 150 | 151 | # Folder config file 152 | [Dd]esktop.ini 153 | 154 | # Recycle Bin used on file shares 155 | $RECYCLE.BIN/ 156 | 157 | # Windows Installer files 158 | *.cab 159 | *.msi 160 | *.msm 161 | *.msp 162 | 163 | # Windows shortcuts 164 | *.lnk 165 | 166 | ### Kotlin template 167 | # Compiled class file 168 | 169 | # Log file 170 | 171 | # BlueJ files 172 | *.ctxt 173 | 174 | # Mobile Tools for Java (J2ME) 175 | .mtj.tmp/ 176 | 177 | # Package Files # 178 | *.war 179 | *.ear 180 | *.zip 181 | *.tar.gz 182 | *.rar 183 | 184 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 185 | hs_err_pid* 186 | 187 | ### macOS template 188 | # General 189 | .DS_Store 190 | .AppleDouble 191 | .LSOverride 192 | 193 | # Icon must end with two \r 194 | Icon 195 | 196 | # Thumbnails 197 | ._* 198 | 199 | # Files that might appear in the root of a volume 200 | .DocumentRevisions-V100 201 | .fseventsd 202 | .Spotlight-V100 203 | .TemporaryItems 204 | .Trashes 205 | .VolumeIcon.icns 206 | .com.apple.timemachine.donotpresent 207 | 208 | # Directories potentially created on remote AFP share 209 | .AppleDB 210 | .AppleDesktop 211 | Network Trash Folder 212 | Temporary Items 213 | .apdisk 214 | 215 | # Markdown Navigator plugin 216 | *markdown** 217 | 218 | # Release mapping files 219 | /release 220 | 221 | # Studio Plugins 222 | .idea/sonarlint/ 223 | .idea/*-idea.xml 224 | .idea/kotlinc.xml 225 | .idea/sonar*.xml 226 | .idea/statistic.xml 227 | -------------------------------------------------------------------------------- /shimmer/src/main/java/com/todkars/shimmer/ShimmerAdapter.java: -------------------------------------------------------------------------------- 1 | /* 2 | ShimmerRecyclerView a custom RecyclerView library 3 | Copyright (C) 2019 Omkar Todkar 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see below link 17 | https://github.com/omtodkar/ShimmerRecyclerView/blob/master/LICENSE.md 18 | */ 19 | package com.todkars.shimmer; 20 | 21 | import android.view.LayoutInflater; 22 | import android.view.View; 23 | import android.view.ViewGroup; 24 | 25 | import androidx.annotation.LayoutRes; 26 | import androidx.annotation.NonNull; 27 | import androidx.recyclerview.widget.RecyclerView; 28 | 29 | import com.facebook.shimmer.Shimmer; 30 | import com.facebook.shimmer.ShimmerFrameLayout; 31 | import com.todkars.shimmer.ShimmerRecyclerView.LayoutType; 32 | 33 | public final class ShimmerAdapter extends RecyclerView.Adapter { 34 | 35 | /** 36 | * A contract to change shimmer view type. 37 | */ 38 | public interface ItemViewType { 39 | 40 | @LayoutRes 41 | int getItemViewType(@LayoutType int layoutManagerType, int position); 42 | } 43 | 44 | private Shimmer shimmer; 45 | 46 | @LayoutRes 47 | private int layout; 48 | 49 | private int itemCount; 50 | 51 | private int layoutManagerType; 52 | 53 | private ItemViewType itemViewType; 54 | 55 | 56 | @RecyclerView.Orientation 57 | private int mLayoutOrientation; 58 | 59 | 60 | ShimmerAdapter(@LayoutRes int layout, int itemCount, int layoutManagerType, 61 | ItemViewType itemViewType, Shimmer shimmer, int layoutOrientation) { 62 | this.layout = layout; 63 | this.itemCount = validateCount(itemCount); 64 | this.layoutManagerType = layoutManagerType; 65 | this.itemViewType = itemViewType; 66 | this.shimmer = shimmer; 67 | this.mLayoutOrientation = layoutOrientation; 68 | } 69 | 70 | @Override 71 | public int getItemViewType(int position) { 72 | return (itemViewType != null) 73 | ? itemViewType.getItemViewType(layoutManagerType, position) 74 | : layout; /* default */ 75 | } 76 | 77 | @NonNull 78 | @Override 79 | public ShimmerViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { 80 | LayoutInflater inflater = LayoutInflater.from(parent.getContext()); 81 | /* inflate view holder layout and then attach provided view in it. */ 82 | View view = inflater.inflate(R.layout.recyclerview_shimmer_viewholder_layout, 83 | parent, false); 84 | 85 | if (mLayoutOrientation == RecyclerView.HORIZONTAL) { 86 | view.getLayoutParams().width = ViewGroup.LayoutParams.WRAP_CONTENT; 87 | } 88 | 89 | return new ShimmerViewHolder((ShimmerFrameLayout) inflater 90 | .inflate(viewType, (ShimmerFrameLayout) view, 91 | true /* attach to view holder layout */)); 92 | } 93 | 94 | @Override 95 | public void onBindViewHolder(@NonNull ShimmerViewHolder holder, int position) { 96 | holder.bindView(shimmer); 97 | } 98 | 99 | @Override 100 | public int getItemCount() { 101 | return itemCount; 102 | } 103 | 104 | /////////////////////////////////////////////////////////////////////////// 105 | // Internal APIs 106 | /////////////////////////////////////////////////////////////////////////// 107 | 108 | void setShimmer(Shimmer shimmer) { 109 | this.shimmer = shimmer; 110 | } 111 | 112 | void setLayout(@LayoutRes int layout) { 113 | this.layout = layout; 114 | } 115 | 116 | void setCount(int count) { 117 | this.itemCount = validateCount(count); 118 | } 119 | 120 | void setShimmerItemViewType(@LayoutType int layoutManagerType, ItemViewType itemViewType) { 121 | this.layoutManagerType = layoutManagerType; 122 | this.itemViewType = itemViewType; 123 | } 124 | 125 | /** 126 | * Validates if provided item count is greater than reasonable number 127 | * of items and returns max number of items allowed. 128 | *

129 | * Try to save memory produced by shimmer layouts. 130 | * 131 | * @param count input number. 132 | * @return valid count number. 133 | */ 134 | private int validateCount(int count) { 135 | return count < 20 ? count : 20; 136 | } 137 | } 138 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_example.xml: -------------------------------------------------------------------------------- 1 | 19 | 23 | 24 | 25 | 26 | 29 | 30 | 33 | 34 | 35 | 38 | 39 | 45 | 46 | 61 | 62 |