java एंड्रॉइड: इंटरसेप्ट टचवेन्ट और प्रेषण टचवेन्ट के बीच अंतर?




android event-handling (12)

क्योंकि यह Google पर पहला परिणाम है। मैं यूट्यूब पर डेव स्मिथ द्वारा एक महान टॉक साझा करना चाहता हूं : एंड्रॉइड टच सिस्टम का मास्टरिंग और स्लाइड यहां उपलब्ध here । इसने मुझे एंड्रॉइड टच सिस्टम के बारे में अच्छी गहरी समझ दी:

गतिविधि कैसे स्पर्श करती है:

  • Activity.dispatchTouchEvent()
    • हमेशा पहले बुलाया जाना है
    • विंडो से जुड़े रूट व्यू में ईवेंट भेजता है
    • onTouchEvent()
      • अगर कोई विचार घटना का उपभोग नहीं करता है तो बुलाया जाता है
      • हमेशा बुलाया जाना है

दृश्य कैसे स्पर्श करता है:

  • View.dispatchTouchEvent()
    • यदि मौजूद है, तो पहले श्रोता को ईवेंट भेजता है
      • View.OnTouchListener.onTouch()
    • यदि उपभोग नहीं किया जाता है, तो स्पर्श को स्वयं संसाधित करता है
      • View.onTouchEvent()

एक व्यू ग्रुप कैसे स्पर्श करता है:

  • ViewGroup.dispatchTouchEvent()
    • onInterceptTouchEvent()
      • जांचें कि क्या बच्चों को पीछे छोड़ देना चाहिए
      • सक्रिय बच्चे को ACTION_CANCEL पास ACTION_CANCEL है
      • एक बार सच हो जाओ, सभी आगामी घटनाओं का उपभोग करता है
    • प्रत्येक बच्चे के दृश्य के लिए, विपरीत क्रम में वे जोड़े गए थे
      • यदि स्पर्श प्रासंगिक है (अंदर देखें), child.dispatchTouchEvent()
      • यदि पिछले द्वारा संभाला नहीं जाता है, तो अगले दृश्य पर प्रेषित करें
    • अगर कोई बच्चा घटना संभाल नहीं लेता है, श्रोता को मौका मिलता है
      • OnTouchListener.onTouch()
    • यदि कोई श्रोता नहीं है, या संभाला नहीं है
      • onTouchEvent()
  • अवरुद्ध घटनाएं बच्चे के कदम पर कूदती हैं

वह github.com/devunwired/ पर कस्टम टच का उदाहरण कोड भी प्रदान करता है।

उत्तर: मूल रूप से dispatchTouchEvent() को प्रत्येक View परत पर यह निर्धारित करने के लिए कहा जाता है कि कोई View चल रहे इशारे में रुचि रखता है या नहीं। व्यू ग्रुप में व्यू ग्रुप में उनके dispatchTouchEvent() टचवेन्ट dispatchTouchEvent() -method में स्पर्श ईवेंट चुरा लेने की क्षमता है, इससे पहले कि यह बच्चों पर dispatchTouchEvent() टचवेन्ट dispatchTouchEvent() को कॉल करे। ViewGroup केवल प्रेषण को रोक देगा यदि ViewGroup onInterceptTouchEvent() -method सत्य देता है। अंतर यह है कि dispatchTouchEvent() onInterceptTouchEvent dispatchTouchEvent() onInterceptTouchEvent को प्रेषित कर रहा है और onInterceptTouchEvent बताता है कि क्या इसे रोकना चाहिए (बच्चों को onInterceptTouchEvent प्रेषित नहीं करना चाहिए ) या नहीं (बच्चों को प्रेषण)

आप कल्पना कर सकते हैं कि व्यू ग्रुप का कोड कम या कम कर रहा है (बहुत सरल):

public boolean dispatchTouchEvent(MotionEvent ev) {
    if(!onInterceptTouchEvent()){
        for(View child : children){
            if(child.dispatchTouchEvent(ev))
                return true;
        }
    }
    return super.dispatchTouchEvent(ev);
}

Android में onInterceptTouchEvent और dispatchTouchEvent onInterceptTouchEvent बीच क्या अंतर है?

एंड्रॉइड डेवलपर गाइड के मुताबिक, दोनों तरीकों का उपयोग टच इवेंट ( MotionEvent ) को रोकने के लिए किया जा सकता है, लेकिन क्या अंतर है?

onInterceptTouchEvent , dispatchTouchEvent और onTouchEvent कैसे दृश्य (दृश्य समूह) के पदानुक्रम के भीतर एक साथ बातचीत करते हैं?


public boolean dispatchTouchEvent(MotionEvent ev){
    boolean consume =false;
    if(onInterceptTouchEvent(ev){
        consume = onTouchEvent(ev);
    }else{
        consume = child.dispatchTouchEvent(ev);
    }
}

इसे नष्ट करने के लिए सबसे अच्छी जगह स्रोत कोड है। दस्तावेजों को समझाने के बारे में अपर्याप्त हैं।

प्रेषण टचएवेंट वास्तव में गतिविधि, दृश्य और दृश्य समूह पर परिभाषित किया गया है। इसे एक नियंत्रक के रूप में सोचें जो तय करता है कि टच इवेंट्स को कैसे रूट किया जाए।

उदाहरण के लिए, सबसे सरल मामला View.dispatchTouchEvent का है जो टच इवेंट को या तो ऑन टच लिस्टनर.ऑन टच पर रूट करेगा यदि यह परिभाषित किया गया है या टचएवेंट पर एक्सटेंशन विधि के लिए।

ViewGroup.dispatchTouchEvent चीजों के लिए रास्ता अधिक जटिल हैं। इसे पता लगाने की जरूरत है कि उसके बच्चे के विचारों में से कौन सा ईवेंट ईवेंट प्राप्त करना चाहिए (child.dispatchTouchEvent को कॉल करके)। यह मूल रूप से एक हिट परीक्षण एल्गोरिदम है जहां आप पता लगाते हैं कि कौन से बच्चे के दृश्य के बाध्य आयत में टच पॉइंट निर्देशांक होते हैं।

लेकिन इससे पहले कि यह उचित बच्चे के दृश्य में घटना को प्रेषित कर सके, माता-पिता सभी को एक साथ जासूसी कर सकते हैं और / या रोक सकते हैं। इन्टरसेप्ट टचवेन्ट पर यही है। तो यह हिट परीक्षण करने से पहले इस विधि को पहले कॉल करता है और यदि ईवेंट को अपहरण कर लिया गया था (इंटरसेप्ट टचवेन्ट से सच लौटकर) यह बच्चे के विचारों में ACTION_CANCEL भेजता है ताकि वे अपने स्पर्श ईवेंट प्रसंस्करण (पिछले स्पर्श ईवेंट से) और उसके बाद से अभिभावक स्तर पर सभी स्पर्श घटनाओं को टच लिस्टनर.ऑन टच (यदि परिभाषित किया गया है) या टचएवेंट () पर भेजा जाता है। इसके अलावा, उस मामले में, इंटरसेप्ट टचवेन्ट को फिर कभी नहीं कहा जाता है।

क्या आप [गतिविधि | व्यू ग्रुप | व्यू] .dispatchTouchEvent को ओवरराइड करना चाहते हैं? जब तक आप कुछ कस्टम रूटिंग नहीं कर रहे हैं तो आपको शायद नहीं करना चाहिए।

मुख्य एक्सटेंशन विधियां ViewGroup.onInterceptTouchEvent हैं यदि आप मूल ईवेंट हैंडलिंग के लिए अभिभावक स्तर और View.onTouchListener / View.onTouchEvent पर टच ईवेंट को जासूसी और / या अवरुद्ध करना चाहते हैं।

सब कुछ अपने अत्यधिक जटिल डिजाइन इमो में लेकिन एंड्रॉइड एपिस सादगी की तुलना में लचीलापन की ओर अधिक दुबला है।


मैं इस वेबपृष्ठ http://doandroids.com/blogs/tag/codeexample/ पर बहुत सहज ज्ञान युक्त स्पष्टीकरण में आया था। वहां से लिया गया:

  • बूलियन ऑन टचवेन्ट (मोशनवेन्ट ईवी) - जब भी इस दृश्य के साथ एक स्पर्श घटना लक्ष्य के रूप में पहचाना जाता है
  • बूलियन ऑनइंटरसेप्ट टचवेन्ट (मोशनवेन्ट ईवी) - जब भी इस व्यू ग्रुप या उसके बच्चे के साथ लक्ष्य के रूप में एक स्पर्श घटना का पता लगाया जाता है। यदि यह फ़ंक्शन सत्य लौटाता है, तो मोशनवेन्ट को अवरुद्ध कर दिया जाएगा, जिसका अर्थ है कि यह बच्चे को नहीं भेजा जाएगा, बल्कि इस दृश्य के टचवेन्ट के लिए।

ViewGroup'sInterceptTouchEvent onInterceptTouchEvent() हमेशा ACTION_DOWN ईवेंट के लिए प्रविष्टि बिंदु होता है जो पहली घटना होती है।

यदि आप इस इशारा को संसाधित करने के लिए onInterceptTouchEvent() चाहते हैं, तो onInterceptTouchEvent() से सत्य लौटें। सत्य लौटने पर, ViewGroup के onTouchEvent() को अगले ACTION_UP या ACTION_CANCEL तक आने वाली सभी घटनाएं प्राप्त ACTION_CANCEL , और ज्यादातर मामलों में, ACTION_DOWN और ACTION_UP या ACTION_CANCEL बीच स्पर्श ईवेंट ACTION_CANCEL हैं, जिन्हें आमतौर पर स्क्रॉलिंग / ACTION_MOVE जेस्चर के रूप में पहचाना जाएगा।

अगर आप onInterceptTouchEvent() से झूठी वापसी करते हैं, तो लक्ष्य दृश्य पर onInterceptTouchEvent() onTouchEvent() को कॉल किया जाएगा। इसे बाद के संदेशों के लिए दोहराया जाएगा जब तक कि आप onInterceptTouchEvent() से सच नहीं onInterceptTouchEvent()

स्रोत: http://neevek.net/posts/2013/10/13/implementing-onInterceptTouchEvent-and-onTouchEvent-for-ViewGroup.html


आप इस वीडियो में उत्तर https://www.youtube.com/watch?v=SYoN-OvdZ3M&list=PLonJJ3BVjZW6CtAMbJz1XD8ELUs1KXaTD&index=19 और अगले 3 वीडियो में जवाब पा सकते हैं। सभी स्पर्श घटनाओं को बहुत अच्छी तरह समझाया गया है, यह बहुत स्पष्ट और उदाहरणों से भरा है।


इन तरीकों के बारे में बहुत भ्रम है, लेकिन वास्तव में यह जटिल नहीं है। अधिकांश भ्रम है क्योंकि:

  1. यदि आपका View/ViewGroup या उसके कोई भी बच्चे onInterceptTouchEvent में सत्य नहीं लौटाता है, तो dispatchTouchEvent onInterceptTouchEvent और onInterceptTouchEvent को केवल onInterceptTouchEvent लिए बुलाया जाएगा। onTouchEvent से सच्चाई के बिना, मूल दृश्य आपके विचार को मोशनवेन्ट्स की आवश्यकता नहीं मानता है।
  2. जब टचवेन्ट पर व्यू ग्रुप के कोई भी बच्चे सही नहीं होते हैं, तो इंटरसेप्ट टचएवेंट को केवल मोशनइवेंट.एक्शन_DOWN के लिए बुलाया जाएगा, भले ही आपका व्यू ग्रुप ऑन टचएवेंट में सत्य हो।

प्रसंस्करण आदेश इस तरह है:

  1. dispatchTouchEvent कहा जाता है।
  2. onInterceptTouchEvent को MotionEvent.ACTION_DOWN लिए बुलाया जाता है या जब ViewGroup के किसी भी बच्चे onTouchEvent में सत्य onTouchEvent
  3. ऑन onTouchEvent को पहली बार View/ViewGroup के बच्चों पर बुलाया जाता है और जब कोई भी बच्चा सच नहीं होता है तो इसे View/ViewGroup पर बुलाया जाता है।

यदि आप अपने बच्चों पर घटनाओं को अक्षम किए बिना TouchEvents/MotionEvents का पूर्वावलोकन करना चाहते हैं, तो आपको दो चीज़ें करना होगा:

  1. ईवेंट का पूर्वावलोकन करने और super.dispatchTouchEvent(ev) वापस करने के लिए dispatchTouchEvent को ओवरराइड करें;
  2. onTouchEvent ओवरराइड करें और सत्य लौटें, अन्यथा आपको MotionEvent को छोड़कर कोई MotionEvent नहीं मिलेगा।

यदि आप स्वाइप ईवेंट की तरह कुछ इशारा पता लगाना चाहते हैं, तब तक जब तक आपको इशारा नहीं पता चला, तब तक आपके बच्चों पर अन्य घटनाओं को अक्षम किए बिना, आप इसे इस तरह से कर सकते हैं:

  1. ऊपर वर्णित मोशनवेन्ट्स का पूर्वावलोकन करें और जब आपने अपना इशारा पता लगाया तो ध्वज सेट करें।
  2. onInterceptTouchEvent सही लौटें जब आपका ध्वज आपके बच्चों द्वारा मोशनएवेंट प्रोसेसिंग को रद्द करने के लिए सेट हो। यह आपके ध्वज को रीसेट करने के लिए एक सुविधाजनक स्थान भी है, क्योंकि InterceptTouchEvent को अगले MotionEvent.ACTION_DOWN तक फिर से नहीं बुलाया जाएगा।

FrameLayout में ओवरराइड का उदाहरण (मेरा उदाहरण सी # है क्योंकि मैं एक्समरिन एंड्रॉइड के साथ प्रोग्रामिंग कर रहा हूं, लेकिन तर्क जावा में समान है):

public override bool DispatchTouchEvent(MotionEvent e)
{
    // Preview the touch event to detect a swipe:
    switch (e.ActionMasked)
    {
        case MotionEventActions.Down:
            _processingSwipe = false;
            _touchStartPosition = e.RawX;
            break;
        case MotionEventActions.Move:
            if (!_processingSwipe)
            {
                float move = e.RawX - _touchStartPosition;
                if (move >= _swipeSize)
                {
                    _processingSwipe = true;
                    _cancelChildren = true;
                    ProcessSwipe();
                }
            }
            break;
    }
    return base.DispatchTouchEvent(e);
}

public override bool OnTouchEvent(MotionEvent e)
{
    // To make sure to receive touch events, tell parent we are handling them:
    return true;
}

public override bool OnInterceptTouchEvent(MotionEvent e)
{
    // Cancel all children when processing a swipe:
    if (_cancelChildren)
    {
        // Reset cancel flag here, as OnInterceptTouchEvent won't be called until the next MotionEventActions.Down:
        _cancelChildren = false;
        return true;
    }
    return false;
}

प्रेषण टचवेन्ट इन्टरसेप्ट टचवेन्ट पर पहले संभालता है।

इस सरल उदाहरण का उपयोग करना:

   main = new LinearLayout(this){
        @Override
        public boolean onInterceptTouchEvent(MotionEvent ev) {
            System.out.println("Event - onInterceptTouchEvent");
            return super.onInterceptTouchEvent(ev);
            //return false; //event get propagated
        }
        @Override
        public boolean dispatchTouchEvent(MotionEvent ev) {
            System.out.println("Event - dispatchTouchEvent");
            return super.dispatchTouchEvent(ev);
            //return false; //event DONT get propagated
        }
    };

    main.setBackgroundColor(Color.GRAY);
    main.setLayoutParams(new LinearLayout.LayoutParams(320,480));    


    viewA = new EditText(this);
    viewA.setBackgroundColor(Color.YELLOW);
    viewA.setTextColor(Color.BLACK);
    viewA.setTextSize(16);
    viewA.setLayoutParams(new LinearLayout.LayoutParams(320,80));
    main.addView(viewA);

    setContentView(main);

आप देख सकते हैं कि लॉग विलल इस तरह होगा:

I/System.out(25900): Event - dispatchTouchEvent
I/System.out(25900): Event - onInterceptTouchEvent

तो यदि आप इन 2 हैंडलर के साथ काम कर रहे हैं तो प्रेषण टचवेन्ट का उपयोग उदाहरण के पहले उदाहरण को संभालने के लिए करें, जो इंटरसेप्ट टचवेन्ट पर जाएगा।

एक और अंतर यह है कि अगर प्रेषण टचवेन्ट वापसी 'झूठी' घटना को बच्चे को प्रचारित नहीं किया जाता है, इस मामले में एडिटटेक्स्ट, जबकि अगर आप इन्टरसेप्ट टचवेन्ट पर झूठी वापसी करते हैं तो ईवेंट अभी भी संपादन टेक्स्ट में प्रेषण प्राप्त करता है


गतिविधि और दृश्य दोनों में विधि प्रेषण है टचवेन्ट () और टचवेन्ट। व्यू ग्रुप में यह विधियां भी हैं, लेकिन इनसेप्टसेप्ट टचएवेंट पर एक और तरीका है। उन विधियों का रिटर्न प्रकार बुलियन है, आप रिटर्न वैल्यू के माध्यम से प्रेषण मार्ग को नियंत्रित कर सकते हैं।

एंड्रॉइड में इवेंट प्रेषण गतिविधि-> व्यू ग्रुप-> व्यू से शुरू होता है।


संक्षिप्त उत्तर: dispatchTouchEvent() को सबसे पहले बुलाया जाएगा।

लघु सलाह: dispatchTouchEvent() ओवरराइड नहीं करना चाहिए क्योंकि इसे नियंत्रित करना मुश्किल है, कभी-कभी यह आपके प्रदर्शन को धीमा कर सकता है। onInterceptTouchEvent() , मैं onInterceptTouchEvent() ओवरराइड करने का सुझाव देता हूं।

चूंकि अधिकतर उत्तर गतिविधि / दृश्य समूह / दृश्य पर प्रवाह स्पर्श ईवेंट के बारे में स्पष्ट रूप से उल्लेख करते हैं, इसलिए मैं केवल ViewGroup में इन विधियों पर कोड के बारे में अधिक जानकारी जोड़ता हूं ( dispatchTouchEvent() ViewGroup dispatchTouchEvent() अनदेखा कर रहा हूं):

onInterceptTouchEvent() को पहले कहा जाएगा, क्रिया घटना क्रमशः नीचे -> move -> up कहा जाएगा। 2 मामले हैं:

  1. यदि आप 3 मामलों (ACTION_DOWN, ACTION_MOVE, ACTION_UP) में झूठी वापसी करते हैं , तो यह विचार करेगा क्योंकि माता-पिता को इस स्पर्श ईवेंट की आवश्यकता नहीं होगी , इसलिए माता-पिता के onTouch() पर कभी भी कॉल नहीं होता है , लेकिन बच्चों के onTouch() के बजाय कॉल करेंगे ; हालांकि कृपया ध्यान दें:

    • onInterceptTouchEvent() अभी भी टच इवेंट प्राप्त करना जारी रखता है, जब तक कि उसके बच्चे onInterceptTouchEvent() नहीं करते हैं requestDisallowInterceptTouchEvent(true)
    • अगर उस घटना को प्राप्त करने वाले कोई बच्चे नहीं हैं (यह 2 मामलों में हो सकता है: उपयोगकर्ताओं को स्पर्श करने की स्थिति में कोई बच्चा नहीं है, या बच्चे हैं लेकिन यह ACTION_DOWN पर झूठा लौटाता है), माता-पिता उस घटना को वापस onTouch() पर भेज देंगे माता-पिता।
  2. इसके विपरीत, यदि आप सच वापस आते हैं , तो माता-पिता तुरंत इस स्पर्श ईवेंट को चुरा लेंगे , और onInterceptTouchEvent() तुरंत बंद हो जाएंगे, इसके बजाय माता-पिता के onTouch() के साथ-साथ बच्चों के सभी onTouch() को अंतिम क्रिया ईवेंट प्राप्त होगा - ACTION_CANCEL (इस प्रकार, इसका मतलब है कि माता-पिता ने टच इवेंट चुरा लिया है, और बच्चे इसे तब से संभाल नहीं सकते हैं)। onInterceptTouchEvent() झूठी वापसी का प्रवाह सामान्य है, लेकिन वापसी के मामले में थोड़ा उलझन है, इसलिए मैं इसे यहां सूचीबद्ध करता हूं:

    • ACTION_DOWN पर सही लौटें, माता-पिता के onTouch() को ACTION_DOWN फिर से और क्रियाओं (ACTION_MOVE, ACTION_UP) के बाद प्राप्त होगा।
    • ACTION_MOVE पर सत्य लौटें, माता-पिता के onTouch() को अगले ACTION_MOVE प्राप्त होगा (एंटरसेप्ट onInterceptTouchEvent() ) पर और उसी क्रिया (ACTION_MOVE, ACTION_UP) में एक ही ACTION_MOVE नहीं होगा।
    • माता-पिता के ACTION_UP पर, onTouch() पर वापस लौटें, क्योंकि माता-पिता के लिए स्पर्श ईवेंट चोरी करने में बहुत देर हो चुकी है।

एक और बात महत्वपूर्ण है कि onTouch() में ईवेंट की ACTION_DOWN यह निर्धारित करेगी कि दृश्य उस घटना से अधिक कार्रवाई प्राप्त करना चाहेगा या नहीं। यदि दृश्य onTouch() में ACTION_DOWN पर सत्य लौटाता है, तो इसका अर्थ यह है कि दृश्य उस ईवेंट से अधिक कार्रवाई प्राप्त करने के इच्छुक है। अन्यथा, onTouch() में ACTION_DOWN पर झूठी वापसी का अर्थ यह होगा कि दृश्य उस घटना से और अधिक कार्रवाई नहीं करेगा।


पूरक उत्तर

अन्य उत्तरों के लिए यहां कुछ दृश्य पूरक हैं। मेरा पूरा जवाब here ।

dispatchTouchEvent() onInterceptTouchEvent() dispatchTouchEvent() विधि onInterceptTouchEvent() पर यह चुनने के लिए उपयोग onInterceptTouchEvent() कि इसे तुरंत टच इवेंट ( onInterceptTouchEvent() साथ) या अपने बच्चों के dispatchTouchEvent() onInterceptTouchEvent() dispatchTouchEvent() विधियों को सूचित करना जारी रखना चाहिए या नहीं।


व्यू ग्रुप सबक्लास के भीतर निम्न कोड इसके माता-पिता कंटेनरों को स्पर्श ईवेंट प्राप्त करने से रोक देगा:

  @Override
  public boolean dispatchTouchEvent(MotionEvent ev) {
    // Normal event dispatch to this container's children, ignore the return value
    super.dispatchTouchEvent(ev);

    // Always consume the event so it is not dispatched further up the chain
    return true;
  }

पृष्ठभूमि दृश्यों को स्पर्श घटनाओं के जवाब देने से रोकने के लिए मैंने इसे कस्टम ओवरले के साथ उपयोग किया।





android-touch-event