2009-05-18 22 views
7

कृपया कोई नोब आउट करने में मदद कर सकता है? मैंने इस समस्या को विभिन्न मंचों पर पोस्ट किया है और मुझे कोई जवाब नहीं मिला है, जबकि अन्य उत्तरों की कई खोजों ने स्टैक ओवरफ्लो को बदल दिया है, इसलिए मुझे उम्मीद है कि यह जगह है।UIScrollView स्पर्श बनाम सबव्यूव स्पर्श

मुझे मिल गया है एक BeachView.h (subclass UIScrollView, एक रेतीले समुद्र तट की तस्वीर) Stone.h (UIImageView, एक पत्थर के एक यादृच्छिक PNG, userInteractionEnabled के उपवर्ग के एक यादृच्छिक संख्या = हाँ छूता है स्वीकार करने के लिए के साथ कवर किया)।

यदि उपयोगकर्ता समुद्र तट पर छूता है और चलता है, तो उसे स्क्रॉल करना चाहिए। यदि उपयोगकर्ता पत्थर को टैप करता है, तो उसे "touchStone" विधि को कॉल करना चाहिए। यदि उपयोगकर्ता समुद्र तट पर टैप करता है जहां कोई पत्थर नहीं है, तो उसे "स्पर्श स्पर्श" विधि को कॉल करना चाहिए।

अब, मुझे एहसास हुआ कि यह मृत सरल लगता है। हर कोई और सबकुछ मुझे बताता है कि यदि UIScrollView पर कुछ ऐसा है जो छूता है तो उसे उस पर नियंत्रण रखना चाहिए। तो जब मैं स्पर्श और खींचता हूं, तो उसे स्क्रॉल करना चाहिए; लेकिन अगर मैं टैप करता हूं, और यह पत्थर पर है, तो इसे समुद्र तट के नल को नजरअंदाज करना चाहिए और पत्थर के नल को स्वीकार करना चाहिए, हाँ?

हालांकि, ऐसा लगता है कि दोनों विचार टैप स्वीकार कर रहे हैं और दोनों स्पर्श किए गए स्टोन और स्पर्श किए गए हैं। इसके अलावा, समुद्र तट टैप पहले होता है, इसलिए मैं "अगर छुआ हुआ स्टोन फिर स्पर्श न करें" प्रकार ध्वज में भी डाल नहीं सकता है।

यहां कुछ कोड है। BeachView.m


- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { 
    if (self.decelerating) { didScroll = YES; } 
     else { didScroll = NO; } 

    UITouch *touch = [[event allTouches] anyObject]; 
    CGPoint touchLocation = [touch locationInView:touch.view]; 
    NSLog(@"touched beach = %@", [touch view]); 
    lastTouch = touchLocation; 
    [super touchesBegan:touches withEvent:event]; 
} 

-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event { 
    didScroll = YES; 
    [super touchesMoved:touches withEvent:event]; 
} 

-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { 
    if (didScroll == NO && isPaused == NO) { 
      [self touchedBeach:YES location:lastTouch]; 
    } 
    [super touchesEnded:touches withEvent:event]; 
} 

पर Stone.m


-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { 
    [parent stoneWasTouched]; // parent = ivar pointing from stone to beachview 
} 

-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { 
    UITouch *touch = [[event allTouches] anyObject]; 
    CGPoint touchLocation = [touch locationInView:touch.view]; 
    NSLog(@"touched stone = %@", [touch view]); 
    [parent touchedStone:YES location:touchLocation]; 
} 

एक पत्थर नल के बाद पर, मेरे NSLog इस तरह दिखता है:


Touched beach = <BeachView: 0x1276a0> 
ran touchedBeach 
Touched Stone = <Stone: 0x1480c0> 
ran touchedStone 

तो यह वास्तव में दोनों चल रहा है। यहां तक ​​कि अजनबी भी है यदि मैं स्पर्श करता हूं, तोगन और स्पर्शों को Stone.m से बाहर निकाला जाता है लेकिन उपयोगकर्ता छोड़ देंइंटरएक्शन सक्षम = हाँ, समुद्र तट दृश्य रजिस्टर दोनों ही छूते हैं, लेकिन स्टोन को स्पर्श के रूप में देखते हैं (दूसरी बार)।


Touched beach = <BeachView: 0x1276a0> 
ran touchedBeach 
Touched beach = <Stone: 0x1480c0> 
ran touchedBeach 

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

उत्तर

2

आईफोन ओएस 3.0 से पहले, यूआईएसक्रॉल व्यू का हिटटेस्ट: साथ: विधि हमेशा स्वयं को वापस लौटाती है ताकि इसे सीधे यूआईईवेंट प्राप्त हो, केवल इसे उचित सबव्यूव में अग्रेषित कर दिया जाए, जब यह निर्धारित करता है कि यह स्क्रॉलिंग या ज़ूमिंग से संबंधित नहीं है।

मैं वास्तव में iPhone OS 3.0 यह एनडीए के अंतर्गत है के रूप में इस पर टिप्पणी नहीं कर सकता, लेकिन जाँच अपने "iPhone SDK रिलीज iPhone OS 3.0 बीटा 5 के लिए नोट" :)

आप लक्षित करना पूर्व -3.0 की जरूरत है, तो आप हिटटेस्ट को ओवरराइड कर सकता है: साथ: बीचव्यू में और अगली समुद्र तट स्पर्श को अनदेखा करने के लिए ध्वज सेट करें यदि CGPoint वास्तव में पत्थर में है।

लेकिन क्या आपने अपनी ओवरराइड विधियों के अंत से शुरुआत में [सुपर स्पर्श *: withEvent:] पर अपनी कॉल को स्थानांतरित करने का प्रयास किया है? इससे पत्थर की नल पहले हो सकती है।

+0

मैं तरीकों के शुरू करने के [सुपर] ले जाया गया है और यह एक नई पहल की समीक्षा करें। यह अभी भी दो नल पंजीकृत करता है लेकिन कम से कम अब यह कह रहा है 1-शुरू हुआबच 2-स्टार्टस्टोन 3-एंडेड 4-एंडस्टोन, इसलिए वहां एक ध्वज पॉप करने का समय है। मैं हिटटेस्ट पर बस देख रहा था, लेकिन जब उसने CAlayers बनाम UIviews के बारे में बात करना शुरू किया, तो यह एक पुस्तक की तरह लग रहा था जिसे मैं खोलने के लिए तैयार नहीं था। मैं इसे एक और शॉट दूंगा। धन्यवाद Hatfinch, -k। –

3

सच है, आईफोन एसडीके 3.0 और ऊपर, -touchesBegan: और touchesEnded: ** UIScrollview ** सबक्लास विधियों को स्पर्श न करें।आप touchesShouldBegin और touchesShouldCancelInContentView विधियों का उपयोग कर सकते हैं जो समान नहीं हैं।

यदि आप वास्तव में यह स्पर्श प्राप्त करना चाहते हैं, तो हैक है जो इसकी अनुमति देता है।

UIScrollView ओवरराइड hitTest विधि के अपने उपवर्ग में इस तरह:

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event { 

    UIView *result = nil; 
    for (UIView *child in self.subviews) 
    if ([child pointInside:point withEvent:event]) 
     if ((result = [child hitTest:point withEvent:event]) != nil) 
     break; 

    return result; 
} 

यह आपको उपवर्ग को यह छूता है पारित करेंगे, फिर भी आप UIScrollView सुपर वर्ग के लिए अंतिम रूप नहीं ले सकते।

0

मैं एक simpleView के साथ एक समान समस्या थी और यह एक scrollView में जोड़ा जाता है, और जब भी मैं simpleView छुआ, scrollView स्पर्श पाने के लिए इस्तेमाल किया और इसके बजाय simpleView की, scrollView ले जाया गया। इससे बचने के लिए, मैंने scrollView के srcolling को अक्षम कर दिया जब उपयोगकर्ता simpleView को स्पर्श करता था और अन्यथा स्क्रॉलिंग सक्षम होती है।

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event { 

    UIView *result = [super hitTest:point withEvent:event] ; 
    if (result == simpleView) 
    { 
     scrollView.scrollEnabled = NO ; 
    } 
    else 
    { 
     scrollView.scrollEnabled = YES ; 
    } 

    return result ; 

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