एक और UIView के तहत एक UIView के साथ बातचीत की अनुमति


115

क्या UIView में एक बटन के साथ बातचीत की अनुमति देने का एक सरल तरीका है जो किसी अन्य UIView के अंतर्गत आता है - जहाँ बटन के शीर्ष पर UIView से कोई वास्तविक वस्तु नहीं हैं?

उदाहरण के लिए, इस समय मेरे पास UIView (A) शीर्ष पर एक वस्तु है और स्क्रीन के नीचे एक वस्तु है और बीच में कुछ भी नहीं है। यह एक और UIView के ऊपर बैठता है जिसमें बीच में बटन होते हैं (B)। हालाँकि, मैं बी के बीच में बटन के साथ बातचीत नहीं कर सकता।

मैं बी में बटन देख सकता हूं - मैंने ए की पृष्ठभूमि को स्पष्ट करने के लिए सेट किया है - लेकिन बी में बटन इस तथ्य के बावजूद स्पर्श प्राप्त नहीं करते हैं कि वास्तव में उन बटन के शीर्ष पर ए से कोई ऑब्जेक्ट नहीं हैं।

संपादित करें - मैं अभी भी शीर्ष UIView में वस्तुओं के साथ बातचीत करने में सक्षम होना चाहता हूं

निश्चित रूप से ऐसा करने का एक सरल तरीका है?


2
इसके बहुत सारे यहाँ समझाया गया है: developer.apple.com/iphone/library/documentation/iPhone/… लेकिन मूल रूप से, हिट को ओवरराइड करें: withEvent :, वे यहां तक ​​कि एक कोड नमूने की आपूर्ति करते हैं।
nash

मैंने उसके लिए एक छोटी कक्षा लिखी है। (उत्तरों में एक उदाहरण जोड़ा गया)। वहाँ का समाधान स्वीकृत उत्तर की तुलना में कुछ बेहतर है क्योंकि आप अभी भी उस पर क्लिक कर सकते हैं UIButtonजो एक अर्ध पारदर्शी के तहत है UIViewजबकि गैर पारदर्शी भाग UIViewअभी भी स्पर्श घटनाओं पर प्रतिक्रिया देगा।
सेगेव

जवाबों:


97

आपको अपने शीर्ष दृश्य के लिए एक UIView उपवर्ग बनाना चाहिए और निम्नलिखित विधि को ओवरराइड करना चाहिए:

- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event {
    // UIView will be "transparent" for touch events if we return NO
    return (point.y < MIDDLE_Y1 || point.y > MIDDLE_Y2);
}

आप हिटस्ट: इवेंट: मेथड को भी देख सकते हैं।


19
यहाँ किसका प्रतिनिधित्व__1 / y2 है?
जेसन रेनाल्डो

यकीन नहीं होता कि वह returnबयान क्या कर रहा है, लेकिन return CGRectContainsPoint(eachSubview.frame, point)मेरे लिए काम करता है। अत्यंत उपयोगी उत्तर अन्यथा
n00neimp0rtant

MIDDLE_Y1 / Y2 व्यवसाय केवल एक उदाहरण है। यह समारोह MIDDLE_Y1<=y<=MIDDLE_Y2क्षेत्र में स्पर्श घटनाओं के लिए "पारदर्शी" होगा ।
जिमी

41

हालांकि यहां कई उत्तर काम करेंगे, मैं यह देखकर थोड़ा हैरान हूं कि सबसे सुविधाजनक, सामान्य और मूर्खतापूर्ण जवाब यहां नहीं दिया गया है। @Ash करीब आ गया, सिवाय इसके कि वहाँ कुछ अजीब चल रहा है जिससे पर्यवेक्षणकर्ता लौट रहा है ... ऐसा मत करो।

यह उत्तर मैंने एक ऐसे ही प्रश्न के उत्तर से लिया है, यहाँ

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
    UIView *hitView = [super hitTest:point withEvent:event];
    if (hitView == self) return nil;
    return hitView;
}

[super hitTest:point withEvent:event]उस दृश्य के पदानुक्रम में सबसे गहरा दृश्य वापस आ जाएगा जिसे छुआ गया था। यदि hitView == self(अर्थात यदि स्पर्श बिंदु के नीचे कोई सबव्यू नहीं है), लौटें nil, यह निर्दिष्ट करते हुए कि यह दृश्य स्पर्श प्राप्त नहीं करना चाहिए । जिस तरह से रिस्पॉन्डर चेन काम करती है, इसका मतलब है कि इस बिंदु के ऊपर पदानुक्रम तब तक ट्रैवर्स किया जाएगा, जब तक कि कोई व्यू नहीं मिलता है जो टच का जवाब देगा। पर्यवेक्षण को वापस न करें , क्योंकि यह इस दृष्टिकोण पर निर्भर नहीं है कि उसके पर्यवेक्षक को स्पर्श स्वीकार करना चाहिए या नहीं!

यह समाधान है:

  • सुविधाजनक है , क्योंकि इसमें किसी अन्य विचार / साक्षात्कार / वस्तुओं के संदर्भ की आवश्यकता नहीं है;
  • सामान्य , क्योंकि यह किसी भी दृश्य पर लागू होता है जो विशुद्ध रूप से उप-साक्षात्कार के लिए एक कंटेनर के रूप में कार्य करता है, और साक्षात्कारों का कॉन्फ़िगरेशन उस तरीके को प्रभावित नहीं करता है जैसे यह काम करता है (जैसा कि यदि आप pointInside:withEvent:किसी विशेष स्पर्श करने योग्य क्षेत्र को वापस करने के लिए ओवरराइड करते हैं)।
  • मूर्ख , बहुत कोड नहीं है ... और अवधारणा आपके सिर के चारों ओर ले जाना मुश्किल नहीं है।

मैं अक्सर इसका उपयोग करता हूं कि मैंने एक ओवरराइड के लिए व्यर्थ दृश्य उपवर्गों को बचाने के लिए इसे एक उपवर्ग में सार कर दिया है। एक बोनस के रूप में, इसे कॉन्फ़िगर करने योग्य बनाने के लिए एक संपत्ति जोड़ें:

@interface ISView : UIView
@property(nonatomic, assign) BOOL onlyRespondToTouchesInSubviews;
@end

@implementation ISView
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
    UIView *hitView = [super hitTest:point withEvent:event];
    if (hitView == self && onlyRespondToTouchesInSubviews) return nil;
    return hitView;
}
@end

फिर जंगली जायें और इस दृश्य का उपयोग करें जहाँ भी आप एक मैदान का उपयोग कर सकते हैं UIView। इसे कॉन्फ़िगर करना उतना ही सरल है जितना कि सेटिंग onlyRespondToTouchesInSubviewsकरना YES


2
एकमात्र सही उत्तर। स्पष्ट होने के लिए, यदि आप किसी दृश्य को स्पर्श को अनदेखा करना चाहते हैं , लेकिन दृश्य में निहित किसी भी बटन (कहते हैं) को नहीं , जैसा कि स्टुअर्ट बताते हैं। (मैं आमतौर पर इसे "धारक दृश्य" कहता हूं क्योंकि यह हानिरहित कुछ बटन "पकड़" कर सकता है, लेकिन, यह "धारक" के नीचे "कुछ भी प्रभावित नहीं करता है।"
Fattie

अंक का उपयोग करने वाले कुछ अन्य समाधानों में समस्याएं हैं यदि आपका दृश्य स्क्रॉल करने योग्य है, जैसे कि UITableView og UICollectionView और आपने ऊपर या नीचे स्क्रॉल किया है। यह समाधान, स्क्रॉलिंग की परवाह किए बिना काम करता है।
पजेसिव

31

ऐसे कई तरीके हैं जिनसे आप इसे संभाल सकते हैं। मेरा पसंदीदा हिटस्टेस्ट को ओवरराइड करना है: withEvent: एक ऐसे दृश्य में, जो परस्पर विरोधी विचारों के लिए एक सामान्य पर्यवेक्षण (शायद अप्रत्यक्ष रूप से) है (लगता है जैसे आप इन ए और बी को बुलाते हैं)। उदाहरण के लिए, कुछ इस तरह (यहाँ ए और बी उविएव पॉइंटर्स हैं, जहाँ बी "छिपा हुआ" है, जो सामान्य रूप से अनदेखा है):

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
    CGPoint pointInB = [B convertPoint:point fromView:self];

    if ([B pointInside:pointInB withEvent:event])
        return B;

    return [super hitTest:point withEvent:event];
}

pointInside:withEvent:जैसा कि gimim सुझाया गया है आप विधि को संशोधित भी कर सकते हैं । यह आपको कम से कम स्पर्श के लिए ए में प्रभावी रूप से "एक छेद पोकिंग" द्वारा एक ही परिणाम प्राप्त करने देता है।

एक अन्य दृष्टिकोण है ईवेंट फॉरवर्डिंग, जिसका अर्थ है ओवरराइडिंग touchesBegan:withEvent:और इसी तरह के तरीके (जैसे touchesMoved:withEvent:आदि) कुछ स्पर्शों को एक अलग ऑब्जेक्ट पर भेजने के लिए जहां वे पहले जाते हैं। उदाहरण के लिए, ए में, आप कुछ इस तरह से लिख सकते हैं:

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    if ([self shouldForwardTouches:touches]) {
        [B touchesBegan:touches withEvent:event];
    }
    else {
        // Do whatever A does with touches.
    }
}

हालांकि, यह हमेशा आपकी अपेक्षा के अनुरूप काम नहीं करेगा ! मुख्य बात यह है कि UIButton जैसे अंतर्निहित नियंत्रण हमेशा अग्रेषित स्पर्शों की उपेक्षा करेंगे। इस वजह से, पहला दृष्टिकोण अधिक विश्वसनीय है।

विचारों को प्रदर्शित करने के लिए एक छोटे से काम कर रहे xcode प्रोजेक्ट के साथ, यहाँ और अधिक विस्तार से बताने वाला एक अच्छा ब्लॉग पोस्ट यहाँ उपलब्ध है:

http://bynomial.com/blog/?p=74


इस समाधान के साथ मुद्दा - सामान्य पर्यवेक्षण पर हिटटेस्ट को ओवरराइड करना - यह है कि यह नीचे के दृश्य को पूरी तरह से सही ढंग से काम करने की अनुमति नहीं देता है जब नीचे का दृश्य स्क्रॉल करने योग्य दृश्य (मैप व्यू आदि) के पूरे सेट में से एक है। शीर्ष दृश्य पर ओवरराइडिंग करना। जैसा कि मैं बता सकता हूं सभी मामलों में नीचे gyim द्वारा सुझाए गए शीर्ष दृश्य पर काम करता है।
डेलानी

@ डेली, यह सच नहीं है; आपके पास अन्य दृश्यों के नीचे स्क्रॉल करने योग्य दृश्य हो सकते हैं और हिटटेस्ट को ओवरराइड करके दोनों काम कर सकते हैं। यहाँ कुछ सैंपल कोड है: bynomial.com/blogfiles/Temp32.zip
टायलर

अरे। सभी स्क्रॉल करने योग्य दृश्य नहीं - बस कुछ ... मैंने ऊपर से आपके ज़िप कोड की कोशिश की, UIScrollView को एक (उदाहरण के लिए) MKMapView में बदल दिया और यह काम नहीं करता है। नल का काम - यह स्क्रॉल है जो कि मुद्दा लगता है।
दिल्ली

ठीक है, मैंने इसकी जाँच की और पुष्टि की कि हिटटेस्ट उस तरह से काम नहीं करता है जैसा आप एमकेपॉच व्यू के साथ कर सकते हैं। आप उस बारे में सही थे, @delany; हालांकि यह UIScrollView के साथ सही ढंग से काम करता है। मुझे आश्चर्य है कि MKMapView विफल क्यों होता है?
टायलर

@ टायलर जैसा कि आपने उल्लेख किया है, "मुख्य बात यह है कि यूआईयूटन जैसे अंतर्निहित नियंत्रण हमेशा आगे के स्पर्श को अनदेखा करेंगे", मैं जानना चाहता हूं कि आप कैसे जानते हैं कि और क्या यह इस व्यवहार को समझाने के लिए एक आधिकारिक दस्तावेज है। मुझे एक समस्या का सामना करना पड़ा है कि जब यूबूटन के पास एक सादा यूआईवीयूई सबव्यू है, तो यह सबव्यू की सीमा में घटनाओं को छूने का जवाब नहीं देगा। और मैंने पाया कि इस कार्यक्रम को यूआईवीवाईई के डिफ़ॉल्ट व्यवहार के रूप में यूआईब्यूटन को ठीक से अग्रेषित किया गया है, लेकिन मुझे यकीन नहीं है कि यह एक निर्दिष्ट सुविधा या सिर्फ बग है। क्या आप कृपया मुझे इसके बारे में दस्तावेज दिखाएंगे? बहुत बहुत धन्यवाद।
नील। मर्लिन

29

आपको सेट करना होगा upperView.userInteractionEnabled = NO;, अन्यथा ऊपरी दृश्य स्पर्शों को बाधित करेगा।

इसका इंटरफ़ेस बिल्डर संस्करण "उपयोगकर्ता सहभागिता सक्षम" नामक दृश्य गुण पैनल के निचले भाग में एक चेकबॉक्स है। इसे अनचेक करें और आपको जाने के लिए अच्छा होना चाहिए।


सॉरी - कहना चाहिए था। मैं अभी भी शीर्ष UIView में वस्तुओं के साथ बातचीत करने में सक्षम होना चाहता हूं।
प्रातः काल 7:00

लेकिन ऊपरी दृश्य को कोई स्पर्श प्राप्त नहीं हो सकता है, ऊपरी दृश्य में बटन शामिल करें।
imcaptor

2
यह समाधान मेरे लिए काम करता है। मुझे छूने के लिए प्रतिक्रिया करने के लिए ऊपरी दृश्य की आवश्यकता नहीं थी।
TJ

11

पॉइंट इंसाइड का कस्टम कार्यान्वयन: withEvent: वास्तव में जाने के लिए रास्ते की तरह लग रहा था, लेकिन हार्ड-कोडेड निर्देशांक के साथ काम करना मुझे अजीब लग रहा था। इसलिए मैंने यह जांचना समाप्त कर दिया कि क्या CGRect बटन CGRect के अंदर CGRectContainsPoint () फ़ंक्शन का उपयोग कर रहा है:

- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event {
    return (CGRectContainsPoint(disclosureButton.frame, point));
}

8

हाल ही में मैंने एक वर्ग लिखा है जो मुझे बस उसी के साथ मदद करेगा। यह एक कस्टम वर्ग के रूप में UIButtonया के लिए UIViewएक पारदर्शी पिक्सेल पर निष्पादित की गई स्पर्श घटनाओं को पारित करेगा।

यह समाधान स्वीकृत उत्तर की तुलना में कुछ हद तक बेहतर है क्योंकि आप अभी भी UIButtonएक अर्ध पारदर्शी के नीचे क्लिक कर सकते हैं UIViewजबकि गैर पारदर्शी भाग UIViewअभी भी स्पर्श घटनाओं पर प्रतिक्रिया देगा।

GIF

जैसा कि आप जीआईएफ में देख सकते हैं, जिराफ बटन एक साधारण आयत है, लेकिन पारदर्शी क्षेत्रों पर स्पर्श की घटनाओं को पीले रंग के UIButtonनीचे से पारित किया जाता है।

कक्षा से लिंक करें


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

धन्यवाद, आपका समाधान मेरे मामले के लिए काम करता है जहां मुझे घटनाओं को छूने के लिए प्रतिक्रिया देने के लिए मेरे UIView के गैर पारदर्शी हिस्से की आवश्यकता होती है, जबकि पारदर्शी भाग नहीं होता है। प्रतिभाशाली!
ब्रूस

@ ब्रूस खुशी यह आपकी मदद की!
सेगेव

4

मुझे लगता है कि मुझे इस पार्टी में थोड़ी देर हो गई है, लेकिन मैं इस संभावित समाधान को जोड़ूंगा:

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
    UIView *hitView = [super hitTest:point withEvent:event];
    if (hitView != self) return hitView;
    return [self superview];
}

यदि आप इस कोड का उपयोग कस्टम UIView के मानक हिटटेस्ट फ़ंक्शन को ओवरराइड करने के लिए करते हैं, तो यह केवल दृश्य को अनदेखा कर देगा। उस दृश्य के किसी भी उप-साक्षात्कार में उनके हिट सामान्य रूप से वापस आ जाएंगे, और जो भी दृश्य देखने गए हैं, वे अपने सुपरवाइज़ को पास कर देंगे।

-Ash


1
यह मेरे लिए पसंदीदा तरीका है, मुझे नहीं लगता कि आपको वापस लौटना चाहिए [self superview]। इस पद्धति पर दस्तावेज़ीकरण "दृश्य पदानुक्रम में रिसीवर का सबसे दूर का वंशज (स्वयं सहित) देता है जिसमें एक निर्दिष्ट बिंदु होता है" और "रिटर्न शून्य होता है यदि बिंदु रिसीवर के पदानुक्रम के बाहर पूरी तरह से निहित होता है"। मुझे लगता है कि आपको वापस लौट जाना चाहिए nil। जब आप शून्य पर लौटते हैं, तो यह देखने के लिए कि यह कोई हिट है या नहीं, इसके लिए सुपरवाइज को कंट्रोल पास करेगा। इसलिए मूल रूप से यह वही काम करेगा, जो पर्यवेक्षण के अलावा भविष्य में कुछ तोड़ सकता है।
जसोन्गग्रेरी

ज़रूर, यह शायद समझदारी होगी (मेरे मूल उत्तर पर तारीख नोट करें - तब से बहुत अधिक कोडिंग की गई)
ऐश

4

बस स्वीकृत उत्तर पर भरोसा करना और इसे मेरे संदर्भ के लिए यहां रखना। स्वीकृत उत्तर पूरी तरह से काम करता है। आप इसे इस तरह से बढ़ा सकते हैं कि आपके दृश्य के साक्षात्कारों को स्पर्श प्राप्त कर सकें, या इसे हमारे पीछे किसी भी दृश्य पर भेज सकें:

- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event {
    // If one of our subviews wants it, return YES
    for (UIView *subview in self.subviews) {
        CGPoint pointInSubview = [subview convertPoint:point fromView:self];
        if ([subview pointInside:pointInSubview withEvent:event]) {
            return YES;
        }
    }
    // otherwise return NO, as if userInteractionEnabled were NO
    return NO;
}

नोट: आपको सबव्यू ट्री पर पुनरावृत्ति करने की भी आवश्यकता नहीं है, क्योंकि प्रत्येक pointInside:withEvent:विधि आपके लिए संभाल लेगी।


3

उपयोगकर्ता निष्क्रियकरण संपत्ति अक्षम करने से मदद मिल सकती है। उदाहरण के लिए:

UIView * topView = [[TOPView alloc] initWithFrame:[self bounds]];
[self addSubview:topView];
[topView setUserInteractionEnabled:NO];

(नोट: ऊपर दिए गए कोड में, 'स्वयं' एक दृश्य को संदर्भित करता है)

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


3

यह दृष्टिकोण काफी साफ है और यह अनुमति देता है कि पारदर्शी साक्षात्कार भी स्पर्श करने के लिए प्रतिक्रिया नहीं कर रहे हैं। बस उपवर्ग UIViewऔर इसके कार्यान्वयन के लिए निम्न विधि जोड़ें:

@implementation PassThroughUIView

- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event {
    for (UIView *v in self.subviews) {
        CGPoint localPoint = [v convertPoint:point fromView:self];
        if (v.alpha > 0.01 && ![v isHidden] && v.userInteractionEnabled && [v pointInside:localPoint withEvent:event])
            return YES;
    }
    return NO;
}

@end

2

मेरा समाधान यहाँ:

-(UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
    CGPoint pointInView = [self.toolkitController.toolbar convertPoint:point fromView:self];

    if ([self.toolkitController.toolbar pointInside:pointInView withEvent:event]) {
       self.userInteractionEnabled = YES;
    } else {
       self.userInteractionEnabled = NO;
    }

    return [super hitTest:point withEvent:event];
}

उम्मीद है की यह मदद करेगा


2

कुछ ऐसा है जिसे आप दोनों विचारों में स्पर्श को रोक सकते हैं।

शीर्ष दृश्य:

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
   // Do code in the top view
   [bottomView touchesBegan:touches withEvent:event]; // And pass them on to bottomView
   // You have to implement the code for touchesBegan, touchesEnded, touchesCancelled in top/bottom view.
}

लेकिन यह विचार है।


यह निश्चित रूप से संभव है - लेकिन बहुत काम है (आपको नीचे की परत में अपने स्वयं के स्पर्श के प्रति संवेदनशील वस्तुओं को रोल करना होगा (जैसे बटन), मुझे लगता है?) और यह अजीब लगता है कि किसी को इसमें अपना रोल करना होगा? व्यवहार प्राप्त करने का तरीका जो सहज प्रतीत होगा।
डेलानी

मुझे यकीन नहीं है कि शायद हमें इसे आज़माना चाहिए।
अलेक्जेंड्रे कैसगैन

2

यहाँ एक स्विफ्ट संस्करण है:

override func pointInside(point: CGPoint, withEvent event: UIEvent?) -> Bool {
    return !CGRectContainsPoint(buttonView.frame, point)
}

2

स्विफ्ट 3

override func point(inside point: CGPoint, with event: UIEvent?) -> Bool {
    for subview in subviews {
        if subview.frame.contains(point) {
            return true
        }
    }
    return false
}

1

मैंने UI टूलकिट का उपयोग करके कभी भी पूर्ण उपयोगकर्ता इंटरफ़ेस नहीं बनाया है, इसलिए मुझे इसके साथ बहुत अनुभव नहीं है। यहाँ मुझे लगता है कि हालांकि काम करना चाहिए।

हर UIView, और इस UIWindow के पास एक संपत्ति है subviews, जो एक NSArray है जिसमें सभी साक्षात्कार हैं।

पहला सबव्यू जिसे आप किसी दृश्य में जोड़ते हैं, सूचकांक 0 प्राप्त करेगा, और अगला सूचकांक 1 और उसके बाद। तुम भी जगह ले सकता है addSubview:के साथ insertSubview: atIndex:या insertSubview:aboveSubview:और इस तरह के तरीकों कि पदानुक्रम में अपने subview की स्थिति का निर्धारण कर सकते हैं।

तो अपने कोड को यह देखने के लिए देखें कि आप अपने UIWindow में कौन सा दृश्य जोड़ते हैं। यह 0 होगा, अन्य 1 होगा।
अब, आपके एक साक्षात्कार से, दूसरे तक पहुंचने के लिए आप निम्नलिखित कार्य करेंगे:

UIView * theOtherView = [[[self superview] subviews] objectAtIndex: 0];
// or using the properties syntax
UIView * theOtherView = [self.superview.subviews objectAtIndex:0];

मुझे पता है कि अगर आपके मामले के लिए काम करता है!


(इस मार्कर के नीचे मेरा पिछला उत्तर है):

यदि विचारों को एक-दूसरे के साथ संवाद करने की आवश्यकता है, तो उन्हें एक नियंत्रक (जो कि लोकप्रिय एमवीसी मॉडल का उपयोग करके ) के माध्यम से ऐसा करना चाहिए ।

जब आप एक नया दृश्य बनाते हैं, तो आप यह सुनिश्चित कर सकते हैं कि यह एक नियंत्रक के साथ खुद को पंजीकृत करता है।

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

यदि आपके विचार में नियंत्रक का वापस लिंक नहीं है (जो कि मामला हो सकता है) तो आप अपने नियंत्रक का संदर्भ प्राप्त करने के लिए एकल और / या वर्ग विधियों का उपयोग कर सकते हैं ।


आपके उत्तर के लिए धन्यवाद - लेकिन मुझे यकीन नहीं है कि मैं समझ गया हूँ। दोनों दृश्य में एक नियंत्रक है - मुद्दा यह है कि, एक दृश्य दूसरे के ऊपर से, नीचे का दृश्य घटनाओं को नहीं उठा रहा है (और उन्हें अपने नियंत्रक को अग्रेषित कर रहा है), यहां तक ​​कि वास्तव में उन घटनाओं को 'अवरुद्ध' करने वाली कोई वस्तु नहीं है। शीर्ष दृश्य।
डेल्ही

क्या आपके पास हमारे UIVIVs के शीर्ष पर UIWindow है? यदि आप करते हैं, तो घटनाओं को प्रचारित किया जाना चाहिए और आपको कोई "जादू" करने की आवश्यकता नहीं होनी चाहिए। Apple देव केंद्र में [विंडो और व्यूज] [1] के बारे में पढ़ें (और हर तरह से, अगर यह आपकी मदद नहीं करता है तो एक और टिप्पणी जोड़ें!) [1]: developer.apple.com/iphone/library/documentation/ iPhone /…
nash करें

हाँ, बिल्कुल - पदानुक्रम के शीर्ष पर एक UIWindow।
डेलानी

मैंने विचारों के पदानुक्रम के माध्यम से कोड को शामिल करने के लिए अपने उत्तर को अपडेट कर दिया है। मुझे पता है अगर आप किसी अन्य मदद की जरूरत है!
नैश

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

1

मुझे लगता है कि दृश्य पदानुक्रम में निर्मित दृश्य श्रृंखला का उपयोग करने का सही तरीका है। आपके दृश्य जो मुख्य दृश्य पर धकेल दिए जाते हैं, के लिए सामान्य दृश्य का उपयोग न करें, बल्कि MYView बनाने के लिए उपक्लास UIView (या इसके UIImageView जैसे संस्करणों में से एक) का उपयोग करें: UIView (या जो कुछ भी आप चाहते हैं, जैसे UIImageView)। YourView के कार्यान्वयन में, टचबेगन विधि लागू करें। यह विधि तब लागू होगी जब उस दृश्य को छुआ जाएगा। उस कार्यान्वयन में आपके पास जो कुछ होना चाहिए वह एक उदाहरण विधि है:

- (void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event ;
{   // cannot handle this event. pass off to super
    [self.superview touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event]; }

यह टचबेगन एक रिस्पॉन्डर एपी है, इसलिए आपको इसे अपने सार्वजनिक या निजी इंटरफ़ेस में घोषित करने की आवश्यकता नहीं है; यह उन जादुई एपि में से एक है जिसके बारे में आपको सिर्फ जानना है। यह self.superview अंत में viewController के अनुरोध को पूरा करेगा। व्यूकंट्रोलर में, फिर टच को संभालने के लिए इस टचबैन को लागू करें।

ध्यान दें कि स्पर्श स्थान (CGPoint) स्वचालित रूप से आपके लिए शामिल दृश्य के सापेक्ष समायोजित हो जाता है क्योंकि यह दृश्य पदानुक्रम श्रृंखला को बाउंस कर जाता है।


1

बस इसे पोस्ट करना चाहते हैं, coz मुझे कुछ इसी तरह की समस्या थी, बिना किसी भाग्य के यहां जवाबों को लागू करने की कोशिश में पर्याप्त समय बिताया। मैंने क्या किया:

 for(UIGestureRecognizer *recognizer in topView.gestureRecognizers)
 {
     recognizer.delegate=self;
     [bottomView addGestureRecognizer:recognizer];   
 }
 topView.abView.userInteractionEnabled=NO; 

और कार्यान्वयन UIGestureRecognizerDelegate:

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
    return YES;
}

नीचे का दृश्य एक नेविगेशन नियंत्रक था, जिसमें सेग की संख्या थी और मेरे पास इसके ऊपर एक दरवाजा था जो पैन इशारे से बंद हो सकता था। पूरी बात अभी तक एक और वीसी में एम्बेडेड थी। एक जादू की तरह काम किया। उम्मीद है की यह मदद करेगा।


1

हिटटेस्ट आधारित समाधान के लिए स्विफ्ट 4 कार्यान्वयन

let hitView = super.hitTest(point, with: event)
if hitView == self { return nil }
return hitView

0

स्टुअर्ट के उत्कृष्ट से व्युत्पन्न, और ज्यादातर मूर्खतापूर्ण उत्तर, और सेगेव के उपयोगी कार्यान्वयन, यहां एक स्विफ्ट 4 पैकेज है जिसे आप किसी भी परियोजना में छोड़ सकते हैं:

extension UIColor {
    static func colorOfPoint(point:CGPoint, in view: UIView) -> UIColor {

        var pixel: [CUnsignedChar] = [0, 0, 0, 0]

        let colorSpace = CGColorSpaceCreateDeviceRGB()
        let bitmapInfo = CGBitmapInfo(rawValue: CGImageAlphaInfo.premultipliedLast.rawValue)

        let context = CGContext(data: &pixel, width: 1, height: 1, bitsPerComponent: 8, bytesPerRow: 4, space: colorSpace, bitmapInfo: bitmapInfo.rawValue)

        context!.translateBy(x: -point.x, y: -point.y)

        view.layer.render(in: context!)

        let red: CGFloat   = CGFloat(pixel[0]) / 255.0
        let green: CGFloat = CGFloat(pixel[1]) / 255.0
        let blue: CGFloat  = CGFloat(pixel[2]) / 255.0
        let alpha: CGFloat = CGFloat(pixel[3]) / 255.0

        let color = UIColor(red:red, green: green, blue:blue, alpha:alpha)

        return color
    }
}

और फिर हिटटेस्ट के साथ:

override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
    guard UIColor.colorOfPoint(point: point, in: self).cgColor.alpha > 0 else { return nil }
    return super.hitTest(point, with: event)
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.