Skip to content

Commit

Permalink
Init commit
Browse files Browse the repository at this point in the history
  • Loading branch information
rommansabbir committed Aug 19, 2021
0 parents commit 443d2a9
Show file tree
Hide file tree
Showing 44 changed files with 1,340 additions and 0 deletions.
15 changes: 15 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
*.iml
.gradle
/local.properties
/.idea/caches
/.idea/libraries
/.idea/modules.xml
/.idea/workspace.xml
/.idea/navEditor.xml
/.idea/assetWizardSettings.xml
.DS_Store
/build
/captures
.externalNativeBuild
.cxx
local.properties
159 changes: 159 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
[![Release](https://jitpack.io/v/jitpack/android-example.svg)](https://jitpack.io/#rommansabbir/NetworkX)

# ⌛ LazyLoadingRecyclerView ⌛

An easy & lightweight library to implemented Lazy Loading/Infinite Scrolling/Pagination with RecyclerView
## Documentation

### Installation

Step 1. Add the JitPack repository to your build file .

```gradle
allprojects {
repositories {
maven { url 'https://jitpack.io' }
}
}
```

Step 2. Add the dependency.

```gradle
dependencies {
implementation 'com.github.rommansabbir:LazyLoadingRecyclerView:Tag'
}
```

---

### Version available

| Releases
| ------------- |
| 1.0.0 |


# Usages

### Step 1:
Attach `SpeedyLayoutManager` as the `LayoutManger` to the recycler view by calling this RecyclerView extension function `attachSpeedyLayoutManager()`

```kotlin
//Attach the SpeedyLayoutManager to the RecyclerView first
binding.rv.attachSpeedyLayoutManager(LinearLayoutManager.VERTICAL, false)
```

---

### Step 2:
Create an instance of `LazyLoadingRecyclerView` by calling static method `getInstance()`

```kotlin
private lateinit var lazyLoadingRecyclerView: LazyLoadingRecyclerView

override fun onCreate(savedInstanceState: Bundle?) {
.....
//Create an instance of LazyLoadingRecyclerView
lazyLoadingRecyclerView = LazyLoadingRecyclerView.getInstance()
}
```

---

### Step 3:
Implemented the `LazyLoadingRecyclerView.Listener` to the `Activity/Fragment` or Initialize as Anonymous listener.

```kotlin
MainActivity : AppCompatActivity(), LazyLoadingRecyclerView.Listener{
override fun loadMore() {
// Faking load more data request, infinite scrolling
}
}
```

or

```kotlin
private val listener = object : LazyLoadingRecyclerView.Listener{
override fun loadMore() {
// Faking load more data request, infinite scrolling
}
}
```
---

### Step 4:
Register the `RecyclerView` with `LazyLoadingRecyclerView.Listener` to `LazyLoadingRecyclerView` by calling this method `registerScrollListener()` when your `Activity/Fragment` is in `onResume` state.

```kotlin
override fun onResume() {
super.onResume()
// IMPORTANT - attach the listener `onResume()` state
lazyLoadingRecyclerView.registerScrollListener(binding.rv, this/listener)
}
```

---

### Step 5:
Remove the listener by calling this method `removeListener()` when your `Activity/Fragment` is in `onStop` state

```kotlin
override fun onStop() {
super.onStop()
// IMPORTANT - remove the listener `onStop` state
lazyLoadingRecyclerView.removeListener()
}
```

---

### Want to update `SmoothScroller` speed per pixel calculation?
You can update `LinearSmoothScroller`s `calculateSpeedPerPixel` by calling this method `SpeedyLinearLayoutManager.setMillisPerInch()`

````kotlin
SpeedyLinearLayoutManager.setMillisPerInch(5f)
````

---

### Want to update `LazyLoadingRecyclerView` handler delay time?
You can update `LazyLoadingRecyclerView`s handler delay time by calling this method `LazyLoadingRecyclerView.setHandlerDelayTime()`

````kotlin
LazyLoadingRecyclerView.setHandlerDelayTime(500)
````

---


### Checkout the sample app for the implementaion in detail

---

### Contact me

[Portfolio](https://www.rommansabbir.com/) | [LinkedIn](https://www.linkedin.com/in/rommansabbir/) | [Twitter](https://www.twitter.com/itzrommansabbir/) | [Facebook](https://www.facebook.com/itzrommansabbir/)

---

### License

[Apache Version 2.0](http://www.apache.org/licenses/LICENSE-2.0.html)

````html
Copyright (C) 2020 Romman Sabbir

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
````
1 change: 1 addition & 0 deletions app/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/build
1 change: 1 addition & 0 deletions app/LazyLoadingRecyclerView/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/build
44 changes: 44 additions & 0 deletions app/LazyLoadingRecyclerView/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
plugins {
id 'com.android.library'
id 'kotlin-android'
}

android {
compileSdk 31

defaultConfig {
minSdk 21
targetSdk 31
versionCode 1
versionName "1.0"

testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
consumerProguardFiles "consumer-rules.pro"
}

buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = '1.8'
}
}

dependencies {

implementation 'androidx.core:core-ktx:1.6.0'
implementation 'androidx.appcompat:appcompat:1.3.1'
implementation 'com.google.android.material:material:1.4.0'
testImplementation 'junit:junit:4.+'
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
implementation "androidx.core:core-ktx:+"
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
}
Empty file.
21 changes: 21 additions & 0 deletions app/LazyLoadingRecyclerView/proguard-rules.pro
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html

# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}

# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable

# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile
5 changes: 5 additions & 0 deletions app/LazyLoadingRecyclerView/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.rommansabbir.lazyloadingrecyclerview">

</manifest>
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package com.rommansabbir.lazyloadingrecyclerview

import android.os.Handler
import android.os.Looper
import androidx.recyclerview.widget.RecyclerView
import java.util.*

var handlerDelayTimer: Timer = Timer()

inline fun handlerPostDelayed(delay: Long, crossinline onSuccess: () -> Unit) {
handlerDelayTimer.cancel()
handlerDelayTimer = Timer()
handlerDelayTimer.schedule(object : TimerTask() {
override fun run() {
Handler(Looper.getMainLooper()).post {
onSuccess.invoke()
}
}
}, delay)
}

fun RecyclerView.attachSpeedyLayoutManager(orientation: Int, reverseLayout: Boolean) {
this.layoutManager = SpeedyLinearLayoutManager(this.context, orientation, reverseLayout)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
package com.rommansabbir.lazyloadingrecyclerview

import android.widget.AbsListView
import androidx.recyclerview.widget.RecyclerView

class LazyLoadingRecyclerView private constructor() {
private var isScrolling = false
private var currentItems = 0
private var totalItems: Int = 0
private var scrollOutItems: Int = 0

private lateinit var recyclerView: RecyclerView
private lateinit var layoutManager: SpeedyLinearLayoutManager

private var loadMoreListener: Listener? = null

companion object {
fun getInstance(): LazyLoadingRecyclerView {
return LazyLoadingRecyclerView()
}

private var HANDLER_DELAY: Long = 500

/**
* Set delay time for handler, must be in Millis
*
* @param value, Value to be set in [Long]
*/
fun setHandlerDelayTime(value: Long) {
HANDLER_DELAY = value
}
}


fun registerScrollListener(recyclerView: RecyclerView, listener: Listener) {
this.recyclerView = recyclerView
if (recyclerView.layoutManager == null) {
throw RuntimeException("LazyLoadingRecyclerView: Layout manager can not be null")
}
if (recyclerView.layoutManager!! is SpeedyLinearLayoutManager) {
this.layoutManager = recyclerView.layoutManager!! as SpeedyLinearLayoutManager
this.loadMoreListener = listener
recyclerView.addOnScrollListener(rvScrollListener)
} else {
throw RuntimeException("LazyLoadingRecyclerView: SpeedyLinearLayoutManager must be attached to the RecyclerView")
}
}

fun removeListener() {
recyclerView.removeOnScrollListener(rvScrollListener)
this.loadMoreListener = null
}

private val rvScrollListener = object : RecyclerView.OnScrollListener() {
override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
super.onScrollStateChanged(recyclerView, newState)
if (newState == AbsListView.OnScrollListener.SCROLL_STATE_TOUCH_SCROLL) {
isScrolling = true
}
}

override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
super.onScrolled(recyclerView, dx, dy)
handlerPostDelayed(HANDLER_DELAY) {
currentItems = layoutManager.childCount
totalItems = layoutManager.itemCount
scrollOutItems = layoutManager.findFirstVisibleItemPosition()
if (isScrolling && (currentItems + scrollOutItems == totalItems)) {
isScrolling = false
loadMoreListener?.loadMore()
}
}
}
}

interface Listener {
fun loadMore()
}
}
Loading

0 comments on commit 443d2a9

Please sign in to comment.