2015-06-08 17 views
53

Tôi đang sử dụng recyclerview 22.2.0 và lớp trợ giúp ItemTouchHelper.SimpleCallback để bật tùy chọn vuốt để loại bỏ tùy chọn vào danh sách của tôi. Nhưng khi tôi có một loại tiêu đề trên nó, tôi cần phải vô hiệu hóa hành vi swipe cho vị trí đầu tiên của bộ điều hợp. Như RecyclerView.Adapter không có isEnabled() phương pháp, tôi đã cố gắng để vô hiệu hóa sự tương tác xem qua các phương pháp isEnabled()isFocusable() trong việc tạo ra ViewHolder chính nó, nhưng đã không thành công. Tôi đã cố điều chỉnh ngưỡng vuốt thành một giá trị đầy đủ, như 0f ot 1f trong phương thức SimpleCallback getSwipeThreshold(), nhưng cũng không thành công.Tắt tính năng vuốt cho vị trí trong RecyclerView sử dụng ItemTouchHelper.SimpleCallback

Một số đoạn mã của tôi để giúp bạn trợ giúp tôi.

Hoạt động của tôi:

@Override 
protected void onCreate(Bundle bundle) { 
    //... initialization 
    ItemTouchHelper.SimpleCallback simpleItemTouchCallback = new ItemTouchHelper.SimpleCallback(0, 
      ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT) { 

     @Override 
     public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, 
          RecyclerView.ViewHolder target) { 
      return false; 
     } 

     @Override 
     public float getSwipeThreshold(RecyclerView.ViewHolder viewHolder) { 
      if (viewHolder instanceof CartAdapter.MyViewHolder) return 1f; 
      return super.getSwipeThreshold(viewHolder); 
     } 

     @Override 
     public void onSwiped(RecyclerView.ViewHolder viewHolder, int swipeDir) { 

     } 
    }; 

    ItemTouchHelper itemTouchHelper = new ItemTouchHelper(simpleItemTouchCallback); 
    itemTouchHelper.attachToRecyclerView(recyclerView); 
} 

Và tôi có một bộ chuyển đổi chung với hai loại chế độ xem. Trong ViewHolder mà tôi muốn vô hiệu hóa swiping, tôi đã làm:

public static class MyViewHolder extends RecyclerView.ViewHolder { 
    public ViewGroup mContainer; 

    public MyViewHolder(View v) { 
     super(v); 
     v.setFocusable(false); 
     v.setEnabled(false); 
     mContainer = (ViewGroup) v.findViewById(R.id.container);  
    } 
} 

Trả lời

118

Sau khi chơi một chút, tôi quản lý mà SimpleCallback có một phương pháp gọi là getSwipeDirs(). Vì tôi có một ViewHolder cụ thể cho không thể hoán đổi vị trí, tôi có thể sử dụng instanceof để tránh thao tác vuốt. Nếu đó không phải là trường hợp của bạn, bạn có thể thực hiện điều khiển này bằng cách sử dụng vị trí của ViewHolder trong Bộ điều hợp.

@Override 
public int getSwipeDirs(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) { 
    if (viewHolder instanceof CartAdapter.MyViewHolder) return 0; 
    return super.getSwipeDirs(recyclerView, viewHolder); 
} 
+0

Chính xác những gì tôi đang tìm kiếm! Đặc biệt khi phương pháp này không xuất hiện trên [tài liệu chính thức] (http://developer.android.com/reference/android/support/v7/widget/helper/ItemTouchHelper.Callback.html) ... – ptitvinou

+1

@ptitvinou trên 'SimpleCallback' http://developer.android.com/intl/pt-br/reference/android/support/v7/widget/helper/ItemTouchHelper.SimpleCallback.html –

+1

Đáng nói đến: nếu bạn muốn chỉ cho phép một hướng trên một số mặt hàng nhất định, sau đó sử dụng 'vị trí trả về == 0? ItemTouchHelper.LEFT: super.getSwipeDirs (recyclerView, viewHolder); '- cái này tức là chỉ cho phép vuốt trái. –

45

Nếu ai đó đang sử dụng ItemTouchHelper.Callback. Sau đó, bạn có thể xóa bất kỳ cờ nào có liên quan trong các hàm getMovementFlags (..).

@Override 
public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) { 
    int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN; 
    int swipeFlags = ItemTouchHelper.START | ItemTouchHelper.END; 
    return makeMovementFlags(dragFlags, swipeFlags); 
} 

đây thay vì dragFlagsswipeFlags Bạn có thể vượt qua 0 để vô hiệu hóa tính năng tương ứng.

ItemTouchHelper.START có nghĩa là vuốt sang trái sang phải trong trường hợp từ trái sang phải (LTR application Support), nhưng ngược lại ở ngôn ngữ từ phải sang trái (Hỗ trợ ứng dụng RTL). ItemTouchHelper.END có nghĩa là vuốt theo hướng ngược lại của START.

để bạn có thể xóa bất kỳ cờ nào theo yêu cầu của mình.

+0

Cảm ơn !, Tôi sử dụng mã: @Override int công cộng getMovementFlags (RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) { int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN; // chuyển động kéo trả về makeFlag (ItemTouchHelper.ACTION_STATE_DRAG, dragFlags); // như tham số, kéo hành động và cờ kéo } –

+0

Đây là câu trả lời ưu tiên nếu (không giống như OP) bạn đang mở rộng 'ItemTouchHelper.Callback' trực tiếp. – tir38

4

Có một số cách để giải quyết vấn đề này, nhưng nếu bạn chỉ có một ViewHolder, nhưng nhiều hơn một bố cục bạn có thể thực hiện phương pháp này.

Ghi đè getItemViewType và cung cấp cho nó một số logic để xác định xem loại dựa trên vị trí hoặc loại dữ liệu trong đối tượng (Tôi có một chức năng getType trong đối tượng của tôi)

@Override 
public int getItemViewType(int position) { 
    return data.get(position).getType; 
} 

Return bố trí thích hợp trong onCreateView dựa trên ViewType (Hãy chắc chắn để vượt qua chế độ xem loại đến lớp ViewHolder.

@Override 
public AppListItemHolder onCreateViewHolder(ViewGroup parent, int viewType) { 
    mContext = parent.getContext(); 

    if (viewType == 0){ 
     return new AppListItemHolder(LayoutInflater.from(mContext).inflate(R.layout.layout, parent, false), viewType); 
    else 
     return new AppListItemHolder(LayoutInflater.from(mContext).inflate(R.layout.header, parent, false), viewType); 
    } 
} 

Lấy lần xem nội dung của các bố trí khác nhau dựa trên chế độ xem loại public static class AppListItemHolder kéo dài RecyclerView.ViewHolder {

public AppListItemHolder (View v, int viewType) { 
     super(v); 

     if (viewType == 0) 
      ... get your views contents 
     else 
      ... get other views contents 
     } 
    } 
} 

Và sau đó trong hành động thay đổi ItemTouchHelper của bạn dựa trên ViewType. Đối với tôi đây vô hiệu hóa swiping một tiêu đề phần RecyclerView

@Override 
public int getSwipeDirs(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) { 
    if (viewHolder.getItemViewType() == 1) return 0; 
     return super.getSwipeDirs(recyclerView, viewHolder); 
    } 
} 
+0

Ý tưởng hay nhưng getItemViewType là cuối cùng – tim

+0

Đó là những gì tôi muốn, cảm ơn bạn –

10

Đây là một cách đơn giản để làm điều này như vậy mà nó chỉ phụ thuộc vào vị trí của mặt hàng đó được swiped:

@Override 
public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder holder) { 
    int position = holder.getAdapterPosition(); 
    int dragFlags = 0; // whatever your dragFlags need to be 
    int swipeFlags = position == 0 ? 0 : ItemTouchHelper.START | ItemTouchHelper.END; 

    return makeMovementFlags(dragFlags, swipeFlags); 
} 

này cũng nên làm việc nếu bạn đang sử dụng SimpleCallback:

@Override 
public int getSwipeDirs(RecyclerView recyclerView, RecyclerView.ViewHolder holder) { 
    int position = holder.getAdapterPosition(); 
    return position == 0 ? 0 : super.getSwipeDirs(recyclerView, viewHolder); 
} 

Liệu điều này có tốt hơn các câu trả lời khác tùy thuộc vào nhu cầu của bạn hay không. Nếu bạn có loại chủ sở hữu cụ thể mà không cần phải vuốt, câu trả lời được chấp nhận sẽ hoạt động tốt. Nếu khả năng vuốt phụ thuộc vào dữ liệu của mục, thì bạn có thể sử dụng position để lấy dữ liệu từ bộ điều hợp cho mục đang được vuốt và tắt tương ứng. Và, cuối cùng, nếu bạn thực sự chỉ muốn vô hiệu hóa dựa trên vị trí, câu trả lời này sẽ hoạt động tốt.

0

đầu tiên trong recyclerView tại phương pháp onCreateViewHolder, đặt thẻ đối với từng loại viewHolder, như dưới đây mã:

@Override 
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) { 
    if(ITEM_TYPE_NORMAL == viewType) { 
     View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.deposite_card_view, viewGroup, false); 
     ItemViewHolder holder = new ItemViewHolder(context, v); 
     holder.itemView.setTag("normal"); 
     return holder; 
    } else { 
     View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.card_header, viewGroup, false); 
     HeaderViewHolder holder = new HeaderViewHolder(context, v); 
     holder.itemView.setTag("header"); 
     return holder; 
    } 
} 

sau đó trong việc thực hiện ItemTouchHelper.Callback, cập nhật getMovementFlags phương pháp, như dưới đây:

public class SwipeController extends ItemTouchHelper.Callback { 

@Override 
public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) { 
    if("normal".equalsIgnoreCase((String) viewHolder.itemView.getTag())) { 
     return makeMovementFlags(0, LEFT | RIGHT); 
    } else { 
     return 0; 
    } 
} 

ở cuối đính kèm với recyclerView:

final SwipeController swipeController = new SwipeController(); 

    ItemTouchHelper itemTouchHelper = new ItemTouchHelper(swipeController); 
    itemTouchHelper.attachToRecyclerView(recyclerView); 
Các vấn đề liên quan