1

Before I've used OnLongClickListener and setOnClickListener for my developing app. Sometimes it was giving some responsiveness problems. I checked it using Log.d messages (logcat) in the head of the events.

Based on some reports from Stackoverflow, I've decided to simulate everything just with the onTouchListener event.

This is my real code.

var otl  = OnTouchListener { v, event ->
  val actual = SystemClock.elapsedRealtime()
  when (event.action) {
    MotionEvent.ACTION_DOWN -> {
      editX = event.x;  editY = event.y
      downClick = atual  // Down touch time 
      vPrev = v.id       // widget in down touch 
      Log.d("myMess", "Down $atual milis")
    } // down
    MotionEvent.ACTION_UP -> {   

      val tag = v.tag as CalcTag      // Se below comments
      val localCheck = tag.name.name == "DISPLAY"  
      var ok =(v.id==vPrev)    // same widget?
          // "Fake" Double click, I'm using just in one situation
      eDoubleClick = (actual - upClick) < doubleClickTime
      upClick = atual   // up touch time
      if (localCheck && ok)  // same 
         ok =  abs(event.x - editX) <=20.0   // "Near" position
               &&  abs(event.x - editX) <=20.0
      if (ok) {    // same widget and position?
        Log.d("myMess", "Up $actual milis: ${event.x} e ${event.y}")
        if ((actual - downClick) > longClickTime)
          clickL(v)  // long click
        else
          clickS(v)  // single click (double click inside!)
      } else
        Log.d("myMess", 
         "Wrong Up $actual milis: ${event.x} e ${event.y}")
     } // up
 //  else-> Log.d("myMess", "Event ${event.action}")
  } // when
  false
} // On Touch

Here I set the touch event for all my widget. It is just one routine.

...
bt.setOnTouchListener(otl)  // bt is related to all widgets 

The variableseditX, editY (saved positions), downClick, upClick (saved times) e vPrev (previous widget id in down touch event) are global variables.

Concerning about above comment at val tag = v.tag as CalcTag , CalcTag is a structure stored in the widget tag field, where the name field stores an enum with the widget type.

In this case, DISPLAY is the only widget type (In fact, only 1 widget has this type) that has large size and the position of the touch is relevant, because this is where the cursor will be positioned.

What I've noticed?

When cursor in the widget DISPLAY is turned off (isCursorVisible=false), my widgted clicks works in the same way that it worked with my old OnLongClickListener and setOnClickListener events.

And also, like before, when I turn on the cursor (isCursorVisible=false) sometimes, specially when I click fast, the widget don't fires the event touch.

To summarize there are the following points:

a) The rest of my program no matters for this discussion, because the problem is all self-contained.
b) The only event I'm associating with my widgets is the touch event.
c) Everything I wrote here I concluded from the logcat in the head of the touch event, without debugging, and of course by the visual result in my app, which is the lack of responsiveness when touch is not detected.
d) The only event outside DOWN and UP that happens on touch is 2 (MOVE), which is irrelevant to my problem. They refer to the micro movements of the finger before lifting it.
e) Cursor on and off seems to be a key to my problem, because Android system update automatically the cursor position.
f) I've disabled all features related to cursor, except the own cursor (Disable EditText context menu)

What can I do?

Need I replace the cursor for a sofware cursor, like to underline the character under the cursor? Is there something that I don't get?

I'm begging for help. I'm in despair!

Paulo Buchsbaum
  • 2,471
  • 26
  • 29

1 Answers1

0

It's unbelievable. I feel tired. Before, I've returned false because touch event prepared the click event. However, it's not anymore like that. The touch event is the end of the trail. So just to change the last line for true has solved the problem fully.

The complete code becomes:

var otl  = OnTouchListener { v, event ->
  val actual = SystemClock.elapsedRealtime()
  when (event.action) {
    MotionEvent.ACTION_DOWN -> {
      editX = event.x;  editY = event.y
      downClick = atual  // Down touch time 
      vPrev = v.id       // widget in down touch 
      Log.d("myMess", "Down $atual milis")
    } // down
    MotionEvent.ACTION_UP -> {   

      val tag = v.tag as CalcTag      // Se below comments
      val localCheck = tag.name.name == "DISPLAY"  
      var ok =(v.id==vPrev)    // same widget?
          // "Fake" Double click, I'm using just in one situation
      eDoubleClick = (actual - upClick) < doubleClickTime
      upClick = atual   // up touch time
      if (localCheck && ok)  // same 
         ok =  abs(event.x - editX) <=20.0   // "Near" position
               &&  abs(event.x - editX) <=20.0
      if (ok) {    // same widget and position?
        Log.d("myMess", "Up $actual milis: ${event.x} e ${event.y}")
        if ((actual - downClick) > longClickTime)
          clickL(v)  // long click
        else
          clickS(v)  // single click (double click inside!)
      } else
        Log.d("myMess", 
         "Wrong Up $actual milis: ${event.x} e ${event.y}")
     } // up
 //  else-> Log.d("myMess", "Event ${event.action}")
  } // when
  true  // That's all, folks
} // On Touch

The strange thing about this story is that it worked perfectly with false, it was only intermitent when the cursor of one of the widgets was on. I find it very unclear how the error manifests itself. He should lock everything and do nothing and not work almost always!

Paulo Buchsbaum
  • 2,471
  • 26
  • 29