DragSortListView Cannot Drag Down on SwipeRefreshLayout

1.2k views Asked by At

I'm using DragSortListView (https://github.com/bauerca/drag-sort-listview) inside the SwipeRefreshLayout to make it able for "pull-to-refresh" and dragable listview. Here's my XML:

<android.support.v4.widget.SwipeRefreshLayout
    android:layout_below="@id/div_subtitle"
    android:id="@+id/srl_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent">


    <com.mobeta.android.dslv.DragSortListView
        android:id="@android:id/list"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        dslv:drag_enabled="true"
        dslv:track_drag_sort="false"
        android:divider="@null"
        dslv:use_default_controller="false"
        tools:listitem="@layout/list_kkategori" />
</android.support.v4.widget.SwipeRefreshLayout>

And this is my listview element's XML:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:paddingRight="@dimen/right_margin"
    android:paddingLeft="@dimen/left_margin"
    android:background="@color/background"
    android:layout_height="50dp">

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@drawable/container_side_dropshadow">

        <ImageView
            android:id="@+id/iv_handler"
            android:layout_width="50dp"
            android:scaleType="fitXY"
            android:layout_height="20dp"
            android:layout_centerVertical="true"
            android:layout_marginLeft="10dp"
            android:src="@drawable/draghandler" />

        <TextView
            android:id="@+id/tv_nama"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textColor="@color/textBlack"
            android:layout_centerVertical="true"
            android:layout_marginLeft="10dp"
            android:layout_toRightOf="@id/iv_handler"
            android:text="Nama Kategori"
            android:textSize="17sp" />

        <View
            android:layout_width="match_parent"
            android:layout_height="0.5dp"
            android:layout_alignParentBottom="true"
            android:background="@color/dividerColor"
            android:layout_marginLeft="@dimen/left_divider_margin"
            android:layout_marginRight="@dimen/right_divider_margin" />

    </RelativeLayout>

</RelativeLayout>

And this is my DragSortListView intialization that I call on my onCreateView of my fragment:

dslv = (DragSortListView) v.findViewById(android.R.id.list);
dslv.addHeaderView(View.inflate(getActivity(), R.layout.list_header, null), null, false);
dslv.addFooterView(View.inflate(getActivity(), R.layout.list_footer, null), null, false);

dslvController = new DragSortController(dslv);
dslvController.setDragHandleId(R.id.iv_handler);
dslvController.setRemoveEnabled(false);
dslvController.setSortEnabled(true);
dslvController.setDragInitMode(DragSortController.ON_DOWN);
dslvController.setRemoveMode(DragSortController.FLING_REMOVE);
dslv.setFloatViewManager(dslvController);
dslv.setOnTouchListener(dslvController);
dslv.setDragEnabled(true);

However, somehow the DragSortListView cannot drag down any list item, but the drag up function still works. I suspect that the onTouchListener in DragSortListView when I drag down the list element is somehow overridden by SwipeRefreshLayout's onTouchListener.

Is there any solution or workaround for this problem? I need both functionality in my app, Swipe-to-Refresh and Drag listview.

2

There are 2 answers

0
PsyGik On

Use dslvController.setDragInitMode(DragSortController.ON_LONG_PRESS); instead of dslvController.setDragInitMode(DragSortController.ON_DOWN);


My bad, still has problem with drag down. One dirty workaround is to move the item slightly up before dragging it downwards. I know this kinda sucks, I'm reading through the docs on SwipeRefreshLayout, will update if i find anything. Sorry for the wrong solution.

1
leroid On

I've faced the same problem, but in my app there are 2 states of a list: first - when user can drag&drop the content and second - when user can swipe to refresh the whole list.

So, I found the way how to prevent swipe refresh action while my list is in drag&drop state. The point is to override function canChildScrollUp() of SwipeRefreshLayout, which by default prevents swiping behavior for any AbsListView unless the action is done when the first row of the list is on the top. I'm checking if the child view is instance of DragSortListView and return true if the list.isDragEnabled(). You can implement any other logic here as well.

Here is my CustomSwipeRefreshLayout:

public class CustomSwipeRefreshLayout extends SwipeRefreshLayout {

private View mTarget;

public CustomSwipeRefreshLayout(Context context) {
    super(context);
}

public CustomSwipeRefreshLayout(Context context, AttributeSet attrs) {
    super(context, attrs);
}

@Override
public boolean canChildScrollUp() {
    ensureTarget();
    if (mTarget != null && mTarget instanceof DragSortListView)
        return super.canChildScrollUp()||((DragSortListView)mTarget).isDragEnabled();
    return super.canChildScrollUp();
}

/** 
* Had to copy the method from SwipeRefreshLayout
**/
private void ensureTarget() {
    // Don't bother getting the parent height if the parent hasn't been laid
    // out yet.
    if (mTarget == null) {
        for (int i = 0; i < getChildCount(); i++) {
            View child = getChildAt(i);
            if (! (child instanceof ImageView)) {
            // In fact, refresh icon is instanseof CircleImageView, but the
            // class is private, so I decided to compare with ImageView. 
                mTarget = child;
                break;
            }
        }
    }
}

}

Hope, it would help someone.