2016-02-08 34 views
10

我一直在關注這個鏈接的指南"Drag and Swipe with RecyclerView - by IPaulPro",我在某些情況下幾乎沒有問題。RecyclerView拖放通過itemTouchHelper bahaving快速拖動時很奇怪

所以,我基本上做了所有他解釋+我加入項目一個TextView表示在RecyclerView項目的位置,這樣的事情: enter image description here

一切似乎不錯,除了當我啓動「彈弓射擊「物品很快,然後我有兩個問題:

  1. 它恰好有一個數字的副本。在 onItemClear()方法使用notifyAdapterSetChanged() enter image description here

    而且我所做的是 - 它固定在它的方式,反而造成 IllegalStateException,其逮住 - 會導致 IndexOutOfBounds例外。

  2. 偶爾,當刷卡速度太快時,項目會進入「背景」。這隻能看到,如果項目不是相同的大小。 enter image description here

我將粘貼下面我的整個適配器代碼,必須有一個缺陷在它的地方。

LayoutInflater inflater; 
Context context; 
AndroidEntityQuestionResult androidEntityQuestionResult; 
ArrayList<AndroidEntityAnswer> list = new ArrayList<>(); 
ORDLayoutManagerQuestion ord; 
ScreenDimensionsConstants sdc; 


public OrderingRecycleAdapter(Context context, AndroidEntityQuestionResult androidEntityQuestionResult, ORDLayoutManagerQuestion ord) { 
    inflater = LayoutInflater.from(context); 
    this.context = context; 
    this.list = androidEntityQuestionResult.getAndroidEntityQuestion().getEntityAnswer(); 
    this.androidEntityQuestionResult = androidEntityQuestionResult; 
    this.ord = ord; 
    sdc = new ScreenDimensionsConstants(context); 
} 

@Override 
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { 
    View view = inflater.inflate(R.layout.custom_row_ordering_rv, parent, false); 
    final RecyclerView.ViewHolder holder = new OrderingViewHolder(view); 
    return holder; 
} 


@Override 
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { 
    if (holder instanceof OrderingViewHolder) { 

     ((OrderingViewHolder) holder).answerText.setText(list.get(position).getAnswer().getANSWER_TEXT()); 
     int currentPosition = position + 1; 
     ((OrderingViewHolder) holder).position.setText("#" + currentPosition); 
    } 
} 

@Override 
public int getItemCount() { 
    return list.size(); 
} 

@Override 
public boolean onItemMove(int fromPosition, int toPosition) { 
    if (fromPosition < toPosition) { 
     for (int i = fromPosition; i < toPosition; i++) { 
      Collections.swap(list, i, i + 1); 
     } 
    } else { 
     for (int i = fromPosition; i > toPosition; i--) { 
      Collections.swap(list, i, i - 1); 
     } 
    } 
    notifyItemMoved(fromPosition, toPosition); 
    notifyItemChanged(fromPosition); 
    return true; 
} 

@Override 
public void onItemDismiss(int position) { 

} 

@Override 
public void onStartDrag(RecyclerView.ViewHolder viewHolder) { 
     ord.getItemTouchHelper().startDrag(viewHolder); 
} 

class OrderingViewHolder extends RecyclerView.ViewHolder implements ItemTouchHelperViewHolder { 
    private TextView answerText; 
    private ImageView pin; 
    private TextView position; 

    public OrderingViewHolder(View itemView) { 
     super(itemView); 
     answerText = (TextView) itemView.findViewById(R.id.orderingAnswer); 
     answerText.setTextSize(TypedValue.COMPLEX_UNIT_PX, sdc.getHeight()/40); 

     pin = (ImageView) itemView.findViewById(R.id.ordering_pin); 
     pin.getLayoutParams().width = sdc.getHeight()/15; 
     pin.getLayoutParams().height = sdc.getHeight()/15; 

     pin.setOnTouchListener(new View.OnTouchListener() { 
      @Override 
      public boolean onTouch(View v, MotionEvent event) { 
       if (MotionEventCompat.getActionMasked(event) == 
         MotionEvent.ACTION_DOWN) { 
        OrderingRecycleAdapter.this.onStartDrag(OrderingViewHolder.this); 
       } 
       return false; 
      } 
     }); 
     position = (TextView) itemView.findViewById(R.id.answer_position); 
     position.setTextSize(TypedValue.COMPLEX_UNIT_PX, sdc.getHeight()/40); 

    } 

    @Override 
    public void onItemSelected() { 
     itemView.setBackgroundResource(R.drawable.menu_item_background_ice_blue); 
    } 

    @Override 
    public void onItemClear() { 
     itemView.setBackgroundResource(R.drawable.menu_item_background_white); 
     int currentPosition = getLayoutPosition() + 1; 
     position.setText("#" + currentPosition); 
     //notifyDataSetChanged(); 

    } 
} 

獎金問題

是否有任何教程或拖動和2個RecyclerViews之間拖放相關的任何信息?

我知道這是一個問題,但沒有答案,我可能會更幸運。

+0

我也是用的代碼從你上面提到的鏈接,我也遇到了麻煩,當我在做swaping太多快,但我通過覆蓋從ItemTouchHelper.Callback擴展的類中的onSelectedChanged來解決此問題。 –

+0

你用什麼代碼覆蓋它?我使用了https://github.com/iPaulPro/Android-ItemTouchHelper-Demo/blob/master/app/src/main/java/co/paulburke/android/itemtouchhelperdemo/helper/SimpleItemTouchHelperCallback中的代碼。java – Sekula1991

+0

你想發佈我的代碼並使用它嗎?或者你想要修復? *我不想看到「我不想要代碼,我想要修復」*這就是爲什麼我問。 – Jaeger

回答

0

對我來說,似乎你的onItemMove()沒有考慮到所有的變化。 當某物移動多於一個物品時(讓我們說在A & B之間),你正在交換兩者之間的所有物品。 但是,只能向A & B報告更改,而不會報告其他元素之間的更改。

我建議你寫報告的所有變化的交換方法:)

public boolean swapItems(int fromPosition, int toPosition){ 
    Collections.swap(list, fromPosition, toPosition); 
    notifyItemMoved(fromPosition, toPosition); 
    notifyItemMoved(toPosition, fromPosition); 
    // And maybe also notifyItemChanged() as the item changes due to the shift 
    notifyItemChanged(fromPosition); 
    notifyItemChanged(toPosition); 
} 

調用此函數,而不是Collections.swap(並刪除通知代碼的其餘部分。

+0

不幸的是,這不起作用,當用這段代碼拖動一件物品時,所有物品都會在拖拽的時候改變它們的值,而看起來很奇怪,而且當物品被釋放時,物品會重新回到原來的位置。 – Sekula1991

+0

順便說一句,像我以前那樣做是不是正確 - 只有A和B項目改變他們的立場,那些在他們之間停留的地方?也許我應該通知周圍toPosition(+1 -1)的項目,因爲他們有時會干擾,我只是無法找到它發生的原因(用一些if語句如果toPosition == list.size();) – Sekula1991

2

更改onitemmove方法

@Override 
public boolean onItemMove(int fromPosition, int toPosition) { 
    if (fromPosition < toPosition) { 
     for (int i = fromPosition; i < toPosition; i++) { 
      Collections.swap(list, i, i + 1); 
     } 
    } else { 
     for (int i = fromPosition; i > toPosition; i--) { 
      Collections.swap(list, i, i - 1); 
     } 
    } 
    notifyItemMoved(fromPosition, toPosition); 
    notifyItemChanged(fromPosition); 
    return true; 
} 

到:

@Override 
public boolean onItemMove(int fromPosition, int toPosition) { 
    if (fromPosition < toPosition) { 
     for (int i = fromPosition; i < toPosition; i++) { 
      Collections.swap(list, i, i + 1); 
     } 
    } else { 
     for (int i = fromPosition; i > toPosition; i--) { 
      Collections.swap(list, i, i - 1); 
     } 
    } 
    notifyItemMoved(fromPosition, toPosition); 
    return true; 
} 
+0

不工作,你有以這種方式按位置拖動它,這不是我想要實現的。 – Sekula1991

+0

不,你不想拖動它的位置位置,只是嘗試這段代碼,並告訴我 –

+0

我的錯誤,它的位置沒有移動的位置 - 它可以通過列表移動,但它釋放時返回fromPosition和notifyItemRangeChanged強制它動態地改變被徘徊的物品的價值,看起來有點不好。 – Sekula1991