domi
domi

Reputation: 968

OnSwipeListener and ExpandableListView click not recognized

I have a problem recognizing onGroup clicks on my expandable list view. I am using a custom swipe listener for my group views for sliding purposes. Now all I want is to expand groups while pressing on them and it seems I can't find the right way to register both OnTouch and onGroupClick on the groups view. I am calling false when I am not swiping so other gestures can be recognizable (such as normal clicks and long clicks), but my group is not responding to clicks and therefore not expanding.

Right now my Swipe listener is working properly but OnGroupClick is not called and not expanding. When I remove my OnSwipeListener from getGroupView() method, the actual expanding is properly working.

My custom on swipe listener:

public class OnSwipeListener implements View.OnTouchListener
{
    private final GestureDetector gestureDetector = new GestureDetector(new GestureListener());

    public boolean onTouch(final View v, final MotionEvent event)
    {
        return gestureDetector.onTouchEvent(event);
    }

    private final class GestureListener extends GestureDetector.SimpleOnGestureListener
    {

        private static final int SWIPE_THRESHOLD = 70;
        private static final int SWIPE_VELOCITY_THRESHOLD = 70;

        @Override
        public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY)
        {
            boolean result = false;
            try
            {
                float diffY = e2.getY() - e1.getY();
                float diffX = e2.getX() - e1.getX();
                if (Math.abs(diffX) > Math.abs(diffY))
                {
                    if (Math.abs(diffX) > SWIPE_THRESHOLD && Math.abs(velocityX) > SWIPE_VELOCITY_THRESHOLD)
                    {
                        if (diffX > 0)
                        {
                            result = onSwipeRight();
                        }
                        else
                        {
                            result = onSwipeLeft();
                        }
                    }
                }
                else
                {
                    if (Math.abs(diffY) > SWIPE_THRESHOLD && Math.abs(velocityY) > SWIPE_VELOCITY_THRESHOLD)
                    {
                        if (diffY > 0)
                        {
                            result = onSwipeBottom();
                        }
                        else
                        {
                            result = onSwipeTop();
                        }
                    }
                }
            }
            catch (Exception exception)
            {
                exception.printStackTrace();
            }
            return result;
        }
    }

    public boolean onSwipeRight()
    {
        return false;
    }

    public boolean onSwipeLeft()
    {
        return false;
    }

    public boolean onSwipeTop()
    {
        return false;
    }

    public boolean onSwipeBottom()
    {
        return false;
    }
}

My expandable list view and its on group click listener set up:

expandable_list_view = (ExpandableListView) findViewById(R.id.activity_profile_expandable_listview);
setGroupParents(); setChildData();
ExpandableListAdapter adapter = new ExpandableListAdapter(this, parentItems, childItems);
expandable_list_view.setAdapter(adapter);

expandable_list_view.setOnGroupClickListener(new ExpandableListView.OnGroupClickListener()
{
    @Override
    public boolean onGroupClick(ExpandableListView parent, View v, int groupPosition, long id)
    {
        parent.smoothScrollToPosition(groupPosition);

        if (parent.isGroupExpanded(groupPosition))
        {
            parent.collapseGroup(groupPosition);
        } else {
            parent.expandGroup(groupPosition);
        }

        return false;
    }
});

And lastly getGroupView from my custom adapter for expandable list view:

@Override
public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent)
{

if (convertView == null)
{
    convertView = inflater.inflate(R.layout.layout_activity_expandableitem, null);
}

final View converted_view = convertView;

final LinearLayout front_view = (LinearLayout) converted_view.findViewById(R.id.layout_activity_expandableitem_front_view); front_view.setTag(Position.CENTER);
final LinearLayout behind_view = (LinearLayout) converted_view.findViewById(R.id.layout_activity_expandableitem_behind_view);
final View confirmation_view = inflater.inflate(R.layout.slide_profile, null); confirmation_view.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.FILL_PARENT));
final View cancel_view = inflater.inflate(R.layout.slide_cancel, null); cancel_view.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.FILL_PARENT));


//  Set onTouchListener
front_view.setOnClickListener(null);
front_view.setOnTouchListener(new OnSwipeListener()
{
    @Override
    public boolean onSwipeRight()
    {
        Position position = (Position) front_view.getTag();
        if (position == Position.CENTER)
        {
            behind_view.removeAllViews();
            behind_view.addView(confirmation_view);
            showConfirmation(front_view);

            front_view.setTag(Position.RIGHT);
        }
        else if (position == Position.LEFT)
        {
            //behind_view.removeAllViews();
            showCenter(front_view, Position.RIGHT);

            front_view.setTag(Position.CENTER);
        }

        return true;
    }

    @Override
    public boolean onSwipeLeft()
    {
        Position position = (Position) front_view.getTag();
        if (position == Position.CENTER)
        {
            behind_view.removeAllViews();
            behind_view.addView(cancel_view);
            showInfo(front_view);

            front_view.setTag(Position.LEFT);
        }
        else if (position == Position.RIGHT)
        {
            //behind_view.removeAllViews();
            showCenter(front_view, Position.LEFT);

            front_view.setTag(Position.CENTER);
        }

        return true;
    }
});

//  Return the view
return converted_view;

Thank you for any idea on how to solve this.

Upvotes: 2

Views: 3015

Answers (2)

Alex.F
Alex.F

Reputation: 6181

So here is what's going on:

  1. When you set OnGroupClick it is set to the whole listview (not per row) the implementation of the listview will "figure out" which row was clicked when you touch the listView
  2. When you set your SwipeListener you attach it to the row.
  3. When both are set, the row precedes the whole listview and will process (consume) the touch event, which in turn will not reach the listview (this is why you have them working when separate).

You have an option to:

  1. Subclass ListView and implement onInterceptTouchEvent(). This way your listview will always be able to "see" the touch events and act on them. (Note that you potentially could get a situation where you detect a swipe and a click simultaneously).
  2. Implement your own ListView whose OnTouch will be in charge of identifying which row has interaction, identifying swipe gestures (through your listener) and click events and deciding which get precedent.

Upvotes: 3

Michele La Ferla
Michele La Ferla

Reputation: 6884

You can try the following solution I implemented myself and am sure it works. I used the onClickListener not the SwipeListener though. Hopefully it can help you solve your problem.

Upvotes: 0

Related Questions