[英]Why does my RecyclerView with ItemTouchHelper stop dragging after only one item, after overriding getItemViewType()?
I have a simple RecyclerView that uses ItemTouchHelper to both swipe and drag items. 我有一个简单的RecyclerView,它使用ItemTouchHelper来滑动和拖动项目。 Everything worked fine until I needed to style the first and last items differently, so I needed to override the getItemViewType(int p) function in the adapter. 一切正常,直到我需要以不同方式设置第一个和最后一个项目的样式,所以我需要覆盖适配器中的getItemViewType(int p)函数。 After I did, the drag functionality stopped being fluent and always dropped the items after moving only one position up/down. 在我这样做之后,拖动功能停止流畅,并且在向上/向下移动一个位置后总是丢弃项目。 This is my RecyclerView Adapter: 这是我的RecyclerView适配器:
public class CurrentStopsAdapter extends RecyclerView.Adapter<CurrentStopsAdapter.ViewHolder> {
private RemoveFromTripListener removeFromTripListener = null;
private SwapPlacesTripListener swapPlacesTripListener = null;
private Context context;
private List<PlaceLink> stops;
public CurrentStopsAdapter(Context context, List<PlaceLink> stops,
RemoveFromTripListener removeListener, SwapPlacesTripListener swapListener) {
this.context = context;
this.stops = stops;
removeFromTripListener = removeListener;
swapPlacesTripListener = swapListener;
}
public interface RemoveFromTripListener {
void onRemoveTripButtonClick(String id);
}
public interface SwapPlacesTripListener {
void onSwapPlacesButtonClick(int first, int second);
}
@Override
public int getItemViewType(int position) {
if (position == (getItemCount()-1)) {
return -1;
}
return position;
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
switch (viewType) {
case -1:
return new ViewHolder(LayoutInflater.from(context).inflate(R.layout.list_item_destination, parent, false));
case 0:
return new ViewHolder(LayoutInflater.from(context).inflate(R.layout.list_item_origin, parent, false));
default:
return new ViewHolder(LayoutInflater.from(context).inflate(R.layout.list_item_stop, parent, false));
}
}
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
holder.bindStop(stops.get(position));
}
@Override
public int getItemCount() {
return stops.size();
}
public void remove(int position) {
if (removeFromTripListener != null) {
removeFromTripListener.onRemoveTripButtonClick(stops.get(position).getId());
}
notifyItemRemoved(position);
}
public void swap(int firstPosition, int secondPosition) {
if (swapPlacesTripListener != null) {
swapPlacesTripListener.onSwapPlacesButtonClick(firstPosition, secondPosition);
}
notifyItemMoved(firstPosition, secondPosition);
}
public class ViewHolder extends RecyclerView.ViewHolder {
public final TextView placeTitle;
public ViewHolder(View view){
super(view);
placeTitle = (TextView) view.findViewById(R.id.stops_list_item_title);
}
public void bindStop(PlaceLink place){
this.placeTitle.setText(place.getTitle());
}
}
}
And My ItemTouchHelper: 和我的ItemTouchHelper:
public class TripTouchHelper extends ItemTouchHelper.SimpleCallback {
private CurrentStopsAdapter currentStopsAdapter;
public TripTouchHelper(CurrentStopsAdapter currentStopsAdapter){
super(ItemTouchHelper.UP | ItemTouchHelper.DOWN, ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT);
this.currentStopsAdapter = currentStopsAdapter;
}
@Override
public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
currentStopsAdapter.swap(viewHolder.getAdapterPosition(), target.getAdapterPosition());
return true;
}
@Override
public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
currentStopsAdapter.remove(viewHolder.getAdapterPosition());
}
}
If I skip the Override on getItemViewType and use the same layout for all items, everything works fine but I would very much like to find a solutions to this problem. 如果我跳过getItemViewType上的Override并对所有项使用相同的布局,一切正常但我非常想找到解决这个问题的方法。 Any help would be really appreciated :) 任何帮助将非常感激 :)
Adapter thinks that the both ViewHolder
you moved is considered different type because getItemViewType()
returned the type unique. Adapter认为你移动的两个ViewHolder
被认为是不同的类型,因为getItemViewType()
返回了唯一的类型。 So it should re-render. 所以它应该重新渲染。
For example, you can return the type by following my procedure: 例如,您可以按照我的过程返回类型:
return 0
for r.layout.foo 为r.layout.foo return 0
return 1
for r.layout.bar 为r.layout.bar return 1
Then you can write own method/pair to check layout when you wanted the layout by type . 然后,您可以编写自己的方法/对,以便在需要按类型布局时检查布局。 If you still need the position , you can get it after ViewHolder
is created: AdapterPosition
. 如果您还需要的位置 ,你可以得到它后ViewHolder
创建: AdapterPosition
。
If you needed position in OnCreateViewHolder()
, you have something wrong and might defeated the purpose of ViewHolder
. 如果你需要OnCreateViewHolder()
位置,你就会出错并且可能会ViewHolder
的目的。 Considered doing that work when manipulating data or when onBindViewHolder()
if not so expensive. 考虑在操作数据时执行该操作或在onBindViewHolder()
如果不那么昂贵。
Delete getItemViewType(int position) in your recyclerview adapter. 在recyclerview适配器中删除getItemViewType(int position)。 I had the same problem, and this worked. 我有同样的问题,这有效。
I think you are supposed to return a "type" as int of the item in question, not the position. 我认为你应该返回一个“类型”作为有问题的项目的int,而不是位置。 Meaning, for the header/footer types you could return one value (ex: 1), while for all other types you could return another value (ex: 2). 这意味着,对于页眉/页脚类型,您可以返回一个值(例如:1),而对于所有其他类型,您可以返回另一个值(例如:2)。 Returning position sees every movement through your types as a different View type because position will be unique, which I assume halts the drag. 返回位置通过您的类型将每个移动视为不同的视图类型,因为位置将是唯一的,我假设停止拖动。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.