ItemTouchHelper.SimpleCallback का उपयोग करके RecyclerView में स्थिति के लिए स्वाइप अक्षम करें


93

मैं अपनी सूची में स्वाइप-टू-खारिज विकल्प को सक्षम करने के लिए 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);      
    }
}

जवाबों:


204

थोड़ा खेलने के बाद, मैंने प्रबंधित किया कि SimpleCallback में getSwipeDirs () नामक एक विधि है । चूंकि मेरे पास स्वाइप करने योग्य स्थिति के लिए एक विशिष्ट व्यूहॉल्डर नहीं है , इसलिए मैं स्वाइप से बचने के लिए इंस्टाफॉ का उपयोग कर सकता हूं । यदि यह आपका मामला नहीं है, तो आप एडेप्टर में ViewHolder की स्थिति का उपयोग करके इस नियंत्रण को निष्पादित कर सकते हैं।

जावा

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

Kotlin

override fun getSwipeDirs (recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder): Int {
    if (viewHolder is CartAdapter.MyViewHolder) return 0
    return super.getSwipeDirs(recyclerView, viewHolder)
}

1
ठीक वही जो मेरे द्वारा खोजा जा रहा था! खासकर जब यह विधि आधिकारिक दस्तावेज पर नहीं दिखाई देती है ...
ptitvinou

1
@ptitvinou यह SimpleCallback डेवलपर.
राफेल टोलेडो

2
उल्लेख करने योग्य: यदि आप कुछ वस्तुओं पर केवल एक दिशा के लिए अनुमति देना चाहते हैं, तो उपयोग करें return position == 0 ? ItemTouchHelper.LEFT : super.getSwipeDirs(recyclerView, viewHolder);- यह एक अर्थात केवल बाएं स्वाइप के लिए अनुमति दें।
जीन डी'रामे

उत्तम। एक आकर्षण की तरह काम करना
जनता का राजा

यह कैसे काम करता है? यदि मैं उदाहरण के लिए स्वाइपिंग राइट को अक्षम करना चाहता हूं तो मैं क्या करूं?
अली बदीर

66

यदि कोई व्यक्ति 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);
}

यहां DragFlags और SwipeFlags के बजाय आप संबंधित सुविधा को अक्षम करने के लिए 0 पास कर सकते हैं।

ItemTouchHelper.START का अर्थ है बाएं से दाएं लोकेल (LTR एप्लिकेशन सपोर्ट) के मामले में बाएं से दाएं स्वाइप करना, लेकिन राइट टू लेफ्ट लोकेल (RTL एप्लिकेशन सपोर्ट) के आसपास। ItemTouchHelper.END का अर्थ है विपरीत दिशा में स्वाइप करना START

इसलिए आप अपनी आवश्यकताओं के अनुसार किसी भी ध्वज को हटा सकते हैं।


धन्यवाद।, मैं कोड का उपयोग करता हूं: @Override public int getMovementFlags (RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN; // मूवमेंट ड्रैग रिटर्न मेकफ्लैग (ItemTouchHelper.ACTION_STATE_DRAG, dragFlags); // पैरामीटर के रूप में, एक्शन ड्रैग एंड फ्लैग्स ड्रैग}
क्या Xuan Nguyen

यह पसंदीदा उत्तर है यदि (ओपी के विपरीत) आप ItemTouchHelper.Callbackसीधे विस्तार कर रहे हैं।
tir38

24

ऐसा करने का एक सरल तरीका यहां दिया गया है जो केवल आइटम की स्थिति पर निर्भर करता है:

@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तो आइटम को स्वाइप किए जाने के लिए एडेप्टर से डेटा प्राप्त करने के लिए मूल्य का उपयोग करें और तदनुसार अक्षम करें।

यदि आपके पास पहले से ही विशिष्ट धारक प्रकार हैं जिन्हें स्वाइप नहीं करने की आवश्यकता है, तो स्वीकृत उत्तर काम करेगा। हालांकि, स्थिति के लिए एक प्रॉक्सी के रूप में धारक प्रकार बनाना एक कीचड़ है और इससे बचा जाना चाहिए।


6

इसके बारे में जाने के कुछ तरीके हैं, लेकिन यदि आपके पास केवल एक ViewHolder है, लेकिन एक से अधिक लेआउट आप इस दृष्टिकोण को ले सकते हैं।

GetItemViewType को ओवरराइड करें और ऑब्जेक्ट में स्थिति या डेटा के प्रकार के आधार पर दृश्य प्रकार निर्धारित करने के लिए इसे कुछ तर्क दें (मेरे पास मेरी ऑब्जेक्ट में गेट टाइप फ़ंक्शन है)

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

दृश्य प्रकार के आधार पर विभिन्न लेआउट के सामग्री दृश्य प्राप्त करें सार्वजनिक स्थैतिक वर्ग AppListItemHolder RecyclerView.Viewolder {

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

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

और फिर ViewType के आधार पर अपने ItemTouchHelper कार्यों को बदलें। मेरे लिए यह एक RecyclerView अनुभाग हेडर के स्वाइप को अक्षम करता है

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

अच्छा विचार है, लेकिन getItemViewType अंतिम है
टिम

3

OnCreateViewHolder पद्धति पर recyclerView में पहले, प्रत्येक दृश्य के लिए टैग सेट करें, नीचे दिए गए कोड की तरह:

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

उसके बाद ItemTouchHelper.allback कार्यान्वयन में, अपडेट पाएं।

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

अंत में recyclerView को संलग्न करें:

final SwipeController swipeController = new SwipeController();

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

2

@ राफेल टोलेडो जवाब के अलावा, यदि आप एडेप्टर में ऑब्जेक्ट में स्थिति या प्रकार के डेटा के आधार पर LEFT स्वाइप या राइट स्वाइप जैसे विशिष्ट स्वाइप जेस्चर को हटाना चाहते हैं, तो आप ऐसा कर सकते हैं।

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

यहाँ मेरे मामले में, मेरे पुनर्नवीनीकरण में मैं चैट वार्तालाप लोड कर रहा हूं और इसमें प्रत्येक आइटम पर राइट (ARCHIVE) और LEFT (EXIT के लिए) स्वाइप जेस्चर हैं। लेकिन अगर बातचीत सक्रिय नहीं है, तो मुझे रिसाइकलर दृश्य में विशिष्ट आइटम के लिए राइट स्वाइप को अक्षम करना होगा।

इसलिए मैं इसके activeChatअनुसार जाँच कर रहा हूँ और राइट स्वाइप को अक्षम कर दिया है।


2

इसका उपयोग करके निष्क्रिय किया जा सकता है ItemTouchHelper.ACTION_STATE_IDLE

ItemTouchHelper.SimpleCallback(
    ItemTouchHelper.UP or ItemTouchHelper.DOWN, //drag directions
    ItemTouchHelper.ACTION_STATE_IDLE //swipe directions
)
val touchHelperCallback = object : ItemTouchHelper.SimpleCallback(ItemTouchHelper.UP or ItemTouchHelper.DOWN, ItemTouchHelper.ACTION_STATE_IDLE) {
    override fun onMove(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder, target: RecyclerView.ViewHolder): Boolean {
        (recyclerView.adapter as MyAdapter).onItemMove(viewHolder.adapterPosition, target.adapterPosition)
        return true
    }

    override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {
        return
    }

}
val touchHelper = ItemTouchHelper(touchHelperCallback)
touchHelper.attachToRecyclerView(recyclerViewX)
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.