vinc3m1 / dragsortadapter Goto Github PK
View Code? Open in Web Editor NEWDrag and drop re-ordering adapter for RecyclerView
License: Other
Drag and drop re-ordering adapter for RecyclerView
License: Other
I created a Trello style component based on your work. Drag-and-drop among multiple adapters feature is supported. But I had to modify your source code to achieve that instead of the subclass way. So what should I do if I wanna use your code? Should I just use your code in my repo and put your name into the credit section or something else? Can you give some advice? Thanks in advance!
I'm getting an error when I use exaclly the same code as your example.
The error:
No enclosing instance of type 'com.makeramen.dragsortadapter.DragSortAdapter' is in scope
My code:
package com.weshopit.android.presentation.views.adapters;
import android.graphics.Point;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import com.makeramen.dragsortadapter.DragSortAdapter;
import com.makeramen.dragsortadapter.NoForegroundShadowBuilder;
import com.weshopit.android.R;
import com.weshopit.android.data.entities.Item;
import java.util.List;
import butterknife.ButterKnife;
import butterknife.InjectView;
import timber.log.Timber;
public class ItemsAdapter extends DragSortAdapter<ItemsAdapter.ItemsViewHolder> {
private List<Item> mList;
public ItemsAdapter(RecyclerView recyclerView, List<Item> list) {
super(recyclerView);
mList = list;
}
@Override
public ItemsViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
View view = LayoutInflater.from(viewGroup.getContext())
.inflate(android.R.layout.simple_list_item_1, viewGroup, false);
ItemsViewHolder holder = new ItemsViewHolder(this, view);
view.setOnClickListener(holder);
view.setOnLongClickListener(holder);
return holder;
}
@Override
public void onBindViewHolder(final ItemsViewHolder viewHolder, final int position) {
Item item = mList.get(position);
viewHolder.mName.setText(item.name);
// NOTE: check for getDraggingId() match to set an "invisible space" while dragging
viewHolder.container.setVisibility(getDraggingId() == item.id ? View.INVISIBLE : View.VISIBLE);
viewHolder.container.postInvalidate();
}
@Override
public int getItemCount() {
return mList.size();
}
@Override
public long getItemId(int position) {
return mList.get(position).id;
}
@Override
public int getPositionForId(long id) {
for(final Item item : mList){
if(item.id == id){
return mList.indexOf(item);
}
}
return 0;
}
@Override
public boolean move(int fromPosition, int toPosition) {
mList.add(toPosition, mList.remove(fromPosition));
return true;
}
static class ItemsViewHolder extends DragSortAdapter.ViewHolder implements
View.OnLongClickListener, View.OnClickListener{
@InjectView(R.id.container) ViewGroup container;
@InjectView(android.R.id.text1) TextView mName;
public ItemsViewHolder(DragSortAdapter adapter, View view) {
super(adapter, view);
ButterKnife.inject(this, view);
}
@Override
public void onClick(View v) {
Timber.d(mName.getText().toString() + " clicked!");
}
@Override
public boolean onLongClick(View v) {
startDrag();
return true;
}
@Override
public View.DragShadowBuilder getShadowBuilder(View itemView, Point touchPoint) {
return new NoForegroundShadowBuilder(itemView, touchPoint);
}
}
}
I change Integer to String with hashCode()
and it'll crash if I drag the item.It's like #11 .Could you show me a right example how to use it ? Thank you very much!
Hi,
I couldn't see any dependency to Api 14.
Is there any reason to make minSdk to 14?
Could you please make it 11 on the next commit?
When I trie to update compile and target versions to 23 its all good if I leave compile 'com.android.support:recyclerview-v7:22.1.0'. But when I change it to 23.1.1 DragSortAdapter can't import android.support.v7.widget.RecyclerView; . Do you have any suggestions how I can fix it.
Thanks.
If I drag fast and for a longer time up and down, I can see that sometimes items disappear... Their place is empty...
I also encountered that the dragged view that is animated in the recyclerview sometimes disappers and sometimes is visible...
Is there any solution for that?
Picking an item up works as expected but when releasing the drag gesture there is a split second where the dragged item is gone and the new item has not yet appeared. I would hope that it is possible to not have that minor delay between releasing the dragged item and the appearance of the new item.
Otherwise... great library. :)
I have tried the demo and everything goes fine.However when I change List to List it will crash if I drag the item.I thought it might be caused by getItemId
because I only change this method when changing from List to List as data.
I wonder how to do it with String data.Thank you very much.
Just a improvement...
Can you provide a screenshot or a screenrecording of the library.
See https://issuetracker.google.com/issues/111758625
OnDrag in DragManager.java does not receive dragInfo other than null so dragging never starts.
This is visible in the example app.
When I swap over items from within the list (say items 10 and 11 for example), they swap absolutely perfectly and the animations all look good.
When swapping the first two items I see very weird animations where the components swap places several times. This happens regardless of the layout manager, but it is easier to observe the grid layout manager.
After fast double touch on the cell which I call startDrag on onTouch method, the app crash with the following exception:
java.lang.IllegalStateException: Cannot call this method while RecyclerView is computing a layout or scrolling
at android.support.v7.widget.RecyclerView.assertNotInLayoutOrScroll(RecyclerView.java:1941)
at android.support.v7.widget.RecyclerView$RecyclerViewDataObserver.onItemRangeChanged(RecyclerView.java:3986)
at android.support.v7.widget.RecyclerView$AdapterDataObservable.notifyItemRangeChanged(RecyclerView.java:8957)
at android.support.v7.widget.RecyclerView$Adapter.notifyItemChanged(RecyclerView.java:5395)
at com.makeramen.dragsortadapter.DragManager$2.onAnimationsFinished(DragManager.java:120)
at android.support.v7.widget.RecyclerView$ItemAnimator.dispatchAnimationsFinished(RecyclerView.java:9775)
at android.support.v7.widget.DefaultItemAnimator.dispatchFinishedWhenDone(DefaultItemAnimator.java:525)
at android.support.v7.widget.DefaultItemAnimator.access$800(DefaultItemAnimator.java:34)
at android.support.v7.widget.DefaultItemAnimator$8.onAnimationEnd(DefaultItemAnimator.java:379)
at android.support.v4.view.ViewPropertyAnimatorCompatJB$1.onAnimationEnd(ViewPropertyAnimatorCompatJB.java:47)
at android.view.ViewPropertyAnimator$AnimatorEventListener.onAnimationEnd(ViewPropertyAnimator.java:1116)
at android.animation.ValueAnimator.endAnimation(ValueAnimator.java:1089)
at android.animation.ValueAnimator.cancel(ValueAnimator.java:992)
at android.view.ViewPropertyAnimator.cancel(ViewPropertyAnimator.java:429)
at android.support.v4.view.ViewPropertyAnimatorCompatICS.cancel(ViewPropertyAnimatorCompatICS.java:102)
at android.support.v4.view.ViewPropertyAnimatorCompat$ICSViewPropertyAnimatorCompatImpl.cancel(ViewPropertyAnimatorCompat.java:462)
at android.support.v4.view.ViewPropertyAnimatorCompat.cancel(ViewPropertyAnimatorCompat.java:1049)
at android.support.v7.widget.DefaultItemAnimator.endAnimation(DefaultItemAnimator.java:425)
at android.support.v7.widget.DefaultItemAnimator.animateChange(DefaultItemAnimator.java:315)
at android.support.v7.widget.RecyclerView.animateChange(RecyclerView.java:3001)
at android.support.v7.widget.RecyclerView.dispatchLayout(RecyclerView.java:2804)
at android.support.v7.widget.RecyclerView.onLayout(RecyclerView.java:3011)
at android.view.View.layout(View.java:15596)
at android.view.ViewGroup.layout(ViewGroup.java:4966)
at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1703)
at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1557)
at android.widget.LinearLayout.onLayout(LinearLayout.java:1466)
at android.view.View.layout(View.java:15596)
at android.view.ViewGroup.layout(ViewGroup.java:4966)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:573)
at android.widget.FrameLayout.onLayout(FrameLayout.java:508)
at android.view.View.layout(View.java:15596)
at android.view.ViewGroup.layout(ViewGroup.java:4966)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:573)
at android.widget.FrameLayout.onLayout(FrameLayout.java:508)
at android.view.View.layout(View.java:15596)
at android.view.ViewGroup.layout(ViewGroup.java:4966)
at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1703)
at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1557)
at android.widget.LinearLayout.onLayout(LinearLayout.java:1466)
at android.view.View.layout(View.java:15596)
at android.view.ViewGroup.layout(ViewGroup.java:4966)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:573)
at android.widget.FrameLayout.onLayout(FrameLayout.java:508)
at android.view.View.layout(View.java:15596)
at android.view.ViewGroup.layout(ViewGroup.java:4966)
at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1703)
at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1557)
at android.widget.LinearLayout.onLayout(LinearLayout.java:1466)
at android.view.View.layout(View.java:15596)
at android.view.ViewGroup.layout(ViewGroup.java:4966)
at android.support.v4.widget.DrawerLayout.onLayout(DrawerLayout.jav```
Not sure what the cause is, but I'm guessing it might actually be an issue with LinearLayoutManager
Edit: I proposed a (working) solution that addresses my problem, see 68ad231. (However, I messed up the datatype, it should be RecyclerView.ViewHolder
instead of ViewHolder
, so I can't make a PR).
One of my app's screens is supposed to use nested RecyclerViews, each with DragSort functionality.
Please don't unleash the lists-in-lists-hate on me, it does have its purpose and I am aware that this may confuse users (which is why I disabled scrolling for the child RecyclerViews). While my View hierarchy may certainly be disputable, I still think this is worth a bug report. I'm open to refactoring suggestions regarding my View hierarchy, but I probably won't be able to handle everything in one list (with indent levels and such) because the DragSorting will get messed up.
Under certain circumstances (see below, "Reproducing the crash") I get the following exception:
java.lang.NullPointerException: Attempt to invoke virtual method 'int android.support.v7.widget.RecyclerView$ViewHolder.getAdapterPosition()' on a null object reference
at com.makeramen.dragsortadapter.DragManager.onDrag(DragManager.java:36)
at android.view.View.dispatchDragEvent(View.java:18321)
at android.view.ViewGroup.dispatchDragEvent(ViewGroup.java:1492)
at android.view.ViewGroup.notifyChildOfDrag(ViewGroup.java:1523)
at android.view.ViewGroup.dispatchDragEvent(ViewGroup.java:1365)
at android.view.ViewGroup.notifyChildOfDrag(ViewGroup.java:1523)
...
at android.view.ViewRootImpl.handleDragEvent(ViewRootImpl.java:5073)
...
The ViewGroup methods get called a dozen times because the DragEvent is being passed down from the very root View down to the View hierarchy's very "leaves".
This is what my View looks like:
The child list with the yellow background is a non-scrollable RecyclerView ("NoScrollRecyclerView") that's being attached to parent list item [43] by my root list's Adapter.
Each RV (be it root or child) has its own distinct DragSortAdapter (yup, I double checked this).
I spent the last five hours in the Android Studio debugger, trying to find whether there is something wrong on on my end, I quadruple checked the itemId
s being assigned to the respective ViewHolders, but everything seems fine.
The NullPointer
derives from the fact that this library will sometimes find the wrong RecyclerView, therefore recyclerView.findViewHolderForItemId(itemId)
will not find the item because it doesn't hold that ViewHolder. For some reason, the DragManager doesn't know which RecyclerView
's element is being dragged. I went to investigate deeper.
As you can see in the stack trace, the DragEvent is being dispatched for all children of the application's very root view, and it will bubble all the way down to the (child) NoScrollRecyclerView
s in my layout, even though dragStart()
and the DragEvent were triggered from within the (root) RecyclerView
.
The NullPointer
occurs when:
The NullPointer
does NOT occur when:
The NullPointer
occurs because the View passed to DragManager.onDrag()
by the Android Framework is the wrong RV, except when there is only one around. That may be by design, however, I don't know how to fix this.
As a consequence I tried to extend the DragManager to check the assignment for null
and simply do nothing if that's the case. However, the decompiled DragManager class is declared final and also isn't publically visible from external packages, therefore I was unable to patch this behavior by doing that.
(I don't even know if it would behave properly when the crash would not occur.)
I also tried overriding the onDrag
callback in the NoScrollRecyclerView
.
I considered overriding findViewHolderForItemId
, but I'm not sure what I am supposed to return if not null. Funny thing is, Android's documentation comment above this method states that, if you use setHasStableIds(true)
it would return non-null values. That also did not work.
Without exposing literally all of my code, it's really hard to explain the issue. You may or may not consider doing something about this - since I am using unorthodox View hierarchies.
Thanks for taking your time to help me out. I'm open to refactoring suggestions regarding my View hierarchy.
Drag the first item and slowly move down then you can see items below move fast upwards. Stop move downwards(still dragging the first item), you can see the blank space is still the first item. Keep moving down, and you'll see items below move fast upwards again.
#2 didn't solve it.
For example turning the LinearLayoutManager
horizontal in the example does not scroll the RecyclerView
while dragging:
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);
linearLayoutManager.setOrientation(LinearLayoutManager.HORIZONTAL);
recyclerView.setLayoutManager(linearLayoutManager);
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.