2

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.

Murtaza Khursheed Hussain
  • 15,176
  • 7
  • 58
  • 83
domi
  • 968
  • 1
  • 10
  • 18

2 Answers2

3

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.
Alex.F
  • 5,648
  • 3
  • 39
  • 63
  • 1
    Thank you for clear explanation and giving the solutions. This is what I have needed, thank you sir! – domi Feb 04 '15 at 14:43
0

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.

Community
  • 1
  • 1
Michele La Ferla
  • 6,775
  • 11
  • 53
  • 79
  • This does not solves my problem. My problem is registering both on touch (from SwipeListener) and on click events on the expandablelistview. – domi Feb 03 '15 at 13:27
  • what I can't understand here is why do you need to use a swipeListener in you business plan. I am not sure if expandible listview supports swipes. It usually uses clicks to open/close the child of the parent element. – Michele La Ferla Feb 03 '15 at 15:09
  • 1
    Every view in Android SDK supports touch events so I have written my Swipe listener and added it to the list view along with onClick listener. I need the swipe listener so user can drag the view left|right. All I need to do is a listview (expandable list view) that I can expand and use swipe gestures to develop further. Hope that helps more. – domi Feb 03 '15 at 15:13
  • ok then, you can try this: http://stackoverflow.com/questions/18857452/3-level-expandable-list-view-with-swipe-feature – Michele La Ferla Feb 03 '15 at 15:59