Giter Site home page Giter Site logo

ernestoyaquello / dragdropswiperecyclerview Goto Github PK

View Code? Open in Web Editor NEW
905.0 12.0 99.0 5.6 MB

Kotlin Android library that extends RecyclerView to support gestures like drag & drop and swipe, among others. It works with vertical, horizontal and grid lists.

License: Apache License 2.0

Kotlin 100.00%
kotlin android swipe swipe-to-delete drag-and-drop drag dividers recyclerview

dragdropswiperecyclerview's People

Contributors

ernestoyaquello avatar jonathanimperato avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

dragdropswiperecyclerview's Issues

[QUESTION]: Can it use with NestedScrollView ?

when using it inside NestedScrollView the auto scroll not working. try to use android:fillViewport="true"
android:orientation="vertical", requestDisallowInterceptTouchEvent with no success

CI?

Hello ernestoyaquello,

It would be good if this repo had some sort of CI, so that we could see if there are any breaking changes.

Love
Yer best pal in the world
and your next of kin

Change view properties in the BehindSwipedItemLayout

Hi, first thank you for the wonderful lib

My question, is that any way to manipulate BehindSwipedItemLayout, for exemple i want to show and hide a progressBar onItemSwiped

    private val onItemSwipeListener = object : OnItemSwipeListener<MyItem> {
        override fun onItemSwiped(position: Int, direction: OnItemSwipeListener.SwipeDirection, item: MyItem): Boolean {
                // Show loading view
                Handler(Looper.getMainLooper()).postDelayed({
                    dataSet[position].status = "3"
                    Log.v("status : ", "3")
                    mAdapter.notifyItemChanged(position)
                    Log.v("delay : ", "2 Sec")
                }, 2000)
                // Hide loading view
                return true
        }
    }

Thank you!

Error inflating class com.ernestoyaquello.dragdropswiperecyclerview.DragDropSwipeRecyclerView

Error: Binary XML file line #19: Binary XML file line #19: Error inflating class com.ernestoyaquello.dragdropswiperecyclerview.DragDropSwipeRecyclerView
This is my layout file:

<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:animateLayoutChanges="true"
android:background="@drawable/app_background"
android:paddingTop="?actionBarSize">

<FrameLayout
    android:layout_width="0dp"
    android:layout_height="0dp"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintRight_toRightOf="parent"
    app:layout_constraintTop_toTopOf="parent">

    <com.ernestoyaquello.dragdropswiperecyclerview.DragDropSwipeRecyclerView
        android:id="@+id/favsRecyclerView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:visibility="visible"
        app:item_layout="@layout/song_item" />

</FrameLayout>

<TextView
    android:id="@+id/no_fav_text"
    style="@style/TrackText"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:animateLayoutChanges="true"
    android:gravity="center"
    android:padding="24dp"
    android:text="@string/no_fav_message"
    android:textAlignment="center"
    android:visibility="invisible"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintRight_toRightOf="parent"
    app:layout_constraintTop_toTopOf="parent"
    tools:visibility="visible" />

</androidx.constraintlayout.widget.ConstraintLayout>

What is wrong? I am using AndroidX

By the way the library is really well made. Thanks a lot for your effort!

Two different recyclers with different ListOrientation objects share removed swipe direction flags

I have 2 completely separated recyclers which are in different fragments in ViewPager. When I remove a swipe or drag flag from one of them it is automatically removed in the second which I find confusing.

Fragment 1:
recyclerOne.layoutManager = LinearLayoutManager(context!!)
recyclerOne.adapter = adapterOne
val orientation = DragDropSwipeRecyclerView.ListOrientation.VERTICAL_LIST_WITH_VERTICAL_DRAGGING
orientation.removeSwipeDirectionFlag(DragDropSwipeRecyclerView.ListOrientation.DirectionFlag.RIGHT)
recyclerOne.orientation = orientation

Fragment 2:
recyclerTwo.layoutManager = LinearLayoutManager(context!!)
recyclerTwo.adapter = adapterTwo
val orientation = DragDropSwipeRecyclerView.ListOrientation.VERTICAL_LIST_WITH_VERTICAL_DRAGGING
orientation.removeSwipeDirectionFlag(DragDropSwipeRecyclerView.ListOrientation.DirectionFlag.LEFT)
recyclerTwo.orientation = orientation

The above code will make both recyclers unswipable in either directions instead of making then swipable in different directions.

Java example?

Hi is there a java example of this ? :) would be nice

Long Click Event not fired while refresh items short periodically

Thanks for your great library.
I have implemented my fragments which shows live prices with your recyclerview.
But I have a problem with item long click listener.
The issue is that item long click events are not fired when refresh items per 500ms or less time.
How can I solve this issue?

Best.

Some questions regarding the example app

I noticed a few things in your example app:

  1. You set the divider and item_layout via XML, but at the same time, the BaseListFragment subclasses set the divider and item_layout programmatically. Should users follow this? If this is the case the README should be updated since the README only talks about setting it in via XML.

  2. Should we implement the same logic found in onItemAddedListener in the BaseListFragment, in order to add new items to the RecyclerView? Specifically, I'm puzzled as to why you had to call adapter.insertItem(position, item)--does this mean the adapter doesn't hold a reference to the list that was passed to its constructor?

  3. In fragment_vertical_list.xml, why are you setting behind_swiped_item_bg_color to @color/swipeBehindBackground, but on VerticalListFragment's setupLayoutBehindItemLayoutOnSwiping method, you are setting behindSwipedItemBackgroundColor to @null? Why are you duplicating the setting of the color?

DragDropSwipeRecyclerview does not recycle when is within NestedScrollView

I've been trying to use the recycler view within a NestedScrollView but it seems to lose all of the recycle-ability, I've searched around stack overflow and I've tried enabling/disabling isNestedScrollEnabled but doesn't seem to work.
Normal RecyclerView works just normal in nestedScroll View

Crash - ArrayIndexOutOfBoundsException

PID: 28622
java.lang.ArrayIndexOutOfBoundsException: length=6; index=-1
at java.util.ArrayList.get(ArrayList.java:413)
at com.ernestoyaquello.dragdropswiperecyclerview.DragDropSwipeAdapter.onIsDraggingImpl(DragDropSwipeAdapter.kt:571)
at com.ernestoyaquello.dragdropswiperecyclerview.DragDropSwipeAdapter.access$onIsDraggingImpl(DragDropSwipeAdapter.kt:26)
at com.ernestoyaquello.dragdropswiperecyclerview.DragDropSwipeAdapter$itemLayoutPositionListener$1.onPositionChanged(DragDropSwipeAdapter.kt:344)
at com.ernestoyaquello.dragdropswiperecyclerview.util.DragDropSwipeTouchHelper.onChildDrawImpl(DragDropSwipeTouchHelper.kt:211)
at com.ernestoyaquello.dragdropswiperecyclerview.util.DragDropSwipeTouchHelper.onChildDraw(DragDropSwipeTouchHelper.kt:159)
at androidx.recyclerview.widget.ItemTouchHelper$Callback.onDraw(ItemTouchHelper.java:1983)
at androidx.recyclerview.widget.ItemTouchHelper.onDraw(ItemTouchHelper.java:561)
at androidx.recyclerview.widget.RecyclerView.onDraw(RecyclerView.java:4284)
at android.view.View.draw(View.java:18410)
at androidx.recyclerview.widget.RecyclerView.draw(RecyclerView.java:4219)
at android.view.View.updateDisplayListIfDirty(View.java:17388)
at android.view.View.draw(View.java:18172)
at android.view.ViewGroup.drawChild(ViewGroup.java:3969)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3755)
at android.view.View.updateDisplayListIfDirty(View.java:17383)
at android.view.View.draw(View.java:18172)
at android.view.ViewGroup.drawChild(ViewGroup.java:3969)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3755)
at android.view.View.draw(View.java:18413)
at android.view.View.updateDisplayListIfDirty(View.java:17388)
at android.view.View.draw(View.java:18172)
at android.view.ViewGroup.drawChild(ViewGroup.java:3969)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3755)
at androidx.constraintlayout.widget.ConstraintLayout.dispatchDraw(ConstraintLayout.java:2023)
at android.view.View.draw(View.java:18413)
at android.view.View.updateDisplayListIfDirty(View.java:17388)
at android.view.View.draw(View.java:18172)
at android.view.ViewGroup.drawChild(ViewGroup.java:3969)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3755)
at android.view.View.updateDisplayListIfDirty(View.java:17383)
at android.view.View.draw(View.java:18172)
at android.view.ViewGroup.drawChild(ViewGroup.java:3969)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3755)
at android.view.View.updateDisplayListIfDirty(View.java:17383)
at android.view.View.draw(View.java:18172)
at android.view.ViewGroup.drawChild(ViewGroup.java:3969)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3755)
at android.view.View.updateDisplayListIfDirty(View.java:17383)
at android.view.View.draw(View.java:18172)
at android.view.ViewGroup.drawChild(ViewGroup.java:3969)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3755)
at android.view.View.updateDisplayListIfDirty(View.java:17383)
at android.view.View.draw(View.java:18172)
at android.view.ViewGroup.drawChild(ViewGroup.java:3969)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3755)
at android.view.View.draw(View.java:18413)
at com.android.internal.policy.DecorView.draw(DecorView.java:967)
at android.view.View.updateDisplayListIfDirty(View.java:17388)
at android.view.ThreadedRenderer.updateViewTreeDisplayList(ThreadedRenderer.java:722)
at android.view.ThreadedRenderer.updateRootDisplayList(ThreadedRenderer.java:728)
at android.view.ThreadedRenderer.draw(ThreadedRenderer.java:836)
at android.view.ViewRootImpl.draw(ViewRootImpl.java:3181)
at android.view.ViewRootImpl.performDraw(ViewRootImpl.java:2977)
at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2565)
at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1550)
at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:7189)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:959)
2019-08-25 15:29:06.805 28622-28622/com.example.sv.testingApp E/AndroidRuntime: at android.view.Choreographer.doCallbacks(Choreographer.java:734)
at android.view.Choreographer.doFrame(Choreographer.java:670)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:945)
at android.os.Handler.handleCallback(Handler.java:751)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6776)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1520)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1410)

[Features] Firestore/Firebase support

Hi @ernestoyaquello,

I'm trying to integrate this with some workaround implementation of firestore adapter from Firebase UI samples. However, it gives me an error throwing out of bounds exception (since I cannot access the internal code of your library). It would be nice to have a firebase or firestore adapter support.

PS. I want to mention that I'm having fun using your library. Thank you for your impressive open-source work.

No updateDataSet() Method

I see that you made the adapter take in the dataset inside the constructor. Would it be possible to update this to include either the dataset in the constructor or use a method called updateDataset(list:Mutablelist){}. This would allow the use of DiffUtil in adapters. Would you be able to possibly add that as a method and allow the constructor list to be null-able?

Remove default delete action

Thanks for working on the swipe functionality. I have one further suggestion. Currently the library fires the ‘onItemSwiped’ callback and immediately removes the item from the array list. This makes it impossible to add undo/other functionality as I cannot intercept the delete.

I have pulled the library and simply deleted the ‘remove’ function call. I can then call ‘remove’ from my own app whenever I like. In my case I show a confirmation dialog in the onItemSwiped before calling remove.

Feature request

Is there any way to change position only two list items (swipe only two) views. That means the the dragged one and the one where the dragged item is dropped.

Swipe background color corner radius

Hi @ernestoyaquello
First of all thanks a lot for this wonderful library 👍

I've just started using it so I might miss something but I am using MaterialCardView for the list item layout - swipe background comes without corner radius on it 😞

It can be easily demonstrated in your sample app if you set the corner radius to 20dp (in list_item_vertical_list_cardview.xml) for example.
I've made a quick demo video on this:

ezgif com-video-to-gif

In my code, I need to set the corner radius to 0dp to avoid such an issue 😞
Can you please help with this?

No Java example.

Spent a long time trying to decode the Kotlin example to work in Java, and still having troubles. At this point, i'm not sure if it's me, or it simply isn't compatible. A Java example would be useful.

Crash

Process: com.macoev.nanana, PID: 7851 java.lang.ArrayIndexOutOfBoundsException: length=2; index=-1 at java.util.ArrayList.get(ArrayList.java:439) at com.ernestoyaquello.dragdropswiperecyclerview.DragDropSwipeAdapter.onIsDraggingImpl(DragDropSwipeAdapter.kt:549) at com.ernestoyaquello.dragdropswiperecyclerview.DragDropSwipeAdapter.access$onIsDraggingImpl(DragDropSwipeAdapter.kt:22) at com.ernestoyaquello.dragdropswiperecyclerview.DragDropSwipeAdapter$itemLayoutPositionListener$1.onPositionChanged(DragDropSwipeAdapter.kt:339) at com.ernestoyaquello.dragdropswiperecyclerview.util.DragDropSwipeTouchHelper.onChildDrawImpl(DragDropSwipeTouchHelper.kt:211) at com.ernestoyaquello.dragdropswiperecyclerview.util.DragDropSwipeTouchHelper.onChildDraw(DragDropSwipeTouchHelper.kt:159) at androidx.recyclerview.widget.ItemTouchHelper$Callback.onDraw(ItemTouchHelper.java:1983) at androidx.recyclerview.widget.ItemTouchHelper.onDraw(ItemTouchHelper.java:561) at androidx.recyclerview.widget.RecyclerView.onDraw(RecyclerView.java:4284) at android.view.View.draw(View.java:19225) at androidx.recyclerview.widget.RecyclerView.draw(RecyclerView.java:4219) at android.view.View.updateDisplayListIfDirty(View.java:18175) at android.view.View.draw(View.java:18953) at android.view.ViewGroup.drawChild(ViewGroup.java:4218) at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4004) at android.view.View.updateDisplayListIfDirty(View.java:18166) at android.view.View.draw(View.java:18953) at android.view.ViewGroup.drawChild(ViewGroup.java:4218) at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4004) at android.view.View.draw(View.java:19228) at android.view.View.updateDisplayListIfDirty(View.java:18175) at android.view.View.draw(View.java:18953) at android.view.ViewGroup.drawChild(ViewGroup.java:4218) at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4004) at androidx.constraintlayout.widget.ConstraintLayout.dispatchDraw(ConstraintLayout.java:2070) at android.view.View.draw(View.java:19228) at android.view.View.updateDisplayListIfDirty(View.java:18175) at android.view.View.draw(View.java:18953) at android.view.ViewGroup.drawChild(ViewGroup.java:4218) at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4004) at android.view.View.updateDisplayListIfDirty(View.java:18166) at android.view.View.draw(View.java:18953) at android.view.ViewGroup.drawChild(ViewGroup.java:4218) at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4004) at androidx.constraintlayout.widget.ConstraintLayout.dispatchDraw(ConstraintLayout.java:2070) at android.view.View.draw(View.java:19228) at android.view.View.updateDisplayListIfDirty(View.java:18175) at android.view.View.draw(View.java:18953) at android.view.ViewGroup.drawChild(ViewGroup.java:4218) at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4004) at android.view.View.updateDisplayListIfDirty(View.java:18166) at android.view.View.draw(View.java:18953) at android.view.ViewGroup.drawChild(ViewGroup.java:4218) at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4004) at android.view.View.updateDisplayListIfDirty(View.java:18166) at android.view.View.draw(View.java:18953) at android.view.ViewGroup.drawChild(ViewGroup.java:4218) at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4004) at android.view.View.updateDisplayListIfDirty(View.java:18166) at android.view.View.draw(View.java:18953) at android.view.ViewGroup.drawChild(ViewGroup.java:4218) at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4004) at android.view.View.updateDisplayListIfDirty(View.java:18166) at android.view.View.draw(View.java:18953) at android.view.ViewGroup.drawChild(ViewGroup.java:4218) at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4004) at android.view.View.draw(View.java:19228) at com.android.internal.policy.DecorView.draw(DecorView.java:786) at android.view.View.updateDisplayListIfDirty(View.java:18175) 2019-01-08 18:23:05.652 7851-7851/com.macoev.nanana E/AndroidRuntime: at android.view.ThreadedRenderer.updateViewTreeDisplayList(ThreadedRenderer.java:647) at android.view.ThreadedRenderer.updateRootDisplayList(ThreadedRenderer.java:653) at android.view.ThreadedRenderer.draw(ThreadedRenderer.java:761) at android.view.ViewRootImpl.draw(ViewRootImpl.java:3027) at android.view.ViewRootImpl.performDraw(ViewRootImpl.java:2831) at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2384) at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1416) at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:6845) at android.view.Choreographer$CallbackRecord.run(Choreographer.java:966) at android.view.Choreographer.doCallbacks(Choreographer.java:778) at android.view.Choreographer.doFrame(Choreographer.java:713) at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:952) at android.os.Handler.handleCallback(Handler.java:789) at android.os.Handler.dispatchMessage(Handler.java:98) at android.os.Looper.loop(Looper.java:164) at android.app.ActivityThread.main(ActivityThread.java:6798) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)

How to simulate:
Create a draggable adapter with at least 2 elements.
Quickly click on one and next on the other until the crash comes.
Please let me know if you need any further info or explanation.
I need this to be fixed. Thanks in advance!

Add onListScrollStateChanged to OnListScrollListener

As far as I've seen from the code, onScrolled(RecyclerView recyclerView, int dx, int dy) is used for onListScrolled(scrollDirection: OnListScrollListener.ScrollDirection, distance: Int).
But onScrollStateChanged(RecyclerView recyclerView, int newState) is unsued.

What about adding a new method to the listener to indicate changes in the state of the scroll? I think the changes in the code would be pretty small.

This feature could be helpful in some situations.

Looking forward to feedback.

Disable Swipe

I want to disable swipe on some screen programmatically?unable to do this

Inheritance

can we use this adapter without inheritance. I mean I must use composition. How to do that

Does not draw divider and behindSwipedItemIcon etc.

Hi, my divider is not displayed and everything that should appear in the background (icons and color). Swipe works, but when the swipe does not appear the icon and the background color, as well as the listeners do not work. I specified parameters both through the XML and in the code. Nothing has changed. Perhaps this is due to the fact that the list is inside in ViewPager?!

My main layout

<androidx.coordinatorlayout.widget.CoordinatorLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@color/colorBackground"
        android:fitsSystemWindows="true">

    <com.google.android.material.appbar.AppBarLayout
            android:layout_width="match_parent"
            android:layout_height="@dimen/report_app_bar_height"
            android:background="@color/colorBackground"
            android:theme="@style/AppTheme.AppBarOverlay">

        <com.google.android.material.appbar.CollapsingToolbarLayout
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:fitsSystemWindows="true"
                android:minHeight="@dimen/bar_default_height"
                android:theme="@style/WalletCollapsedBar"
                app:layout_scrollFlags="scroll|exitUntilCollapsed"
                app:titleEnabled="false">

            <RelativeLayout
                    android:id="@+id/dashboard_diagram_container"
                    android:layout_width="match_parent"
                    android:layout_height="@dimen/diagram_height"
                    android:paddingBottom="@dimen/default_very_small_margin"
                    android:background="@color/colorPrimary"/>

            <TextView
                    android:id="@+id/diagram_place_holder"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:gravity="center"
                    android:text="@string/diagram_place_holder"
                    android:layout_gravity="center"
                    android:textColor="@color/colorAccent"/>

            <com.gigamole.navigationtabstrip.NavigationTabStrip
                    android:id="@+id/nav_tab_period"
                    android:layout_width="match_parent"
                    android:layout_height="@dimen/tab_period_height"
                    android:layout_gravity="bottom"
                    android:layout_marginBottom="@dimen/default_very_small_margin"
                    android:fitsSystemWindows="true"
                    app:layout_collapseMode="pin"
                    app:nts_animation_duration="300"
                    app:nts_color="@color/colorAccent"
                    app:nts_corners_radius="@dimen/tab_period_radius"
                    app:nts_inactive_color="@color/colorPrimaryDark"
                    app:nts_active_color="@color/colorAccent"
                    app:nts_size="@dimen/default_middle_margin"
                    app:nts_type="point"
                    app:nts_weight="@dimen/tab_period_nts_weight"/>

        </com.google.android.material.appbar.CollapsingToolbarLayout>

    </com.google.android.material.appbar.AppBarLayout>

    <androidx.viewpager.widget.ViewPager
            android:id="@+id/dashboard_view_pager"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:layout_behavior="@string/appbar_scrolling_view_behavior"/>

</androidx.coordinatorlayout.widget.CoordinatorLayout>

ViewPager has two fragments in which lists

<androidx.constraintlayout.widget.ConstraintLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:id="@+id/total_sum_layout"
        android:background="@color/colorBackground"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

    <View android:id="@+id/sum_background_view"
          android:layout_width="match_parent"
          android:layout_height="80dp"
          android:background="@color/colorSeparator"
          app:layout_constraintTop_toTopOf="parent"
          app:layout_constraintStart_toStartOf="parent"
          app:layout_constraintEnd_toEndOf="parent"/>

    <TextView
            android:id="@+id/main_tv_total_sum_title"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/total_sum_layout"
            android:textColor="@android:color/black"
            android:textSize="@dimen/default_big_text_size"
            app:layout_constraintStart_toStartOf="@+id/sum_background_view"
            app:layout_constraintEnd_toEndOf="@+id/sum_background_view"
            android:layout_marginTop="@dimen/default_small_margin"
            app:layout_constraintTop_toTopOf="@+id/sum_background_view"/>

    <TextView
            android:id="@+id/main_tv_total_sum"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginStart="@dimen/default_middle_margin"
            android:layout_marginTop="@dimen/default_very_small_margin"
            android:textColor="@color/colorAccent"
            android:gravity="center"
            android:textSize="@dimen/default_middle_text_size"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/main_tv_total_sum_title"
            android:layout_marginEnd="@dimen/default_middle_margin"
            app:layout_constraintEnd_toEndOf="parent"
            android:layout_marginBottom="8dp"
            app:layout_constraintBottom_toBottomOf="@+id/sum_background_view"/>


    <com.ernestoyaquello.dragdropswiperecyclerview.DragDropSwipeRecyclerView
            android:id="@+id/recycler_spend"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            app:item_layout="@layout/item_spend_list"
            app:divider="@drawable/list_divider"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/sum_background_view"/>

</androidx.constraintlayout.widget.ConstraintLayout>

Adapter

class SpendAdapter(
    private val items: MutableList<Spend>,
    val presenter: DashboardContract.Presenter
) : DragDropSwipeAdapter<Spend, SpendAdapter.SpendViewHolder>(items) {


    override fun onBindViewHolder(item: Spend, viewHolder: SpendViewHolder, position: Int) {
        val wallet = presenter.getWalletByID(item.walletId)
        viewHolder.tvWalletName.text = wallet.name
        viewHolder.tvSpendSum.text = "${item.value} ${wallet.currency.shortName}"
        viewHolder.tvCategory.text = presenter.getCategoryByID(item.categoryId).name
        viewHolder.tvDate.text = DateUtils.getFormattedDate(item.timeStamp)
        viewHolder.tvNote.text = item.note
    }

    override fun getViewHolder(itemView: View) =
        SpendViewHolder(itemView)

    override fun getViewToTouchToStartDraggingItem(item: Spend, viewHolder: SpendViewHolder, position: Int): View? {
        return viewHolder.fgContainer
    }

    internal fun addButch(items: MutableList<Spend>) {
        this.items.clear()
        this.items.addAll(items)
    }

    class SpendViewHolder : DragDropSwipeAdapter.ViewHolder {

        @BindView(R.id.spend_item_row_fg)
        internal lateinit var fgContainer: ConstraintLayout
        @BindView(R.id.spend_tv_wallet_name)
        internal lateinit var tvWalletName: TextView
        @BindView(R.id.spend_tv_sum)
        internal lateinit var tvSpendSum: TextView
        @BindView(R.id.spend_tv_category_name)
        internal lateinit var tvCategory: TextView
        @BindView(R.id.spend_tv_date)
        internal lateinit var tvDate: TextView
        @BindView(R.id.spend_tv_note_name)
        internal lateinit var tvNote: TextView

        constructor(itemView: View) : super(itemView) {
            ButterKnife.bind(this, itemView)
        }
    }
}

 Code in fragment

    @BindView(R.id.recycler_spend)
    internal lateinit var recyclerSpend: DragDropSwipeRecyclerView
    private var spendAdapter: SpendAdapter? = null

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        initList()
    }

    private fun initList() {
        recyclerSpend.layoutManager = LinearLayoutManager(activity)
        recyclerSpend.orientation = DragDropSwipeRecyclerView.ListOrientation.HORIZONTAL_LIST_WITH_HORIZONTAL_DRAGGING
        recyclerSpend.orientation?.removeSwipeDirectionFlag(DragDropSwipeRecyclerView.ListOrientation.DirectionFlag.DOWN)
        recyclerSpend.orientation?.removeSwipeDirectionFlag(DragDropSwipeRecyclerView.ListOrientation.DirectionFlag.UP)
        recyclerSpend.behindSwipedItemIconDrawableId = R.drawable.ic_remove_white
        recyclerSpend.behindSwipedItemIconSecondaryDrawableId = R.drawable.ic_edit_white
        recyclerSpend.behindSwipedItemIconMargin = 16.toFloat()
        recyclerSpend.behindSwipedItemBackgroundColor = R.color.colorSnackBarBackground
        recyclerSpend.behindSwipedItemBackgroundSecondaryColor = R.color.colorAccent
        recyclerSpend.reduceItemAlphaOnSwiping = true

        recyclerSpend.swipeListener = object : OnItemSwipeListener<String> {
            override fun onItemSwiped(position: Int, direction: OnItemSwipeListener.SwipeDirection, item: String): Boolean {
                // Return false to indicate that the swiped item should be removed from the adapter's data set (default behaviour)
                // Return true to stop the swiped item from being automatically removed from the adapter's data set (in this case, it will be your responsibility to manually update the data set as necessary)
                return false
            }
        }
    }

    internal fun updateSpendList(list: MutableList<Spend>) {
        spendAdapter = SpendAdapter(list, presenter) //How to update adapter recyclerSpend.adapter?.notifyDataSetChanged() - doesn't work
        recyclerSpend.adapter = spendAdapter
    }

Bug - Empty items are drawn on on dragging

I faced a strange bug. I have grid recycler (3 cols) with for example 50 draggable and 50 non-draggable items. When I'm dragging an item to the botom and release after the point where last draggable item goes out of the screen and gets recycled, scroll up to the place of last draggable position (where my dragged view is located now), I'm seeing 3 empty cells
image

Swipe only one Direction and DiffUtil

Hey, is it possible only to allow swiping in one direction (primary or secondary)? Possibly they could be renamed to Left/Right or Start/End to follow convention?
Also it would be great if the Adapter would feature the DiffUtil ListAdapter for nice animations :)

behindSwipedItemLayout disappears on reinitializing the adapter

View Used:: DragDropSwipeRecyclerView
Adapter Used:: DragDropSwipeAdapter

XML

    `<com.ernestoyaquello.dragdropswiperecyclerview.DragDropSwipeRecyclerView`
        android:layout_width="match_parent"
        android:id="@+id/rv_orders"
        app:behind_swiped_item_custom_layout="@layout/behind_swiped_vertical_list"
        app:behind_swiped_item_custom_layout_secondary="@layout/behind_swiped_vertical_list_secondary"
        android:layout_height="match_parent" />`

Main Activity

`private fun setupRecyclerView(orders: List<OrderSingle>) {
    if (swipeRefresh.isRefreshing) {
        swipeRefresh.isRefreshing = false
    }
    if(currentPage == 1) {
        mainOrdersList = orders.toMutableList()
        layoutManager = LinearLayoutManager(this)
        rv_orders.layoutManager = layoutManager
        adapter = OrdersAdapter(this, this, mainOrdersList, mainOrdersList, status!!)
        rv_orders.adapter = adapter
        adapter.notifyDataSetChanged()
        rv_orders.orientation = DragDropSwipeRecyclerView.ListOrientation.VERTICAL_LIST_WITH_VERTICAL_DRAGGING
        rv_orders.behindSwipedItemLayoutId = R.layout.behind_swiped_vertical_list
        rv_orders.behindSwipedItemSecondaryLayoutId = R.layout.behind_swiped_vertical_list_secondary
        rv_orders.reduceItemAlphaOnSwiping = true
        rv_orders.scrollListener = onListScrollListener
        rv_orders.dragListener = onItemDragListener
        rv_orders.swipeListener = onItemSwipeListener
        rv_orders.disableSwipeDirection(DragDropSwipeRecyclerView.ListOrientation.DirectionFlag.UP)
        rv_orders.disableSwipeDirection(DragDropSwipeRecyclerView.ListOrientation.DirectionFlag.DOWN)
        rv_orders.isNestedScrollingEnabled = true
        rv_orders.setHasFixedSize(true)
        when (status) {
            "NEW" -> {
                rv_orders.disableSwipeDirection(DragDropSwipeRecyclerView.ListOrientation.DirectionFlag.RIGHT)
            }
            "PENDING" -> {
                rv_orders.disableSwipeDirection(DragDropSwipeRecyclerView.ListOrientation.DirectionFlag.LEFT)
            }
            else -> {
                rv_orders.disableSwipeDirection(DragDropSwipeRecyclerView.ListOrientation.DirectionFlag.LEFT)
                rv_orders.disableSwipeDirection(DragDropSwipeRecyclerView.ListOrientation.DirectionFlag.RIGHT)
            }
        }
    } else {
        mainOrdersList.addAll(orders)
        Log.e("More loading","SIZE " + mainOrdersList.size)
        Log.e("More loading","SIZE 2 " + orders.size)
        adapter.notifyDataSetChanged()
    }
}`

Adapter

`class OrdersAdapter(
private var context: Context,
private var listener: OnItemClickListener,
private var data: List,
private var filteredData: List,
private var statusText: String
) : DragDropSwipeAdapter<OrderSingle, OrdersAdapter.MyViewHolder>(filteredData), Filterable {

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
    val view =
        LayoutInflater.from(parent.context).inflate(R.layout.single_item_order, parent, false)
    return MyViewHolder(view)
}

override fun getItemCount(): Int {
    Log.e("COUNT", filteredData.size.toString())
    return filteredData.size
}


class MyViewHolder(view: View) : DragDropSwipeAdapter.ViewHolder(view) {
    val singleOrderItem: LinearLayout = view.findViewById(R.id.singleOrderItem)
    val orderId: TextView = view.findViewById(R.id.tv_orderId_SO)
    val status: TextView = view.findViewById(R.id.tv_status_SO)
    val name: TextView = view.findViewById(R.id.tv_name_SO)
    private val address: TextView = view.findViewById(R.id.tv_address_SO)
    val dragIcon: ImageView = view.findViewById(R.id.drag_icon)


    fun bindTo(item: OrderSingle, context: Context, statusText: String) {
        try {
            orderId.text = "ORDER ID: ${item.orderId}"

            status.text = item.orderStatus
            if(item.orderStatus == "PICKUP") {
                status.text = "REMAINING"
            }
            when (statusText) {
                "PENDING", "NEW" -> {
                    status.setTextColor(ContextCompat.getColor(context, R.color.pending))
                }
                "DELIVERED" -> {
                    status.setTextColor(ContextCompat.getColor(context, R.color.delivered))
                }
                else -> {
                    status.setTextColor(ContextCompat.getColor(context, R.color.colorPrimary))
                }
            }
            name.text = item.shipTo
            address.text = item.shippingAddress
        } catch (e: Exception) {
            e.printStackTrace()
        }
    }
}

override fun getFilter(): Filter {
    return object : Filter() {
        override fun performFiltering(charSequence: CharSequence): FilterResults? {
            val charString = charSequence.toString()
            if (charString.isEmpty()) {
                filteredData = data
            } else {
                val filteredList: MutableList<OrderSingle> = ArrayList()
                for (row in data) { // name match condition. this might differ depending on your requirement
                    if (
                        row.orderId.toLowerCase(Locale.ROOT).contains(charString.toLowerCase(Locale.ROOT)) ||
                        row.shipTo.toLowerCase(Locale.ROOT).contains(charString.toLowerCase(Locale.ROOT)) ||
                        row.shippingAddress.toLowerCase(Locale.ROOT).contains(charString.toLowerCase(Locale.ROOT)) ||
                        row.orderStatus.toLowerCase(Locale.ROOT).contains(charString.toLowerCase(Locale.ROOT)) ||
                        row.deliveryType.toLowerCase(Locale.ROOT).contains(charString.toLowerCase(Locale.ROOT))
                            ) {
                        filteredList.add(row)
                    }
                }
                filteredData = filteredList
            }
            val filterResults = FilterResults()
            filterResults.values = filteredData
            return filterResults
        }

        override fun publishResults(
            charSequence: CharSequence?,
            filterResults: FilterResults
        ) {
            filteredData = filterResults.values as List<OrderSingle>
            notifyDataSetChanged()
        }
    }
}



override fun getViewHolder(itemView: View): MyViewHolder {
    return MyViewHolder(itemView)
}


override fun getViewToTouchToStartDraggingItem(
    item: OrderSingle,
    viewHolder: MyViewHolder,
    position: Int
) = viewHolder.dragIcon

override fun onBindViewHolder(item: OrderSingle, viewHolder: MyViewHolder, position: Int) {
    viewHolder.bindTo(item, context, statusText)
    viewHolder.singleOrderItem.setOnClickListener {
        if(statusText != "NEW")
            listener.onItemClick(filteredData[position].orderId)
    }
}

}`

Whenever the list pull pulled from top to bottom, new data set is called and that in turn calls 'setupRecyclerView' and provides it with new data list and as soon as I refresh the list, both the behindSwipedItemLayout disappears and I get empty background when swiped.

New features - drag on long click & drag item animator

Hi!
The first thing I want to mention is it would be nice if you add an option to start dragging on long click (where the current touch listener in TouchHelper is)
Also it'd be a great thing if you add a feature to animate dragged view (kinda DragViewAnimator interface) (For example to scale view up on drag started and down on ended)

Sometimes items in the Reyclerview become less opaque after dataSet changes

This happens to me when I delete items from my data source (LiveData) and then I try to update the dataSet.

viewModel.items.observe(this@MyFragment, Observer { adapter.dataSet = it })

Also if you try to move the opaque item, his opacity will become normal again.

This does not happen when you use the default behavior of the swipe, which as far as I've seen uses removeItem(position: Int)

On the other hand, when adding an item everything seems to be ok.
I'm not sure this happens. I will try to reproduce it in a smaller project asap.

ezgif com-video-to-gif

Grid issue

Hello,
maybe I've not really gotten it but I can't create a grid view with 5 columns and 2 rows.

mList.numOfColumnsPerRowInGridList = 5 or mList.numOfRowsPerColumnInGridList = 2 don't have any effect.

Any hints are appreciated.

Difficulty creating views of different types

My recycler, receives some different types of item views, in my current implementation, I use the viewType inside onCreateViewHolder, to differentiate and inflate different layouts. I wonder if it is possible to do this with your library?

How do you limit swipe direction?

Seems to default to both directions but hoping for right to left only. Looks like something to do with the ListOrientation but cannot figure out the Java syntax.

disableSwipeDirection & enableSwipeDirection not working as expected

In my OnCreateView fragment, I am setting these properties based on a "lock UI" preference, which prevents swiping left/right/reordering.

In short, I need to restart the activity for this to take effect, it doesn't work setting this within the fragment OnCreateView, even though the code paths are being executed at the expected time. Is there something else I need to do here, or is this a bug?

Thanks.

_binding.list.setOrientation(DragDropSwipeRecyclerView.ListOrientation.VERTICAL_LIST_WITH_VERTICAL_DRAGGING);

if (PreferenceManager.getDefaultSharedPreferences(getContext()).getBoolean("UI_LOCKED", false))
{
    _binding.list.disableSwipeDirection(DragDropSwipeRecyclerView.ListOrientation.DirectionFlag.LEFT);
    _binding.list.disableSwipeDirection(DragDropSwipeRecyclerView.ListOrientation.DirectionFlag.RIGHT);
}
else
{
    _binding.list.enableSwipeDirection(DragDropSwipeRecyclerView.ListOrientation.DirectionFlag.LEFT);
    _binding.list.enableSwipeDirection(DragDropSwipeRecyclerView.ListOrientation.DirectionFlag.RIGHT);
}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.