Propagating touch events in a ScrollView

I am having difficulty propagating touch events in an android app. I have a ScrollView that contains a view that acts like an element. When you click on an element, I want to handle the onclick event. This can be done using setOnClickListener on the element. But I also need to intercept the scrollview ACTION_UP and ACTION_DOWN events. I do this using the scrollview setOnTouchListener.

Scrolling views ACTION_UP and ACTION_DOWN are not accepted. Then I decided to use setOnTouchListener on the element using setOnClickListener. This improves the situation. When you click on an element, the onTouchListener is called for ACTION_DOWN. I am returning false when exiting the onTouchListener object. Then the scrollview onTouchListener is called and the ACTION_DOWN is received. Everything seems to be going well. It puzzles me, but why is the onTouchListener element called first and not the scrollview. I am returning false when exiting the scrollview onTouchListener. Now when I unlock my finger the scrollview ACTION_UP is called and I return false.

The problem I have in mind now is that the ACTION_UP item is never called. I had to try every true / false return combination in the onTouchListener, but I can't seem to get the ACTION_UP to work, or if I get it to work, then something in the scrollview onTouchListener doesn't work anymore.

I also tried adding a dispatchTouchEvent to the scrollview onTouchHandler, but found that I was getting an infinite recursive call.

Is there a way to have a scrollview and its child get ACTION_UP / ACTION_DOWN?

+3


source to share


1 answer


It takes some tricky coding to make an element in the scrollview respond to onClick, but also know when the user has tapped the finger down or up. The solution is available here for API 15+. The main thing to note is that the onTouchListener is not actually used for the scrollview. Instead, events are detected on the element using the OnSimpleGestureListener. However, it's interesting to note that there is no onUp method for OnSimpleGestureListener, although onDown does (go figure). To solve the problem for onUp, you need to check the return value of onTouchEvent:

GestureDetector gestureDetector = new GestureDetector(context, new GestureDetectorListItem());

listItem.setOnTouchListener(this.onTouchArticleItem);

private View.OnTouchListener onTouchArticleItem = new View.OnTouchListener()
{
  @Override
  public boolean onTouch(View v, MotionEvent event)
  {
    try
    {

      boolean state = gestureDetector.onTouchEvent(event);

      if ((event.getAction() == android.view.MotionEvent.ACTION_UP) && !state)
      {
        // Handle up event here.
        return true;
      }
      else if ((event.getAction() == android.view.MotionEvent.ACTION_DOWN) && state)
      {
        // Handle down event here.
        return true;
      }
      else
        return state;


    }
    catch (Exception ex)
    {
      Logger.Log(context, ex.getMessage(), Log.ERROR);
      return false;
    }
  }
};


private class GestureDetectorListItem extends GestureDetector.SimpleOnGestureListener
{
  public boolean onSingleTapUp(MotionEvent e)
  {
    return true;
  }

  public void onLongPress(MotionEvent e)
  {
  }

  public boolean onDoubleTap(MotionEvent e)
  {
    return false;
  }

  public boolean onDoubleTapEvent(MotionEvent e)
  {
    return false;
  }

  public boolean onSingleTapConfirmed(MotionEvent e)
  {
    return false;

  }

  public void onShowPress(MotionEvent e)
  {
  }

  public boolean onDown(MotionEvent e)
  {
    return true;
  }


  public boolean onScroll(MotionEvent e1, MotionEvent e2, final float distanceX, float distanceY)
  {
    return super.onScroll(e1, e2, distanceX, distanceY);
  }

  @Override
  public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY)
  {
    return super.onFling(e1, e2, velocityX, velocityY);
  }
}

      



The only problem I can see with this solution is that there are too few scrolling items to scroll through. If there are too few elements and the user clicks somewhere on the scrollview other than the element, then up / down events are not detected. It doesn't matter if it matters in your application or not, you will need to decide. If needed, you might need to also enable the onTouchListener for the scrollview.

0


source







All Articles