Kotlin users looking for a solution for a normal ScrollView
implementation:
As an extension to this answer, I created a custom view that solved my problems very well.
The view (create a new Kotlin file, maintain your package reference on line 1):
import android.annotation.SuppressLint
import android.content.Context
import android.util.AttributeSet
import android.view.MotionEvent
import android.widget.ScrollView
import kotlin.math.abs
class ScrollViewWithEndFunc (
context: Context?,
attrs: AttributeSet?,
defStyle: Int
) : ScrollView(context, attrs, defStyle) {
constructor(context: Context?) : this(context, null, 0) {}
constructor(context: Context?, attrs: AttributeSet?) : this(context, attrs, 0) {}
interface OnScrollListener {
fun onScrollChanged(scrollView: ScrollViewWithEndFunc?, x: Int, y: Int, oldX: Int, oldY: Int)
fun onEndScroll(scrollView: ScrollViewWithEndFunc?)
}
private var isScrolling = false
private var isTouching = false
private var scrollingRunnable: Runnable? = null
private var onScrollListener: OnScrollListener? = null
fun setOnScrollListener(onScrollListener: OnScrollListener) {
this.onScrollListener = onScrollListener
}
fun removeOnScrollListener() {
this.onScrollListener = null
}
@SuppressLint("ClickableViewAccessibility")
override fun onTouchEvent(ev: MotionEvent): Boolean {
val action = ev.action
if (action == MotionEvent.ACTION_MOVE) {
isTouching = true; isScrolling = true
} else if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) {
if (isTouching && !isScrolling) {
onScrollListener?.onEndScroll(this)
}
isTouching = false
}
return super.onTouchEvent(ev)
}
override fun onScrollChanged(x: Int, y: Int, oldX: Int, oldY: Int) {
super.onScrollChanged(x, y, oldX, oldY)
if (abs(oldY - y) > 0) {
scrollingRunnable?.let { removeCallbacks(it) }
scrollingRunnable = Runnable {
if (isScrolling && !isTouching) {
onScrollListener?.onEndScroll(this@ScrollViewWithEndFunc)
}
isScrolling = false
scrollingRunnable = null
}
postDelayed(scrollingRunnable, 200)
}
onScrollListener?.onScrollChanged(this, x, y, oldX, oldY)
}
}
XML view implementation:
<your.package.here.ScrollViewWithEndFunc
android:id="@+id/scrollview_main_dashboard"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true">
Activity/Fragment implementation:
scrollviewMainDashboard.setOnScrollListener(object : ScrollViewWithEndFunc.OnScrollListener {
override fun onScrollChanged(scrollView: ScrollViewWithEndFunc?, x: Int, y: Int, oldX: Int, oldY: Int) { }
override fun onEndScroll(scrollView: ScrollViewWithEndFunc?) {
/* Scroll ended, handle here */
})
onStart
will do the trick:hsv.getViewTreeObserver().addOnScrollChangedListener(new ViewTreeObserver.OnScrollChangedListener() {@Override public void onScrollChanged() {Log.i(TAG,"scroll:"+hsv.getScrollX());}});
in onStart() wherehsv
is aHorizontalScrollView
works. – JohnnyLambada