2015-07-14 22 views
15

Tôi đã xóa hình nền, vẽ nền (giống như ứng dụng Inbox), được thực hiện bởi ItemTouchHelper - bằng cách ghi đè phương thức onChilDraw và vẽ hình chữ nhật trên canvas được cung cấp:RecyclerView ItemTouchHelper swipe xóa hoạt ảnh

ItemTouchHelper mIth = new ItemTouchHelper(
     new ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.RIGHT) { 

      public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) { 
       remove(viewHolder.getAdapterPosition()); 
      } 

      public boolean onMove(RecyclerView recyclerview, RecyclerView.ViewHolder v, RecyclerView.ViewHolder target) { 
       return false; 
      } 

      @Override 
      public void onChildDraw(Canvas c, RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive) { 

       View itemView = viewHolder.itemView; 

       Drawable d = ContextCompat.getDrawable(context, R.drawable.bg_swipe_item_right); 
       d.setBounds(itemView.getLeft(), itemView.getTop(), (int) dX, itemView.getBottom()); 
       d.draw(c); 

       super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive); 
      } 
     }); 

phương thức remove gọi trên là trong Adaptor:

public void remove(int position) { 
     items.remove(position); 
     notifyItemRemoved(position); 
    } 

nền rút ra độc đáo, nhưng khi notifyItemRemoved được gọi là (theo ông Debugger), các RecyclerView đầu tiên xóa nền màu xanh lá cây khá của tôi, và sau đó đẩy hai các mục với nhau.

enter image description hereenter image description here

Tôi muốn thắng để giữ nền có khi nó làm điều đó (giống như các ứng dụng Inbox). Có cách nào để làm điều đó?

Trả lời

2

Tôi đã gặp vấn đề tương tự và tôi không muốn giới thiệu một lib mới chỉ để sửa lỗi đó. RecyclerView không xóa nền màu xanh lục đẹp của bạn, nó chỉ vẽ lại chính nó và ItemTouchHelper của bạn không được vẽ nữa. Trên thực tế nó vẽ nhưng dX là 0 và đang vẽ từ itemView.getLeft() (0) đến dX (là 0) để bạn không thấy gì cả. Và nó vẽ quá nhiều, nhưng tôi sẽ quay lại sau.

Dù sao quay lại nền trong khi các hàng có hiệu ứng động: Tôi không thể thực hiện trong phạm vi ItemTouchHelperonChildDraw. Cuối cùng tôi phải thêm một trang trí khác để làm điều đó.Nó đi dọc theo các dòng sau:

public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) { 
    if (parent.getItemAnimator().isRunning()) { 
     // find first child with translationY > 0 
     // draw from it's top to translationY whatever you want 

     int top = 0; 
     int bottom = 0; 

     int childCount = parent.getLayoutManager().getChildCount(); 
     for (int i = 0; i < childCount; i++) { 
      View child = parent.getLayoutManager().getChildAt(i); 
      if (child.getTranslationY() != 0) { 
       top = child.getTop(); 
       bottom = top + (int) child.getTranslationY();      
       break; 
      } 
     } 

     // draw whatever you want 

     super.onDraw(c, parent, state); 
    } 
} 

Mã này chỉ tính đến các hàng hoạt ảnh, nhưng bạn cũng nên xem xét các hàng sắp xuất hiện. Điều đó xảy ra nếu bạn vuốt xóa hàng cuối cùng, các hàng ở trên sẽ tạo hiệu ứng động cho không gian đó.

Khi tôi nói ItemTouchHelper của bạn vẽ quá nhiều ý tôi là: Có vẻ như ItemTouchHelper giữ ViewHolder s các hàng bị xóa trong trường hợp chúng cần được khôi phục. Nó cũng kêu gọi onChildDraw cho những VH ngoài việc VH bị quét. Không chắc chắn về tác động quản lý bộ nhớ của hành vi này nhưng tôi cần một kiểm tra bổ sung vào đầu của onChildDraw để tránh vẽ cho các hàng "fantom".

if (viewHolder.getAdapterPosition() == -1) { 
    return; 
} 

Trong trường hợp của bạn, nó vẽ từ trái = 0 sang phải = 0 để bạn không thấy gì ngoài phí ở đó. Nếu bạn bắt đầu nhìn thấy trước đó swiped hàng vẽ nền của họ đó là lý do.

CHỈNH SỬA: Tôi đã thực hiện việc này, xem blog post và điều này github repo.

1

Tôi đã cố gắng làm cho thiết bị hoạt động bằng cách sử dụng thư viện Wasabeefs's recyclerview-animators.

My ViewHolder tại kéo dài AnimateViewHolder quy của thư viện:

class MyViewHolder extends AnimateViewHolder { 

    TextView textView; 

    public MyViewHolder(View itemView) { 
     super(itemView); 
     this.textView = (TextView) itemView.findViewById(R.id.item_name); 
    } 

    @Override 
    public void animateAddImpl(ViewPropertyAnimatorListener listener) { 
     ViewCompat.animate(itemView) 
       .translationY(0) 
       .alpha(1) 
       .setDuration(300) 
       .setListener(listener) 
       .start(); 
    } 

    @Override 
    public void preAnimateAddImpl() { 
     ViewCompat.setTranslationY(itemView, -itemView.getHeight() * 0.3f); 
     ViewCompat.setAlpha(itemView, 0); 
    } 

    @Override 
    public void animateRemoveImpl(ViewPropertyAnimatorListener listener) { 
     ViewCompat.animate(itemView) 
       .translationY(0) 
       .alpha(1) 
       .setDuration(300) 
       .setListener(listener) 
       .start(); 
    } 

} 

Việc triển khai chức năng overrided là giống hệt với những gì là trong readme recyclerview-họa sĩ trên github.

Nó cũng có vẻ cần thiết để thay đổi ItemAnimator đến một tùy chỉnh một và thiết lập các removeDuration 0 (hoặc một giá trị thấp - điều này là để ngăn chặn một số nhấp nháy):

recyclerView.setItemAnimator(new SlideInLeftAnimator()); 
    recyclerView.getItemAnimator().setRemoveDuration(0); 

này không gây ra bất kỳ vấn đề như hoạt ảnh xóa bình thường (không vuốt) được sử dụng là ảnh động trong AnimateViewHolder.

Tất cả các mã khác được giữ nguyên như trong câu hỏi. Tôi đã không có thời gian để tìm ra các hoạt động bên trong của điều này được nêu ra, nhưng nếu có ai cảm thấy như làm nó cảm thấy tự do để cập nhật câu trả lời này.

Cập nhật: Đặt recyclerView.getItemAnimator().setRemoveDuration(0); thực sự phá vỡ hoạt ảnh "khôi phục" của thao tác vuốt. May mắn thay, loại bỏ dòng đó và thiết lập một thời gian dài hơn trong animateRemoveImpl (500 công trình cho tôi) cũng giải quyết được vấn đề nhấp nháy.

Cập nhật 2: Chỉ ra rằng ItemTouchHelper.SimpleCallback sử dụng thời lượng hoạt ảnh của ItemAnimator, đó là lý do tại sao setRemoveDuration trên (0) phá vỡ hoạt ảnh vuốt. Chỉ cần ghi đè phương thức getAnimationDuration của nó là:

@Override 
public long getAnimationDuration(RecyclerView recyclerView, int animationType, float animateDx, float animateDy) { 
    return animationType == ItemTouchHelper.ANIMATION_TYPE_DRAG ? DEFAULT_DRAG_ANIMATION_DURATION 
      : DEFAULT_SWIPE_ANIMATION_DURATION; 
} 

giải quyết vấn đề đó.

Các vấn đề liên quan