I have some TextViews
with drag and drop implemented in Kotlin and I what I would like to do is when I drag one TextView at the bottom of the screen, where a ScrollView
is located, for it to scroll downwards.
As it is shown in the image, I want to drag TextViews
from the left column (components) and drop then into the right column (boxes). The boxes LinearLayout
continues off screen, and the point is that I don't want the user to have to scroll to the last box before dragging something into it from the "components" LinearLayout.
So to answer my own question, the solution i found is this:
lowerLimForScroll = (Resources.getSystem().displayMetrics.heightPixels * 0.8).toInt()
textView.setOnDragListener { boxContentView, dragEvent ->
val boxesLayoutCoords = intArrayOf(0, 0)
// this calculates the x, y of the top left corner of the
// ScrollView
boxContentView.getLocationInWindow(boxesLayoutCoords)
when (dragEvent.action) {
DragEvent.ACTION_DRAG_LOCATION -> {
checkForScroll(dragEvent.y, boxesLayoutCoords[1])
}
true
}
likewise, i have to do add an on Drag Listener to the scrollView as well because i use dividers and the scrolling stopped when i got out of the scrollview and hovered over the divider which belongs to the ScrollView
scrollView.setOnDragListener { _, dragEvent ->
val boxesLayoutCoords = intArrayOf(0, 0)
scrollView.getLocationInWindow(boxesLayoutCoords)
when (dragEvent.action) {
DragEvent.ACTION_DRAG_LOCATION -> {
checkForScroll(dragEvent.y, boxesLayoutCoords[1])
}
}
true
}
and finally the checkForScroll function
private fun checkForScroll(pointerY: Float, startOfScrollView: Int) {
/* if the upper limit is passed, meaning a pixel height, scroll up */
if ((pointerY + startOfScrollView) < upperLimForScroll) {
findViewById<ScrollView>(R.id.boxesScrollView).smoothScrollBy(0, -20)
}
/* if the lower limit is passed, meaning a pixel height, scroll down */
else if (pointerY + startOfScrollView > lowerLimForScroll) {
findViewById<ScrollView>(R.id.boxesScrollView).smoothScrollBy(0, 15)
}
}