IT박스

ItemTouchHelper.SimpleCallback을 사용하여 RecyclerView의 위치에 대해 스 와이프를 비활성화합니다.

itboxs 2020. 10. 11. 09:22
반응형

ItemTouchHelper.SimpleCallback을 사용하여 RecyclerView의 위치에 대해 스 와이프를 비활성화합니다.


recyclerview 22.2.0과 도우미 클래스 ItemTouchHelper.SimpleCallback을 사용 하여 내 목록에 대해 스 와이프 하여 닫기 옵션을 활성화 합니다. 그러나 헤더 유형이 있으므로 어댑터의 첫 번째 위치에 대해 스 와이프 동작을 비활성화해야합니다. 으로 RecyclerView.Adapter이 없는 의 IsEnabled () 메소드를 나는 방법을 통해 뷰의 상호 작용을하지 않도록 노력 의 IsEnabled ()isFocusable () ViewHolder 생성 자체, 그러나 성공이 없었다. SimpleCallback의 메서드 getSwipeThreshold () 에서 0f ot 1f 와 같이 스 와이프 임계 값을 전체 값으로 조정하려고 시도 했지만 성공하지 못했습니다.

당신이 나를 도울 수 있도록 내 코드의 일부.

내 활동 :

@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);
}

그리고 두 가지 보기 유형 이있는 공통 어댑터가 있습니다. 스 와이프를 비활성화하려는 ViewHolder 에서 다음을 수행 했습니다.

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);      
    }
}

비트를 연주 후, 나는 그 관리 SimpleCallback이 방법이라고이 getSwipeDirs을 () . 스 와이프 할 수 없는 위치에 대한 특정 ViewHolder가 있으므로 스 와이프 를 피하기 위해 instanceof사용할 수 있습니다 . 그렇지 않은 경우 어댑터의 ViewHolder 위치를 사용하여이 제어를 수행 할 수 있습니다.

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

누군가 ItemTouchHelper.Callback을 사용하는 경우 . 그런 다음 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);
}

여기에서 dragFlagsswipeFlags 대신 0을 전달하여 해당 기능을 비활성화 할 수 있습니다.

ItemTouchHelper.START 는 왼쪽에서 오른쪽 로케일 (LTR 애플리케이션 지원)의 경우 왼쪽에서 오른쪽으로 스 와이프하지만 오른쪽에서 왼쪽 로케일 (RTL 애플리케이션 지원)에서는 반대 방향으로 스 와이프하는 것을 의미합니다. ItemTouchHelper.END 는의 반대 방향으로 스 와이프하는 것을 의미 START합니다.

따라서 요구 사항에 따라 플래그를 제거 할 수 있습니다.


다음은 스 와이프되는 항목의 위치에만 의존하는 간단한 방법입니다.

@Override
public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder holder) {
    int position = holder.getAdapterPosition();
    int dragFlags = 0; // whatever your dragFlags need to be
    int swipeFlags = createSwipeFlags(position)

    return makeMovementFlags(dragFlags, swipeFlags);
}

private int createSwipeFlags(int position) {
  return position == 0 ? 0 : ItemTouchHelper.START | ItemTouchHelper.END;
}

다음을 사용하는 경우에도 작동합니다 SimpleCallback.

@Override
public int getSwipeDirs(RecyclerView recyclerView, RecyclerView.ViewHolder holder) {
    int position = holder.getAdapterPosition();
    return createSwipeFlags(position);
}

private int createSwipeFlags(int position) {
  return position == 0 ? 0 : super.getSwipeDirs(recyclerView, viewHolder);
}

항목의 데이터에 대한 조건부 스 와이프를 비활성화하려면 position값을 사용하여 스 와이프되는 항목에 대한 어댑터에서 데이터를 가져오고 그에 따라 비활성화합니다.

스 와이프하지 않아도되는 특정 보유자 유형이 이미있는 경우 수락 된 답변이 작동합니다. 그러나 위치에 대한 프록시로 홀더 유형을 생성하는 것은 번거롭기 때문에 피해야합니다.


이에 대해 몇 가지 방법이 있지만 ViewHolder가 하나만 있고 레이아웃이 둘 이상인 경우이 방법을 사용할 수 있습니다.

getItemViewType을 재정의하고 개체의 위치 또는 데이터 유형에 따라보기 유형을 결정하는 로직을 제공합니다 (객체에 getType 함수가 있습니다).

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

ViewType에 따라 onCreateView에서 적절한 레이아웃을 반환합니다 (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);
    }
}

보기 유형에 따라 다양한 레이아웃의 콘텐츠보기를 가져옵니다. public static class AppListItemHolder extends RecyclerView.ViewHolder {

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

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

그런 다음 ItemTouchHelper에서 ViewType에 따라 작업을 변경합니다. 나를 위해 이것은 RecyclerView 섹션 헤더의 스 와이프를 비활성화합니다.

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

First in recyclerView at onCreateViewHolder method, set tag for each viewHolder type, like below code:

@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;
    }
} 

then in ItemTouchHelper.Callback implementation, update getMovementFlags method, like below:

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;
    }
}

at end attach to recyclerView:

final SwipeController swipeController = new SwipeController();

    ItemTouchHelper itemTouchHelper = new ItemTouchHelper(swipeController);
    itemTouchHelper.attachToRecyclerView(recyclerView);

In addition to the @Rafael Toledo answer, If you want to remove the specific swipe gesture like LEFT swipe or RIGHT swipe based on position or type of data in object in Adapter, then you can do like this.

@Override
  public int getSwipeDirs(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder)
       {
          int position = viewHolder.getAdapterPosition();
          ConversationDataModel conversationModel = null;
          conversationModel = mHomeAdapter.getItems().get(position);
          boolean activeChat = true;
          if(conversationModel!=null && !conversationModel.isActive())
           {
             activeChat = false;
           }
  return activeChat ? super.getSwipeDirs(recyclerView, viewHolder): ItemTouchHelper.RIGHT;
        }

Here in my case, In my Recyclerview I am loading the chat conversations and it have RIGHT (for ARCHIVE) & LEFT ( for EXIT) swipe gestures on each item. But in case if the conversation is not active, then I need to disable the RIGHT swipe for the specific item in the Recycler view.

So I am checking for the activeChat and accordingly and disabled the RIGHT swipe.

참고URL : https://stackoverflow.com/questions/30713121/disable-swipe-for-position-in-recyclerview-using-itemtouchhelper-simplecallback

반응형