Kotlin OnTouchListener called but it does not override performClick

Viewed 75978

How to override performClick in Kotlin to avoid warning?

next.setOnTouchListener(View.OnTouchListener { view, motionEvent ->
        when (motionEvent.action){
            MotionEvent.ACTION_DOWN -> {
                val icon: Drawable = ContextCompat.getDrawable(activity.applicationContext, R.drawable.layer_bt_next)
                icon.setColorFilter(Color.GRAY, PorterDuff.Mode.MULTIPLY)
                next.setImageDrawable(icon)
            }
            MotionEvent.ACTION_UP -> {
                //view.performClick()
                next.setImageResource(R.drawable.layer_bt_next)
            }
        }
        return@OnTouchListener true
    })

view.performClick does not work.

7 Answers

Try this way :

 next.setOnTouchListener(object : View.OnTouchListener {
        override fun onTouch(v: View?, event: MotionEvent?): Boolean {
            when (event?.action) {
                MotionEvent.ACTION_DOWN -> //Do Something
            }

            return v?.onTouchEvent(event) ?: true
        }
    })

Okay, I solved my own problem by overriding the OnTouch listener.

override fun onTouch(view: View, motionEvent: MotionEvent): Boolean {
    when (view) {
        next -> {
            Log.d("next", "yeyy")
            when (motionEvent.action){
                MotionEvent.ACTION_DOWN -> {
                    val icon: Drawable = ContextCompat.getDrawable(activity.applicationContext, R.drawable.layer_bt_next)
                    icon.setColorFilter(Color.GRAY, PorterDuff.Mode.MULTIPLY)
                    next.setImageDrawable(icon)
                }
                MotionEvent.ACTION_UP -> {
                    view.performClick()
                    next.setImageResource(R.drawable.layer_bt_next)
                }
            }
        }
        previous -> {
            //ingredients here XD
        }
    }
    return true
}

And in that way, I can call single onTouch and implement it to many button and also can use the onClick by :

view.performClick()

Don't forget to implement :

View.OnTouchListener

And set the listener :

next.setOnTouchListener(this)
previous.setOnTouchListener(this)

After a ton of digging, and not being able to fix my variation of this issue with anything in this thread, I finally found a fix. Maybe it will work for some of you. I had this widget listener setter in my MainActivity onCreate function:

findViewById<TextView>(R.id.tvAnimalList).setOnTouchListener { v, event ->
    mGestureDetector.onTouchEvent(event)
}

Which results in the warnings:

  • 'onTouch' lambda should call 'View#performClick' when a click is detected
  • Custom view "TextView" has 'setOnTouchListener' called on it but does not override 'performClick'

First, I added a call to v.performClick(), which got rid of the first warning. Like this:

findViewById<TextView>(R.id.tvAnimalList).setOnTouchListener { v, event ->
    v.performClick()
    mGestureDetector.onTouchEvent(event)
}

I got rid of the second warning by changing the findViewById cast from <TextView> to <View>. Here's my warning-free result:

findViewById<View>(R.id.tvAnimalList).setOnTouchListener { v, event ->
    v.performClick()
    mGestureDetector.onTouchEvent(event)
}
  private fun closeKeyboard(binding: ContollerMeterBinding) {
    binding.scrollView.apply {
        setOnTouchListener(OnTouchListener { v, event ->
            if (event != null && event.action == MotionEvent.ACTION_MOVE) {
                val imm =
                    activity?.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
                val isKeyboardUp = imm.isAcceptingText
                if (isKeyboardUp) {
                    imm.hideSoftInputFromWindow(v.windowToken, 0)
                }
            }
            performClick()
            false
        })
    }
}

This works for me: (not directly related to onTouch event but yields the same warning, might be helpful to someone)

 takePhotoButton.setOnTouchListener { _, motionEvent ->
            when (motionEvent.action) {
                MotionEvent.ACTION_DOWN -> {
                    //when user touch down
                }
                MotionEvent.ACTION_UP -> {
                    //when user touch release
                }
            }
            true
        }
Related