1

I have an activity where there are ImageViews as items in a ScrolView, this list will grow as time goes. What I want to do is when I swipe right on an item (imageView) it should navigate to another activity (let's say, orderActivity) where I can take further action. TextViews on orderActivity to be populated (details like, name of the item, price, quantity, etc) based on the item that is swiped right.

Following is the XML code, I don't have any idea how to code for the swipe right.

Is this the way it should be done, or is there a better way?

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".ListOfItems">

    <ScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:layout_editor_absoluteX="6dp"
        tools:layout_editor_absoluteY="1dp">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical" >

            <ImageView
                android:id="@+id/iVitemOne"
                android:layout_width="match_parent"
                android:layout_height="103dp"
                android:layout_marginTop="0dp"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintHorizontal_bias="0.4"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toTopOf="parent"
                app:srcCompat="@drawable/item1" />

            <ImageView
                android:id="@+id/iVitemTwo"
                android:layout_width="match_parent"
                android:layout_height="103dp"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintHorizontal_bias="0.0"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toBottomOf="@+id/iVitemOne"
                app:srcCompat="@drawable/item2" />

            <ImageView
                android:id="@+id/iVitemThree"
                android:layout_width="match_parent"
                android:layout_height="103dp"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintHorizontal_bias="0.0"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toBottomOf="@+id/iVitemTwo"
                app:srcCompat="@drawable/item3" />

            <ImageView
                android:id="@+id/iVitemFour"
                android:layout_width="match_parent"
                android:layout_height="103dp"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintHorizontal_bias="1.0"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toBottomOf="@+id/iVitemThree"
                app:srcCompat="@drawable/item4" />

        </LinearLayout>
    </ScrollView>


</androidx.constraintlayout.widget.ConstraintLayout>

I am on Android Studio using Kotlin.

Edit:

I added the Override part into the ListOfItems.kt file as follows. I know it's wrong.

class ListOfGames : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_list_of_games)
    }

    imageview.setOnTouchListener(object :OnSwipeTouchListener(context){
        override fun onSwipeRight() {
            //Do want you want
        }
    })

}
user3765415
  • 99
  • 1
  • 5
  • 17

2 Answers2

1

You can use this class (Kotlin version of another answer in Java)

 open class OnSwipeTouchListener(ctx: Context?) : OnTouchListener {
    private val gestureDetector: GestureDetector  = GestureDetector(ctx, GestureListener())

    override fun onTouch(v: View, event: MotionEvent): Boolean {
        return gestureDetector.onTouchEvent(event)
    }

    private inner class GestureListener : SimpleOnGestureListener() {
        private val SWIPE_THRESHOLD = 100
        private val SWIPE_VELOCITY_THRESHOLD = 100

        override fun onDown(e: MotionEvent): Boolean {
            return true
        }

        override fun onFling(e1: MotionEvent, e2: MotionEvent, velocityX: Float, velocityY: Float): Boolean {
            var result = false
            try {
                val diffY: Float = e2.y - e1.y
                val diffX: Float = e2.x - e1.x
                if (abs(diffX) > abs(diffY)) {
                    if (abs(diffX) > SWIPE_THRESHOLD && abs(velocityX) > SWIPE_VELOCITY_THRESHOLD) {
                        if (diffX > 0) {
                            onSwipeRight()
                        } else {
                            onSwipeLeft()
                        }
                        result = true
                    }
                } else if (abs(diffY) > SWIPE_THRESHOLD && abs(velocityY) > SWIPE_VELOCITY_THRESHOLD) {
                    if (diffY > 0) {
                        onSwipeBottom()
                    } else {
                        onSwipeTop()
                    }
                    result = true
                }
            } catch (exception: Exception) {
                exception.printStackTrace()
            }
            return result
        }
    }

    open fun onSwipeRight() {}
    open fun onSwipeLeft() {}
    open fun onSwipeTop() {}
    open fun onSwipeBottom() {}
}

and use it with your ImageViews like

iVitemOne.setOnTouchListener(object : OnSwipeTouchListener(requireContext()){
            override fun onSwipeRight() {
                super.onSwipeRight()

            }

            override fun onSwipeLeft() {
                super.onSwipeLeft()
            }
        })
ॐ Rakesh Kumar
  • 1,318
  • 1
  • 14
  • 24
Somesh Kumar
  • 8,088
  • 4
  • 33
  • 49
  • What needs to be at requireContext? – user3765415 Jan 02 '20 at 15:27
  • @user3765415 It just returns context from a fragment. If you are using Activity then you need to use `youractivityName.this` – Somesh Kumar Jan 03 '20 at 04:39
  • Error ListOfGames.kt file. `class ListOfGames : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_list_of_games) val iVitemOne=findViewById(R.id.iVFIFA20) iVitemOne.setOnTouchListener(object : OnSwipeTouchListener(MainActivity.this()){ override fun onSwipeRight() { super.onSwipeRight() } override fun onSwipeLeft() { super.onSwipeLeft() } }) } }` – user3765415 Jan 03 '20 at 05:43
  • you need to pass `this` instead of `MainActivity.this()` inside `OnSwipeTouchListener()` – Somesh Kumar Jan 03 '20 at 05:58
  • That fixed the error but nothing happens when I swipe right or left on the ImageView, iVFIFA20. There is a grey squiggly line that says "Custom view 'ImageView' has setOnTouchListener called on it but does not override performClick. Issue id: ClickableViewAccesibility. – user3765415 Jan 03 '20 at 08:37
  • 1
    It is working for me. Try adjusting `SWIPE_THRESHOLD ` value and see what fits for your need – Somesh Kumar Jan 03 '20 at 10:28
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/205289/discussion-between-user3765415-and-somesh-kumar). – user3765415 Jan 03 '20 at 10:56
0

Create OnSwipeTouchListener which is drived from View.OnTouchListener.This class help you to listern the left,right,top and bottom swipe.

class OnSwipeTouchListener(ctx: Context?) : OnTouchListener {
private val gestureDetector: GestureDetector
override fun onTouch(v: View, event: MotionEvent): Boolean {
    return gestureDetector.onTouchEvent(event)
}

private inner class GestureListener : SimpleOnGestureListener() {
    private  val SWIPE_THRESHOLD = 100
    private  val SWIPE_VELOCITY_THRESHOLD = 100
    override fun onDown(e: MotionEvent): Boolean {
        return true
    }

    override fun onFling(
        e1: MotionEvent,
        e2: MotionEvent,
        velocityX: Float,
        velocityY: Float
    ): Boolean {
        var result = false
        try {
            val diffY = e2.y - e1.y
            val diffX = e2.x - e1.x
            if (Math.abs(diffX) > Math.abs(diffY)) {
                if (Math.abs(diffX) > SWIPE_THRESHOLD && Math.abs(
                        velocityX
                    ) > SWIPE_VELOCITY_THRESHOLD
                ) {
                    if (diffX > 0) {
                        onSwipeRight()
                    } else {
                        onSwipeLeft()
                    }
                    result = true
                }
            } else if (Math.abs(diffY) > SWIPE_THRESHOLD && Math.abs(
                    velocityY
                ) > SWIPE_VELOCITY_THRESHOLD
            ) {
                if (diffY > 0) {
                    onSwipeBottom()
                } else {
                    onSwipeTop()
                }
                result = true
            }
        } catch (exception: Exception) {
            exception.printStackTrace()
        }
        return result
    } 
}

fun onSwipeRight() {}
fun onSwipeLeft() {}
fun onSwipeTop() {}
fun onSwipeBottom() {}

init {
    gestureDetector = GestureDetector(ctx, GestureListener())
}
}

Now you need to override this methods for your view.

  imageview.setOnTouchListener(object :OnSwipeTouchListener(context){
    override fun onSwipeRight() {
       //Do want you want
    }
})

That's it. I hope this will work for you.

Rahul sharma
  • 1,492
  • 12
  • 26
  • I think this is JAVA code, I am using Kotlin as mentioned in my question. – user3765415 Jan 02 '20 at 08:05
  • then you can covert that in kotlin not bigdeal. – Rahul sharma Jan 02 '20 at 08:07
  • I am just a beginner, I might do things incorrectly. What I did now is that I created a new class file with a name 'OnSwipeTouchListener' and added the first block of code into it and converted the code into Kotlin. Now I am left with a few errors. I do not know where and how to add the Override part, the second set of codes. – user3765415 Jan 02 '20 at 10:35
  • Updated code has no build errors, bravo. But I am still not able to use the code as I don't know how to use the second part, 'override'. I tried, but I do know if that is the right way to do it and I got errors. Can you tell me how to do the second part? – user3765415 Jan 02 '20 at 11:06
  • I added the Override part into the ListOfItems.kt file as follows. I know it's wrong. class ListOfGames : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_list_of_games) } imageview.setOnTouchListener(object :OnSwipeTouchListener(context){ override fun onSwipeRight() { //Do want you want } }) } – user3765415 Jan 02 '20 at 12:02
  • Update your question don't add as comment bcoz it is not understandable. And if it is not working for `recyclerview` then try this for any individual like `imageview` or `textview` – Rahul sharma Jan 02 '20 at 12:14
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/205227/discussion-between-user3765415-and-frankenstein). – user3765415 Jan 02 '20 at 12:31