AndroidSwipeLayout icon indicating copy to clipboard operation
AndroidSwipeLayout copied to clipboard

quick Swipe gesture trigger the onClickListener

Open thomaslc66 opened this issue 9 years ago • 14 comments

Hi, i've configure your library correctly, i used the BaseSwipeAdapter with the onOpen method and an onClickListener method for the surface. But sometimes when i swipe without keeping my finger on the screen, my move trigger the onClickListener of my row (when i swipe to Open and sometimes when i swipe to close). How can i manage to avoid this behavior?

Thanks

thomaslc66 avatar May 06 '15 14:05 thomaslc66

Here is a video of the problem

https://mega.nz/#!PAJmXYYY!SkxP83OB04aidyXiu5bQ55QkjGAkwiB-6Uutd12RYEw

thomaslc66 avatar May 06 '15 14:05 thomaslc66

just dropping in here to say "same here", I haven't really investigated it yet though.

Groxx avatar May 07 '15 06:05 Groxx

Think i found something:

in your onClickListener test the swipelayout Status

    swipeLayout.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            // test if the swipe is closed
            if(swipeLayout.getOpenStatus() == SwipeLayout.Status.Close){
                //DO WHAT YOU WANT
            }//if
        }
    });

Try it and tell me?!

thomaslc66 avatar May 07 '15 07:05 thomaslc66

It still triggers the onClickListener when you close (swipe back) the surface view

af608 avatar May 09 '15 19:05 af608

You may want to try this work-around:

swipeLayout.setOnClickListener(new View.OnClickListener()
{
  boolean wasClosed = true;

  @Override
  public void onClick(View v)
  {
    if (SwipeLayout.Status.Close == swipeLayout.getOpenStatus())
    {
      if (wasClosed)
      {
        //DO WHAT YOU WANT
      }
      else
      {
        wasClosed = true;
      }
    }
    else
    {
      wasClosed = false;
    }
  }
});

af608 avatar May 09 '15 23:05 af608

Alrighty, so the problem is (essentially) here: https://github.com/daimajia/AndroidSwipeLayout/blob/cc6a322f745c3f7acfc9b02223e4cb3067e9fdc5/library/src/main/java/com/daimajia/swipe/SwipeLayout.java#L1002-L1013

private void performAdapterViewItemClick() {
    if(getOpenStatus()!= Status.Close) return;
    ViewParent t = getParent();
    if (t instanceof AdapterView) {
        AdapterView view = (AdapterView) t;
        int p = view.getPositionForView(SwipeLayout.this);
        if (p != AdapterView.INVALID_POSITION){
            view.performItemClick(view.getChildAt(p - view.getFirstVisiblePosition()), p, view
                    .getAdapter().getItemId(p));
        }
    }
}

If you e.g. swipe an open layout closed, and the layout closes before you release your finger (e.g. if the background view is 100dp, and you swiped 110dp before lifting), the getOpenStatus() will return Close, because it's only based on the current layout.

Unfortunately I'm not sure what a clean solution would look like. Maybe this is worth special-casing, and adding an "if swiped by this touch" flag?

Groxx avatar May 10 '15 19:05 Groxx

Hi, I am also getting this in my listview. I am using this latest one com.daimajia.swipelayout:library:1.2.0@aar"

Thanks,

kprathap23 avatar May 27 '15 06:05 kprathap23

Tested that @Groxx 's commit using jitpack. It's finally working perfectly in my case.

This is the dependency line I'm using: compile 'com.github.Groxx:AndroidSwipeLayout:c8a42d84c1', don't forget to add maven { url "https://jitpack.io" } line to your repositories block.

Going to use this workaround until that fix got into this upstream repo. Hope it will be merged soon.

akhy avatar Jun 10 '15 10:06 akhy

Any updates? I have to downgrade the library to v1.1.9 to get rid of this problem.

dyhpoon avatar Jun 22 '15 08:06 dyhpoon

One thing that I did that fix this was instead of putting the onClickListener on the whole layout (itemView of a ViewHolder, for example), I put it only on the SurfaceView. For what I understood, the SwipeLayout get the click first and use it if dragging, don't pass to children. If not dragging, then the click will be used by children.

Using the same layout on the wiki, would be something like this:

<com.daimajia.swipe.SwipeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent" android:layout_height="80dp"
    android:id="@+id/swipe_layout">
    <!-- Bottom View Start-->
     <LinearLayout
        android:id="@+id/bottom_wrapper"
        android:layout_width="160dp"
        android:layout_height="match_parent">
        <!--What you want to show-->
    </LinearLayout>
    <!-- Bottom View End-->

    <!-- Surface View Start -->
     <LinearLayout
        android:id="@+id/ll_surface_view"
        android:layout_width="match_parent"
        android:background="?attr/selectableItemBackground"
        android:layout_height="match_parent">
        <!--What you want to show in SurfaceView-->
    </LinearLayout>
    <!-- Surface View End -->
</com.daimajia.swipe.SwipeLayout>

And on my ViewHolder

ll_surface_view.setOnClickListener(view -> {
    if(swipe_layout.getOpenStatus() == SwipeLayout.Status.Close){
        listener.onSubjectClicked(subject);
    }
});

tsuharesu avatar Oct 14 '15 13:10 tsuharesu

Used @tsuharesu solution, worked perfectly, I guess you could close the issue so people will know there a solution when looking at the issue.

mgohin avatar Oct 03 '17 18:10 mgohin

Used @tsuharesu solution with Cursor Adaptor and the problem is solved1 Thanks

juniaziz avatar Nov 06 '17 09:11 juniaziz

Not the perfect workaround but it works well for my purposes

public class CSwipeLayout extends SwipeLayout {
    public enum SwipeStatus {OPENING, OPENED, CLOSING, CLOSED}

    SwipeStatus swipeStatus = SwipeStatus.CLOSED;
    OnClickListener onClickListener;

    public CSwipeLayout(Context context) {
        super(context);

        init(context);
    }

    public CSwipeLayout(Context context, AttributeSet attrs) {
        super(context, attrs);

        init(context);
    }

    public CSwipeLayout(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);

        init(context);
    }

    private void init(Context context) {
        addSwipeListener(new SimpleSwipeListener() {
            Handler handler = new Handler();
            Runnable closeRunnable = new Runnable() {
                @Override
                public void run() {
                    swipeStatus = SwipeStatus.CLOSED;
                }
            };
            Runnable openRunnable = new Runnable() {
                @Override
                public void run() {
                    swipeStatus = SwipeStatus.OPENED;
                }
            };

            @Override
            public void onStartOpen(SwipeLayout layout) {
                swipeStatus = SwipeStatus.OPENING;
                handler.removeCallbacks(closeRunnable);
            }

            @Override
            public void onOpen(SwipeLayout layout) {
                handler.removeCallbacks(closeRunnable);
                handler.postDelayed(openRunnable, 100);
            }

            @Override
            public void onStartClose(SwipeLayout layout) {
                swipeStatus = SwipeStatus.CLOSING;
                handler.removeCallbacks(closeRunnable);
            }

            @Override
            public void onClose(SwipeLayout layout) {
                handler.removeCallbacks(openRunnable);
                handler.postDelayed(closeRunnable, 100);
            }
        });

        super.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View view) {
                if (getSwipeStatus() == CSwipeLayout.SwipeStatus.CLOSED) {
                    if (onClickListener != null)
                        onClickListener.onClick(view);
                } else if (getSwipeStatus() == CSwipeLayout.SwipeStatus.OPENED) {
                    // This will close the layout in case of a click while already opened
                    close();
                }
            }
        });
    }

    public SwipeStatus getSwipeStatus() {
        return swipeStatus;
    }

    @Override
    public void setOnClickListener(OnClickListener onClickListener) {
        this.onClickListener = onClickListener;
    }
}


Then

swipeLayout.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View view) {
                    // DO WHATEVER YOU WANT
            }
        });

qzmp2000 avatar Oct 02 '18 00:10 qzmp2000

Think i found something:

in your onClickListener test the swipelayout Status

    swipeLayout.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            // test if the swipe is closed
            if(swipeLayout.getOpenStatus() == SwipeLayout.Status.Close){
                //DO WHAT YOU WANT
            }//if
        }
    });

Try it and tell me?!

its working for me. thanks a lot. you saved my time

prakash-apps avatar Dec 28 '18 11:12 prakash-apps