Can't handle both click and touch events simultaneously

后端 未结 12 2033
时光说笑
时光说笑 2020-12-01 03:45

I am trying to handle touch events and click events on a button. I do the following:

button.setOnClickListener(clickListener);
button.setOnTouchListener(touc         


        
相关标签:
12条回答
  • 2020-12-01 03:55

    This is an example of TouchListener that doesn't shadow ClickListener.

    import android.graphics.PointF
    import android.view.MotionEvent
    import android.view.MotionEvent.*
    import android.view.View
    import kotlin.math.abs
    
    object TouchAndClickListener : View.OnTouchListener {
    
        /** Those are factors you can change as you prefer */
        private const val touchMoveFactor = 10
        private const val touchTimeFactor = 200
    
    
        private var actionDownPoint = PointF(0f, 0f)
        private var previousPoint = PointF(0f, 0f)
        private var touchDownTime = 0L
    
        override fun onTouch(v: View, event: MotionEvent) = when (event.action) {
            ACTION_DOWN -> PointF(event.x, event.y).let {
    
                actionDownPoint = it  // Store it to compare position when ACTION_UP
                previousPoint = it  // Store it to compare position when ACTION_MOVE
                touchDownTime = now() // Store it to compare time when ACTION_UP
    
                /* Do other stuff related to ACTION_DOWN you may whant here */
    
                true
            }
    
            ACTION_UP -> PointF(event.x, event.y).let {
    
                val isTouchDuration = now() - touchDownTime < touchTimeFactor  // short time should mean this is a click
                val isTouchLength = abs(it.x - actionDownPoint.x) + abs(it.y - actionDownPoint.y) < touchMoveFactor  // short length should mean this is a click
    
                val shouldClick = isTouchLength && isTouchDuration  // Check both
    
                if (shouldClick) yourView.performClick() //Previously define setOnClickListener{ } on yourView, then performClick() will call it
    
                /* Do other stuff related to ACTION_UP you may whant here */
    
                true
            }
    
            ACTION_MOVE -> PointF(event.x, event.y).let {
    
                /* Do other stuff related to ACTION_MOVE you may whant here */
    
                previousPoint = it
                true
            }
    
            else -> false // Nothing particular with other event
        }
    
        private fun now() = System.currentTimeMillis()
    }
    
    0 讨论(0)
  • 2020-12-01 03:57

    In ACTION_UP perform onClick manually using condition

    boolean shouldClick = event.eventTime - event.downTime <= 200 // compares the time with some threshold
    

    So, try within MotionEvent.ACTION_UP

    if(event.eventTime - event.downTime <= 200) { // case or when statement of action Touch listener
        view.performClick();
    }
    
    0 讨论(0)
  • 2020-12-01 04:00
    button.setOnTouchListener(this);
    

    Implement interface and the code here:

    @Override
    public boolean onTouch(View view, MotionEvent motionEvent) {
        switch (view.getId()) {
            case R.id.send:
                switch(motionEvent.getAction()){
                    case MotionEvent.ACTION_DOWN:
                        //when the user has pressed the button
                        //do the needful here
                        break;
                    case MotionEvent.ACTION_UP:
                        //when the user releases the button
                        //do the needful here
                        break;
                }
                break;
        }
        return false;
    }
    
    0 讨论(0)
  • 2020-12-01 04:01

    I suppose you're returning true in your OnTouchListener? That will consume the event so it won't be sent down for any further processing.

    On a side note - what's the point of having both a click and touch listener?

    0 讨论(0)
  • 2020-12-01 04:01

    To make both events possible in gridview,only by making return of touch listener"false" as follows,this worked for me.

    **GridView myView = findViewById(R.id.grid_view);
    myView.setOnTouchListener(new OnTouchListener() {
        public boolean onTouch(View v, MotionEvent event) {
            // ... Respond to touch events
            return false;
        }
    });**
    

    in this way both events can be achieved

    0 讨论(0)
  • 2020-12-01 04:02

    Thanks to @urSus for great answer
    But in that case every touch will perform click, Even ACTION_MOVE
    Assuming you want to separate move event and click event you can use a little trick
    define a boolean field and use like this:

     @Override
            public boolean onTouch(View view, MotionEvent motionEvent)
            {
                switch (motionEvent.getAction() & MotionEvent.ACTION_MASK)
                {
                    case MotionEvent.ACTION_DOWN:
                        shouldClick = true;
                        .
                        .
                        break;
                    case MotionEvent.ACTION_UP:
                        if (shouldClick)
                            view.performClick();
                        break;
                    case MotionEvent.ACTION_POINTER_DOWN:
                        break;
                    case MotionEvent.ACTION_POINTER_UP:
                        break;
                    case MotionEvent.ACTION_MOVE:
                        //Do your stuff
                        shouldClick = false;
                        break;
                }
                rootLayout.invalidate();
                return true;
            }
    
    0 讨论(0)
提交回复
热议问题