10

समस्यालेने वाली स्पर्श इवेंट

से RecyclerView रोकथाम मैं Google Play आवेदन की सही व्यवहार अनुकरण करने का प्रयास कर रहा हूँ।

वर्तमान में जब आप 'टॉप गेम्स' जैसी श्रेणी के माध्यम से स्क्रॉल कर रहे हैं और आप सूची को स्पर्श करते हैं, तो सेल के साथ-साथ RecyclerView स्पर्श ईवेंट को संभालता है, आप बता सकते हैं कि वे दोनों तरंगों के कारण इसे संभालने के कारण हैंडलिंग करते हैं आप अपनी उंगली के साथ-साथ स्क्रॉलिंग को स्टॉप पर आते हैं। या यदि आप सेल पर क्लिक करते हैं, तो सूची अभी भी चल रही है कि सामग्री तुरंत खोली गई है।

डिफ़ॉल्ट व्यवहार स्क्रॉलिंग के लिए तत्काल रुकने के लिए है यदि आप अपनी उंगली को आगे बढ़ते समय नीचे रखते हैं, और उसके लिए उस स्पर्श घटना का उपभोग करने के लिए, जिसका मतलब है कि सेल को उस स्पर्श के बारे में कभी नहीं बताया जाता है। यह आपके अविश्वसनीय रूप से परेशान है जब आपके अनुप्रयोग मुख्य सामग्री RecyclerView में होती है और यदि उपयोगकर्ता निरंतर स्क्रॉल कर रहा है तो सेल पर क्लिक करके, उसे दो बार क्लिक करने की आवश्यकता होती है, क्योंकि स्क्रॉल को रोककर पहले क्लिक का उपभोग किया जाता है, भले ही सूची थी मुश्किल से चल रहा है।

क्या मैं तो कोशिश की है सुदूर

पहले तो मैंने सोचा था कि वहाँ RecyclerView अंदर झंडा किसी तरह का है जो यह बताता है कि स्पर्श घटना का उपभोग नहीं होना चाहिए। मैंने एंड्रॉइड सोर्स कोड को देखा है और एंड्रॉइड प्रलेखन के माध्यम से कोई फायदा नहीं हुआ है।

फिर मैंने onInterceptTouchEvent के साथ स्पर्श ईवेंट को कैप्चर करने का प्रयास किया और मैन्युअल रूप से मेरे विचार को बताया कि इसे छुआ जा रहा है;

@Override 
public boolean onInterceptTouchEvent(MotionEvent event) { 
    View myCell = recyclerView.findChildViewUnder(event.getX(), event.getY()); 
    myCell.dispatchTouchEvent(event); 
    return super.onInterceptTouchEvent(event); 
} 

यहाँ, dispatchTouchEvent कुछ भी भले ही दृश्य मैं हो रही थी इसी टैग जो मैं अनुकूलक में सेट किया था ऐसा करने के लिए नहीं मालूम था।

मैंने इस समस्या को सभी कोणों पर अपनी कोड मशीन बंदूक के साथ शूट करने का प्रयास किया है; requestDisallowInterceptTouchEvent के साथ खेलकर, मैन्युअल रूप से onTouch पर कॉल करके RecyclerView और उसके बाद के सभी श्रोताओं को ओवरराइड करना।

कुछ भी काम नहीं कर रहा है। मुझे यकीन है कि इसके लिए एक शानदार समाधान होना चाहिए और मैंने पागलपन के रास्ते के साथ कहीं भी एक महत्वपूर्ण विवरण पर स्किम किया है? विशेष रूप से क्योंकि Google के अपने ऐप्स इस तरीके से व्यवहार करते हैं।

कृपया मदद करें! :) धन्यवाद।

समाधान

Jagoan नियॉन के लिए धन्यवाद एक समाधान पाया गया है। मैंने आसानी से उपयोग के लिए कस्टम RecyclerView के अंदर अपना जवाब लपेट लिया।

public class MultiClickRecyclerView extends RecyclerView { 
    public MultiClickRecyclerView(Context context) { 
     super(context); 
    } 

    public MultiClickRecyclerView(Context context, AttributeSet attrs) { 
     super(context, attrs); 
    } 

    public MultiClickRecyclerView(Context context, AttributeSet attrs, int defStyle) { 
     super(context, attrs, defStyle); 
    } 

    @Override 
    public boolean onInterceptTouchEvent(MotionEvent event) { 
     if (event.getAction() == MotionEvent.ACTION_DOWN && this.getScrollState() == RecyclerView.SCROLL_STATE_SETTLING) { 
      this.stopScroll(); 
     } 
     return super.onInterceptTouchEvent(event); 
    } 
} 

उत्तर

9

सबसे पहले आप शायद इस तरह एक वैश्विक चर के रूप में, एक OnItemTouchListener परिभाषित करना चाहिए:

RecyclerView.OnItemTouchListener mOnItemTouchListener = new RecyclerView.OnItemTouchListener() { 
    @Override 
    public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) { 
     if (e.getAction() == MotionEvent.ACTION_DOWN && rv.getScrollState() == RecyclerView.SCROLL_STATE_SETTLING) { 
      Log.d(TAG, "onInterceptTouchEvent: click performed"); 
      rv.findChildViewUnder(e.getX(), e.getY()).performClick(); 
      return true; 
     } 
     return false; 
    } 

    @Override 
    public void onTouchEvent(RecyclerView rv, MotionEvent e) {} 

    @Override 
    public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {} 
}; 

क्यों ACTION_DOWN और SCROLL_STATE_SETTLING?

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

और सही वापस लौटना याद रखें ताकि आप अपने रीसाइक्लर व्यू को बता रहे हों कि आपने मोशनवेन्ट का उपभोग किया है। अन्यथा आपका प्रदर्शन क्लिक करें() को एक से अधिक बार बुलाया जा सकता है।

onResume पर अपने RecyclerView में जोड़कर onPause पर इसे हटाने, और तो आप तैयार हैं;) जब आप findChildViewUnder कर रहे हैं

अद्यतन

एक अशक्त चेकर जोड़ें - यह शून्य देता है जब आप एक विशिष्ट सेल को छू नहीं रहा।

View childView = rv.findChildViewUnder(e.getX(), e.getY()); 
if (childView != null) childView.performClick(); 

अद्यतन 2

बाहर कर देता है, जो स्क्रॉल से RecyclerView रोक पर्याप्त होगा। इसके बजाय इसे करें:

@Override 
    public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) { 
     if (e.getAction() == MotionEvent.ACTION_DOWN && rv.getScrollState() == RecyclerView.SCROLL_STATE_SETTLING) 
      rv.stopScroll(); 
     return false; 
    } 
+0

मैंने आज सुबह आपका उत्तर लागू किया और हम लगभग वहां हैं! यह बहुत अजीब है; यह समाधान उस समय के लगभग 30% काम करता प्रतीत होता है, इस पर निर्भर करता है कि मैं पहले से कितनी धीमी गति से खींच रहा हूं। मैं गति घटना लॉग आउट कर रहा हूं और राज्य को स्क्रॉल कर रहा हूं और ऐसा लगता है कि यह कब काम करता है और जब ऐसा नहीं होता है। यदि मैं सूची को तेज़ी से स्क्रॉल करता हूं और फिर मेरी अंगुली को टैप करके रखता हूं तो यह लगभग कभी भी संपर्क को पंजीकृत नहीं करता है और लहर को दिखाता है (जैसे Google Play ऐप करता है)। क्या यह लगातार आपके लिए काम कर रहा है? मैं एक 2 अवधि गिनती ग्रिड लेआउट का उपयोग कर रहा हूं, हालांकि मुझे कल्पना नहीं होगी कि इससे कोई फर्क पड़ता है। – vguzzi

+0

क्या आपने अपना दूसरा संपादन देखा है? –

+0

हाँ, मैं वर्तमान में स्टॉप स्क्रॉल व्यू कार्यान्वयन पर हूं। मैंने पिछले सुझावों की भी कोशिश की। – vguzzi

संबंधित मुद्दे