Skip to content
This repository was archived by the owner on Dec 22, 2023. It is now read-only.

Commit e573438

Browse files
committed
* [u] Gradle wrapper to 5.1.1 from 4.4
* [u] Kotlin from `1.3.41` to `1.2.50` * [M] Making Compile SDK to 28 * [M] Migrating `AppCompat` usage to `AndroidX` * [u] Android Gradle plugin to `3.4.1` from `3.1.3` * [r] Bumped library version to `0.1.2-alpha` * [r] Fixing lint errors on RecyclerViewFastScroller.kt
1 parent bd786c2 commit e573438

File tree

19 files changed

+138
-133
lines changed

19 files changed

+138
-133
lines changed

build.gradle

Lines changed: 7 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
// Top-level build file where you can add configuration options common to all sub-projects/modules.
22

33
buildscript {
4-
ext.kotlin_version = '1.2.50'
4+
ext.kotlin_version = '1.3.41'
55
ext.versions = [
6-
'compileSdk': 27,
7-
'buildTools': '27.0.3',
6+
'compileSdk': 28,
7+
'buildTools': '28.0.3',
88
'minSdk': 19,
99
'targetSdk': 27,
1010
'supportLibrary': '27.1.1',
@@ -13,26 +13,19 @@ buildscript {
1313
]
1414
ext.deps = [
1515
'gson':"com.google.code.gson:gson:${versions.gson}",
16-
'constraintLayout': "com.android.support.constraint:constraint-layout:${versions.constraintLayout}",
16+
'constraintLayout': 'androidx.constraintlayout:constraintlayout:1.1.3',
1717
'support': [
18-
'annotations': "com.android.support:support-annotations:${versions.supportLibrary}",
19-
'v4': "com.android.support:support-v4:${versions.supportLibrary}",
20-
'appCompat': "com.android.support:appcompat-v7:${versions.supportLibrary}",
21-
'design': "com.android.support:design:${versions.supportLibrary}",
22-
'recyclerView': "com.android.support:recyclerview-v7:${versions.supportLibrary}",
23-
'cardView': "com.android.support:cardview-v7:${versions.supportLibrary}",
18+
'appCompat': 'androidx.appcompat:appcompat:1.0.0',
19+
'recyclerView': 'androidx.recyclerview:recyclerview:1.0.0',
2420
]
2521
]
2622
repositories {
2723
google()
2824
jcenter()
2925
}
3026
dependencies {
31-
classpath 'com.android.tools.build:gradle:3.1.3'
27+
classpath 'com.android.tools.build:gradle:3.4.1'
3228
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
33-
34-
// NOTE: Do not place your application dependencies here; they belong
35-
// in the individual module build.gradle files
3629
}
3730
}
3831

gradle.properties

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,15 @@ org.gradle.jvmargs=-Xmx1536m
1111
# This option should only be used with decoupled projects. More details, visit
1212
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
1313
# org.gradle.parallel=true
14+
android.useAndroidX=true
15+
android.enableJetifier=true
1416

15-
VERSION_NAME=0.1.1-alpha
16-
VERSION_CODE=1
17+
# Nexus related information
18+
# ref: https://github.com/chrisbanes/gradle-mvn-push and
19+
# ref2: https://chris.banes.dev/2013/08/27/pushing-aars-to-maven-central/
20+
21+
VERSION_NAME=0.1.2
22+
VERSION_CODE=2
1723
GROUP=com.quiph.ui
1824

1925
POM_DESCRIPTION=A modern implementation of the RecyclerViewFastScroller for Android written in Kotlin
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
#Tue Jun 26 19:01:24 IST 2018
1+
#Mon Jul 08 17:07:02 IST 2019
22
distributionBase=GRADLE_USER_HOME
33
distributionPath=wrapper/dists
44
zipStoreBase=GRADLE_USER_HOME
55
zipStorePath=wrapper/dists
6-
distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-all.zip
6+
distributionUrl=https\://services.gradle.org/distributions/gradle-5.1.1-all.zip

recyclerviewfastscroller/build.gradle

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ android {
99
versionCode 1
1010
versionName "1.0-alpha"
1111

12-
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
12+
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
1313

1414
}
1515

@@ -26,16 +26,16 @@ dependencies {
2626
implementation fileTree(dir: 'libs', include: ['*.jar'])
2727

2828
// kotlin runtime
29-
implementation 'org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.2.50'
29+
implementation 'org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.3.41'
3030

3131
// support libs
32-
implementation deps.support.recyclerView
33-
implementation deps.support.appCompat
32+
implementation 'androidx.recyclerview:recyclerview:1.1.0-beta01'
33+
implementation 'androidx.appcompat:appcompat:1.1.0-rc01'
3434

3535
// testing libs
36-
testImplementation 'junit:junit:4.12'
37-
androidTestImplementation 'com.android.support.test:runner:1.0.2'
38-
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
36+
testImplementation 'junit:junit:4.13-beta-3'
37+
androidTestImplementation 'androidx.test:runner:1.3.0-alpha01'
38+
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0-alpha01'
3939
}
4040
repositories {
4141
mavenCentral()

recyclerviewfastscroller/src/main/java/com/qtalk/recyclerviewfastscroller/RecyclerViewFastScroller.kt

Lines changed: 36 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
* See the License for the specific language governing permissions and
1414
* limitations under the License.
1515
*/
16+
@file:Suppress("unused", "MemberVisibilityCanBePrivate")
17+
1618
package com.qtalk.recyclerviewfastscroller
1719

1820
import android.animation.Animator
@@ -21,12 +23,12 @@ import android.content.Context
2123
import android.content.res.TypedArray
2224
import android.graphics.Rect
2325
import android.graphics.drawable.Drawable
24-
import android.support.annotation.*
25-
import android.support.v4.content.ContextCompat
26-
import android.support.v4.widget.TextViewCompat
27-
import android.support.v7.widget.AppCompatImageView
28-
import android.support.v7.widget.LinearLayoutManager
29-
import android.support.v7.widget.RecyclerView
26+
import androidx.annotation.*
27+
import androidx.core.content.ContextCompat
28+
import androidx.core.widget.TextViewCompat
29+
import androidx.appcompat.widget.AppCompatImageView
30+
import androidx.recyclerview.widget.LinearLayoutManager
31+
import androidx.recyclerview.widget.RecyclerView
3032
import android.util.AttributeSet
3133
import android.util.Log
3234
import android.view.Gravity
@@ -37,6 +39,10 @@ import android.view.ViewPropertyAnimator
3739
import android.widget.LinearLayout
3840
import android.widget.RelativeLayout
3941
import android.widget.TextView
42+
import kotlin.math.abs
43+
import kotlin.math.max
44+
import kotlin.math.min
45+
import kotlin.math.roundToInt
4046

4147
/**
4248
* Sets a custom scroller for [RecyclerView].
@@ -213,7 +219,7 @@ class RecyclerViewFastScroller @JvmOverloads constructor(
213219
alignPopupLayout()
214220

215221
// if not defined, set default popupTextView background
216-
popupTextView.background = if (attribs.hasValue(R.styleable.RecyclerViewFastScroller_popupDrawable) == true){
222+
popupTextView.background = if (attribs.hasValue(R.styleable.RecyclerViewFastScroller_popupDrawable)){
217223
loadDrawableFromAttribs(R.styleable.RecyclerViewFastScroller_popupDrawable)
218224
}else{
219225
ContextCompat.getDrawable(context, Defaults.popupDrawableInt)
@@ -268,13 +274,12 @@ class RecyclerViewFastScroller @JvmOverloads constructor(
268274
if (!adapterDataObserver.isInitialized()){
269275
registerDataObserver()
270276
}
271-
checkNotNull(recyclerView) { ERROR_MESSAGE_NO_RECYCLER_VIEW }
272277

273278
//compute relative touch offset only on DOWN and use the same for MOVE events
274279
touchRelativeOffset = motionEvent.rawY - yAbsPosition - handleImageView.y
275280

276281
//check if offset is in bounds
277-
if (Math.abs(touchRelativeOffset)>handleImageView.height) touchRelativeOffset = 0f
282+
if (abs(touchRelativeOffset) >handleImageView.height) touchRelativeOffset = 0f
278283

279284
//set the engaged flag to prevent the handle from scrolling again as the OnScrolled event in the ScrollListener is called even for programmatic scrolls
280285
isEngaged = true
@@ -300,7 +305,7 @@ class RecyclerViewFastScroller @JvmOverloads constructor(
300305
if (motionEvent.action == MotionEvent.ACTION_MOVE){
301306
handleStateListener?.onDragged(handleImageView.y, position)
302307
}
303-
updateTextInPopup(Math.min((recyclerView.adapter.itemCount)-1, position))
308+
updateTextInPopup(min((recyclerView.adapter?.itemCount ?: 0) -1, position))
304309
}else{
305310
recyclerView.scrollBy(0, currentRelativeYPos.toInt())
306311
}
@@ -382,7 +387,7 @@ class RecyclerViewFastScroller @JvmOverloads constructor(
382387
* @param finalOffset the offset to move to
383388
* */
384389
private fun moveViewByRelativeYInBounds(view: View, finalOffset: Float){
385-
view.y = Math.min(Math.max(finalOffset, 0f), (height.toFloat()-view.height.toFloat()))
390+
view.y = min(max(finalOffset, 0f), (height.toFloat()-view.height.toFloat()))
386391
}
387392

388393
/**
@@ -448,9 +453,11 @@ class RecyclerViewFastScroller @JvmOverloads constructor(
448453
* else uses the standard [RecyclerView.LayoutManager.scrollToPosition] method. The offset in [LinearLayoutManager] is the position where the view should be after scrolling relative to the [RecyclerView]
449454
* */
450455
private fun RecyclerView.safeScrollToPosition(position: Int){
451-
when(this.layoutManager){
452-
is LinearLayoutManager -> (this.layoutManager as LinearLayoutManager).scrollToPositionWithOffset(position,0)
453-
is RecyclerView.LayoutManager -> this.layoutManager.scrollToPosition(position)
456+
with(this.layoutManager){
457+
when(this){
458+
is LinearLayoutManager -> scrollToPositionWithOffset(position,0)
459+
is RecyclerView.LayoutManager -> scrollToPosition(position)
460+
}
454461
}
455462
}
456463

@@ -475,17 +482,17 @@ class RecyclerViewFastScroller @JvmOverloads constructor(
475482
if (totalVisibleItems == RecyclerView.NO_POSITION) return RecyclerView.NO_POSITION
476483

477484
// the last item would have one less visible item, this is to offset it.
478-
previousTotalVisibleItem = Math.max(previousTotalVisibleItem, totalVisibleItems)
485+
previousTotalVisibleItem = max(previousTotalVisibleItem, totalVisibleItems)
479486
//check bounds and then set position
480-
val position = Math.min(recyclerViewItemCount, Math.max(0, Math.round(newOffset * (recyclerViewItemCount - totalVisibleItems))))
487+
val position = min(recyclerViewItemCount, max(0, (newOffset * (recyclerViewItemCount - totalVisibleItems)).roundToInt()))
481488

482-
val toScrollPosition = Math.min((this.adapter?.itemCount?:0)-(previousTotalVisibleItem+1), position)
489+
val toScrollPosition = min((this.adapter?.itemCount?:0)-(previousTotalVisibleItem+1), position)
483490
safeScrollToPosition(toScrollPosition)
484491
return position
485492
}
486493
else -> {
487494

488-
val position = Math.round(newOffset * recyclerViewItemCount)
495+
val position = (newOffset * recyclerViewItemCount).roundToInt()
489496
safeScrollToPosition(position)
490497
return position
491498
}
@@ -498,26 +505,23 @@ class RecyclerViewFastScroller @JvmOverloads constructor(
498505
private fun updateTextInPopup(position: Int){
499506
if (position !in 0 until (recyclerView.adapter?.itemCount?:1)) { return }
500507

501-
val adapter = recyclerView.adapter
502-
when (adapter){
508+
when (val adapter = recyclerView.adapter){
509+
null -> {throw IllegalAccessException("No adapter found, if you have an adapter then try placing if before calling the attachFastScrollerToRecyclerView() method")}
503510
is OnPopupTextUpdate -> popupTextView.text =adapter.onChange(position).toString()
504511
is OnPopupViewUpdate -> {adapter.onUpdate(position, popupTextView)}
505-
null -> {throw IllegalAccessException("No adapter found, if you have an adapter then try placing if before calling the attachFastScrollerToRecyclerView() method")}
506512
else -> { throw IllegalAccessException("Should implement the OnPopupTextUpdate or OnPopupViewUpdate interface")}
507513
}
508514
}
509515

510516
private val emptySpaceItemDecoration by lazy {
511517
object : RecyclerView.ItemDecoration() {
512518

513-
override fun getItemOffsets(outRect: Rect, view: View, parent: RecyclerView, state: RecyclerView.State?) {
519+
override fun getItemOffsets(outRect: Rect, view: View, parent: RecyclerView, state: RecyclerView.State) {
514520
super.getItemOffsets(outRect, view, parent, state)
515-
516-
if (parent.getChildAdapterPosition(view) == parent.adapter.itemCount - 1) {
521+
if (parent.getChildAdapterPosition(view) == parent.adapter?.itemCount ?: 0 - 1) {
517522
val currentVisiblePos: Int = (recyclerView.layoutManager as LinearLayoutManager).findFirstVisibleItemPosition()
518523
if (currentVisiblePos != RecyclerView.NO_POSITION) {
519-
outRect.bottom = (parent.findViewHolderForAdapterPosition(currentVisiblePos)?.itemView?.height
520-
?: 0)
524+
outRect.bottom = (parent.findViewHolderForAdapterPosition(currentVisiblePos)?.itemView?.height ?: 0)
521525
}
522526
}
523527
}
@@ -548,13 +552,12 @@ class RecyclerViewFastScroller @JvmOverloads constructor(
548552
recyclerView.adapter?.registerAdapterDataObserver(adapterDataObserver.value)
549553
}
550554
private val onScrollListener = object : RecyclerView.OnScrollListener() {
551-
override fun onScrolled(recyclerView: RecyclerView?, dx: Int, dy: Int) {
555+
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
552556
super.onScrolled(recyclerView, dx, dy)
553557
if (isEngaged && isFastScrollEnabled) return
554558

555-
val computeVerticalScrollExtent: Float = recyclerView?.computeVerticalScrollExtent()?.toFloat()
556-
?: 0f
557-
val computeVerticalScrollRange : Float = recyclerView?.computeVerticalScrollRange()?.toFloat() ?: 1f
559+
val computeVerticalScrollExtent: Float = recyclerView.computeVerticalScrollExtent().toFloat()
560+
val computeVerticalScrollRange : Float = recyclerView.computeVerticalScrollRange().toFloat()
558561

559562
// check if the layout is scrollable. i.e. range is large than extent, else disable fastscrolling and track touches.
560563
if (computeVerticalScrollExtent<computeVerticalScrollRange){
@@ -567,8 +570,7 @@ class RecyclerViewFastScroller @JvmOverloads constructor(
567570
handleImageView.isEnabled = false
568571
return
569572
}
570-
val offsetScale = ((recyclerView?.computeVerticalScrollOffset()?.toFloat() ?: 0f)) /
571-
((computeVerticalScrollRange) - (computeVerticalScrollExtent))
573+
val offsetScale = (recyclerView.computeVerticalScrollOffset().toFloat()) / ((computeVerticalScrollRange) - (computeVerticalScrollExtent))
572574
val finalOffset = offsetScale * (computeVerticalScrollExtent - handleImageView.height.toFloat())
573575
moveViewByRelativeYInBounds(handleImageView, finalOffset)
574576
moveViewByRelativeYInBounds(popupTextView, finalOffset - popupTextView.height.toFloat())
@@ -618,7 +620,7 @@ class RecyclerViewFastScroller @JvmOverloads constructor(
618620
* */
619621
@Keep
620622
fun attachFastScrollerToRecyclerView(recyclerView: RecyclerView){
621-
this.recyclerView = requireNotNull(recyclerView) { ERROR_MESSAGE_NO_RECYCLER_VIEW }
623+
this.recyclerView = recyclerView
622624
initImpl()
623625
}
624626
/**
@@ -629,6 +631,7 @@ class RecyclerViewFastScroller @JvmOverloads constructor(
629631
* @see attachFastScrollerToRecyclerView
630632
* @since 1.0
631633
**/
634+
@SuppressLint("ClickableViewAccessibility")
632635
fun detachFastScrollerFromRecyclerView(){
633636
// unregister the observer to prevent memory leaks only if initialized
634637
if (adapterDataObserver.isInitialized()){

sample/build.gradle

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,10 @@ android {
77
applicationId "com.qtalk.sample"
88
minSdkVersion versions.'minSdk'
99
targetSdkVersion versions.'targetSdk'
10-
versionCode 1
11-
versionName "1.0"
10+
versionCode 2
11+
versionName "1.1"
1212

13-
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
13+
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
1414

1515
}
1616

@@ -28,13 +28,13 @@ dependencies {
2828
implementation project(':recyclerviewfastscroller')
2929
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
3030
implementation deps.gson
31-
implementation deps.support.appCompat
32-
implementation deps.support.recyclerView
31+
implementation 'androidx.appcompat:appcompat:1.1.0-rc01'
32+
implementation 'androidx.recyclerview:recyclerview:1.1.0-beta01'
3333

34-
implementation deps.constraintLayout
34+
implementation 'androidx.constraintlayout:constraintlayout:2.0.0-beta2'
3535

36-
implementation 'com.android.support:support-v4:27.1.1'
37-
testImplementation 'junit:junit:4.12'
38-
androidTestImplementation 'com.android.support.test:runner:1.0.2'
39-
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
36+
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
37+
testImplementation 'junit:junit:4.13-beta-3'
38+
androidTestImplementation 'androidx.test:runner:1.3.0-alpha01'
39+
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0-alpha01'
4040
}

sample/src/main/java/com/qtalk/sample/MainActivity.kt

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
package com.qtalk.sample
22

33
import android.content.Context
4-
import android.support.v7.app.AppCompatActivity
4+
import androidx.appcompat.app.AppCompatActivity
55
import android.os.Bundle
6-
import android.support.v4.app.Fragment
7-
import android.support.v4.app.FragmentManager
8-
import android.support.v4.app.FragmentPagerAdapter
6+
import androidx.fragment.app.Fragment
7+
import androidx.fragment.app.FragmentManager
8+
import androidx.fragment.app.FragmentPagerAdapter
99
import com.qtalk.sample.fragments.AdvancedFragment
1010
import com.qtalk.sample.fragments.BasicFragment
1111
import com.qtalk.sample.fragments.ContactsFragment
@@ -15,24 +15,25 @@ class MainActivity : AppCompatActivity() {
1515

1616
companion object {
1717
private const val VIEWPAGER_COUNT = 3
18+
private const val PAGE_INDEX_BASIC = 0
19+
private const val PAGE_INDEX_ADVANCE = 1
20+
private const val PAGE_INDEX_CONTACTS = 2
1821
}
1922
override fun onCreate(savedInstanceState: Bundle?) {
2023
super.onCreate(savedInstanceState)
2124
setContentView(R.layout.activity_main)
2225
view_pager.adapter = ViewPagerAdapter(supportFragmentManager, this)
2326
}
2427

25-
private class ViewPagerAdapter internal constructor(fm: FragmentManager?, val mContext: Context?) : FragmentPagerAdapter(fm) {
28+
private class ViewPagerAdapter internal constructor(fm: FragmentManager, val mContext: Context?) : FragmentPagerAdapter(fm, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT) {
2629
//internal ViewPagerAdapter class, with 3 fragments.
27-
28-
override fun getItem(position: Int): Fragment? {
29-
lateinit var fragment : Fragment
30-
when (position){
31-
0 -> fragment = BasicFragment()
32-
1 -> fragment = AdvancedFragment()
33-
2 -> fragment = ContactsFragment()
30+
override fun getItem(position: Int): Fragment {
31+
return when (position){
32+
PAGE_INDEX_BASIC -> BasicFragment()
33+
PAGE_INDEX_ADVANCE -> AdvancedFragment()
34+
PAGE_INDEX_CONTACTS -> ContactsFragment()
35+
else -> throw IllegalArgumentException("Not expecting $position.")
3436
}
35-
return fragment
3637
}
3738

3839
override fun getCount(): Int {
@@ -41,9 +42,9 @@ class MainActivity : AppCompatActivity() {
4142
// for the pageTitleStrip View at the top of the viewpager
4243
override fun getPageTitle(position: Int): CharSequence? {
4344
when(position){
44-
0 -> return mContext?.resources?.getString(R.string.basic_fragment)
45-
1 -> return mContext?.resources?.getString(R.string.advanced_fragment)
46-
2 -> return mContext?.resources?.getString(R.string.contacts_fragment)
45+
PAGE_INDEX_BASIC -> return mContext?.resources?.getString(R.string.basic_fragment)
46+
PAGE_INDEX_ADVANCE -> return mContext?.resources?.getString(R.string.advanced_fragment)
47+
PAGE_INDEX_CONTACTS -> return mContext?.resources?.getString(R.string.contacts_fragment)
4748
}
4849
return ""
4950
}

0 commit comments

Comments
 (0)