UIView फ्रेम, सीमा और केंद्र


320

मैं जानना चाहूंगा कि इन गुणों का सही तरीके से उपयोग कैसे किया जाए।

जैसा कि मैं समझता हूं, मेरे द्वारा बनाए frameजा रहे दृश्य के कंटेनर से उपयोग किया जा सकता है। यह कंटेनर दृश्य के सापेक्ष दृश्य स्थिति सेट करता है। यह उस दृश्य का आकार भी निर्धारित करता है।

मेरे द्वारा बनाए centerजा रहे दृश्य के कंटेनर से भी उपयोग किया जा सकता है। यह गुण इसके कंटेनर के सापेक्ष दृश्य की स्थिति को बदल देता है।

अंत में, boundsदृश्य के सापेक्ष है। यह दृश्य के लिए ड्रा करने योग्य क्षेत्र को बदल देता है।

क्या आप frameऔर के बीच संबंधों के बारे में अधिक जानकारी दे सकते हैं bounds? clipsToBoundsऔर masksToBoundsगुणों के बारे में क्या ?


1
यह चर्चा पहले से ही यहां हल है। इसलिए pls इसे यहां देखें या डेवलपर डॉक्यूमेंटेशन देख सकते हैं जो यहां दिया गया है। developer.apple.com/library/ios/#documentation/uikit/reference/… stackoverflow.com/questions/1210047/… स्लाइडशेयर.net/onoaonoa-cs193p-lecture-5 -व्यू-एनीमेशन
शानदार

जवाबों:


577

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

पहले प्रश्न पर एक पुनर्कथन: फ्रेम, सीमा और केंद्र और उनके रिश्ते।

फ़्रेमव्यूज़frame ( CGRect) की आयत superviewप्रणाली में इसकी आयत की स्थिति है। डिफ़ॉल्ट रूप से यह शीर्ष बाईं ओर शुरू होता है।

सीमाएं एक दृश्य का bounds( CGRect) अपने स्वयं के समन्वय प्रणाली में एक दृश्य आयत को व्यक्त करता है।

केंद्र A centerको समन्वय प्रणाली के CGPointरूप में व्यक्त किया गया superviewहै और यह दृश्य के सटीक केंद्र बिंदु की स्थिति निर्धारित करता है।

पिछले गुणों के बीच UIView + स्थिति से लिया गया ये संबंध हैं (वे कोड में काम नहीं करते हैं क्योंकि वे अनौपचारिक समीकरण हैं):

  • frame.origin = center - (bounds.size / 2.0)

  • center = frame.origin + (bounds.size / 2.0)

  • frame.size = bounds.size

नोट: ये रिश्ते लागू नहीं होते यदि दृश्य घुमाए जाते हैं। अधिक जानकारी के लिए, मैं आपको सुझाव दूंगा कि आप स्टैनफोर्ड CS193p पाठ्यक्रम पर आधारित द किचन ड्रावर से ली गई छवि पर एक नज़र डालें । क्रेडिट्स @Rhubarb को जाता है ।

फ्रेम, सीमा और केंद्र

आप का उपयोग करने के लिए frameअनुमति देता है और इसके भीतर एक दृश्य का आकार बदलने के लिए / या superview। आमतौर पर इसका उपयोग superviewउदाहरण के लिए किया जा सकता है , जब आप एक विशिष्ट सबव्यू बनाते हैं। उदाहरण के लिए:

// view1 will be positioned at x = 30, y = 20 starting the top left corner of [self view]
// [self view] could be the view managed by a UIViewController
UIView* view1 = [[UIView alloc] initWithFrame:CGRectMake(30.0f, 20.0f, 400.0f, 400.0f)];    
view1.backgroundColor = [UIColor redColor];

[[self view] addSubview:view1];

जब आपको अपने अंदर ड्राइंग करने के लिए निर्देशांक की आवश्यकता होती है तो viewआप आमतौर पर संदर्भित करते हैं bounds। एक विशिष्ट उदाहरण viewपहले के इनसेट के रूप में एक सबव्यू के भीतर आकर्षित करने के लिए हो सकता है । सबव्यू को आकर्षित करने के लिए सुपरवाइज का पता होना चाहिए bounds। उदाहरण के लिए:

UIView* view1 = [[UIView alloc] initWithFrame:CGRectMake(50.0f, 50.0f, 400.0f, 400.0f)];    
view1.backgroundColor = [UIColor redColor];

UIView* view2 = [[UIView alloc] initWithFrame:CGRectInset(view1.bounds, 20.0f, 20.0f)];    
view2.backgroundColor = [UIColor yellowColor];

[view1 addSubview:view2];

जब आप boundsकिसी दृश्य को बदलते हैं तो विभिन्न व्यवहार होते हैं। उदाहरण के लिए, यदि आप परिवर्तन करते हैं bounds size, तो frameपरिवर्तन (और इसके विपरीत)। centerदृश्य के आसपास परिवर्तन होता है । नीचे दिए गए कोड का उपयोग करें और देखें कि क्या होता है:

NSLog(@"Old Frame %@", NSStringFromCGRect(view2.frame));
NSLog(@"Old Center %@", NSStringFromCGPoint(view2.center));    

CGRect frame = view2.bounds;
frame.size.height += 20.0f;
frame.size.width += 20.0f;
view2.bounds = frame;

NSLog(@"New Frame %@", NSStringFromCGRect(view2.frame));
NSLog(@"New Center %@", NSStringFromCGPoint(view2.center));

इसके अलावा, यदि आप बदलते bounds originहैं तो आप originइसकी आंतरिक समन्वय प्रणाली को बदल देते हैं। डिफ़ॉल्ट रूप originसे (0.0, 0.0)(शीर्ष बाएं कोने में) है। उदाहरण के लिए, अगर आप को बदलने originके लिए view1आप देख सकते हैं (पिछले कोड अगर आप चाहते हैं टिप्पणी) के लिए है कि अब ऊपरी बाएं कोने view2छूता view1है। प्रेरणा काफी सरल है। आप कहते हैं कि करने के लिए view1है कि इसके ऊपर बाएं कोने अब स्थान पर है (20.0, 20.0)लेकिन जब से view2की frame originसे शुरू होता है (20.0, 20.0), वे मेल खाना होगा।

CGRect frame = view1.bounds;
frame.origin.x += 20.0f;
frame.origin.y += 20.0f;
view1.bounds = frame; 

अपने भीतर की स्थिति का originप्रतिनिधित्व करता है, लेकिन केंद्र की स्थिति का वर्णन करता है।viewsuperviewbounds

अंत में, boundsऔर originसंबंधित अवधारणाएं नहीं हैं। दोनों frameएक दृश्य को प्राप्त करने की अनुमति देते हैं (पिछले समीकरण देखें)।

देखें 1 का केस स्टडी

यहाँ निम्नलिखित स्निपेट का उपयोग करते समय क्या होता है।

UIView* view1 = [[UIView alloc] initWithFrame:CGRectMake(30.0f, 20.0f, 400.0f, 400.0f)];
view1.backgroundColor = [UIColor redColor];

[[self view] addSubview:view1];

NSLog(@"view1's frame is: %@", NSStringFromCGRect([view1 frame]));
NSLog(@"view1's bounds is: %@", NSStringFromCGRect([view1 bounds]));
NSLog(@"view1's center is: %@", NSStringFromCGPoint([view1 center]));

सापेक्ष छवि।

यहां छवि विवरण दर्ज करें

इसके बजाय अगर मैं [self view]निम्नलिखित की तरह सीमा को बदल दूं तो क्या होगा ।

// previous code here...
CGRect rect = [[self view] bounds];
rect.origin.x += 30.0f;
rect.origin.y += 20.0f;
[[self view] setBounds:rect];

सापेक्ष छवि।

यहां छवि विवरण दर्ज करें

यहाँ आप कहते हैं [self view]कि इसका ऊपरी बायां कोना अभी (30.0, 20.0) की स्थिति में है, लेकिन चूँकि view1फ्रेम की उत्पत्ति (30.0, 20.0) से शुरू होती है, वे संयोग करेंगे।

अतिरिक्त संदर्भ (यदि आप चाहें तो अन्य संदर्भों के साथ अद्यतन करने के लिए)

के बारे में clipsToBounds(स्रोत Apple doc)

इस वैल्यू को YES में सेट करने से सबव्यूवर को रिसीवर की सीमा में जाना पड़ता है। अगर NO पर सेट किया जाता है, तो ऐसे सबव्यूअर, जिनके फ्रेम रिसीवर के दृश्यमान सीमा से परे होते हैं, क्लिप नहीं होते हैं। यह डिफ़ॉल्ट मान नहीं है।

दूसरे शब्दों में, यदि कोई दृश्य frameहै (0, 0, 100, 100)और उसका सबव्यू है (90, 90, 30, 30), तो आप उस सबव्यू का केवल एक हिस्सा देखेंगे। उत्तरार्द्ध मूल दृश्य की सीमा से अधिक नहीं होगा।

masksToBoundsके बराबर है clipsToBounds। ए के बजाय UIView, यह संपत्ति ए पर लागू होती है CALayer। हुड के तहत, clipsToBoundsकॉल masksToBounds। आगे के संदर्भों के लिए एक नज़र डालें कि UIView के क्लिपटॉब और कैलेयर के मास्कटॉब के बीच कैसे संबंध है?


@ रूबरू आप बिलकुल सही हैं। मैं इसे अपने उत्तर में इंगित करूंगा। धन्यवाद।
लोरेंजो B

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

@nimgrg ऐसा लगता है कि दृश्य नकारात्मक दिशा में चलता है लेकिन ऐसा नहीं है। पर्यवेक्षक के आंतरिक निर्देशांक बदले जाते हैं।
लोरेंजो बी

मेरी ज्यामितीय क्षमताओं को माफ़ करें, अगर पर्यवेक्षक के आंतरिक निर्देशांक मूल (30.0, 20.0) में बदल जाते हैं, तो बिंदु (0,0) नीले वर्ग के अंदर या उसके बाहर स्थित होता है। मैं केवल परिवर्तनों को ट्रैक करने और इसके बारे में समझ बनाने की कोशिश कर रहा हूं। जवाब देने के लिए समय निकालने के लिए धन्यवाद।
निकरग

@flexaddicted: हाय, आपके द्वारा जोड़ी गई स्लाइड कहती है: "अपने समन्वय स्थान में B का मध्य देखें: bounds.size. उपलब्धता / 2 + origin.x" - यह मामला क्यों है? चूंकि शीर्षक अपने स्वयं के समन्वय स्थान में कहता है , मैं कहूंगा कि यह है: bounds.size. उपलब्धता / 2 + bounds.origin.x ?? है ना ??

134

इस सवाल का पहले से ही एक अच्छा जवाब है, लेकिन मैं इसे कुछ और चित्रों के साथ पूरक करना चाहता हूं। मेरा पूरा जवाब यहाँ है।

फ़्रेम को याद रखने में मेरी मदद करने के लिए , मैं एक दीवार पर एक चित्र फ़्रेम के बारे में सोचता हूं । जैसे किसी चित्र को दीवार पर कहीं भी ले जाया जा सकता है, एक दृश्य के फ्रेम की समन्वय प्रणाली का पर्यवेक्षण है। (दीवार = देखरेख, फ्रेम = दृश्य)

सीमा को याद रखने में मेरी मदद करने के लिए , मैं एक बास्केटबॉल कोर्ट की सीमा के बारे में सोचता हूं । बास्केटबॉल कोर्ट के भीतर कहीं है जैसे दृश्य की सीमा की समन्वय प्रणाली केवल दृश्य के भीतर है। (अदालत = दृश्य, बास्केटबॉल / खिलाड़ी = दृश्य के अंदर की सामग्री)

फ्रेम की तरह, view.center भी पर्यवेक्षण के निर्देशांक में है।

फ्रेम बनाम सीमा - उदाहरण 1

पीला आयत दृश्य के फ्रेम का प्रतिनिधित्व करता है। हरे रंग की आयत दृश्य की सीमा का प्रतिनिधित्व करती है। दोनों छवियों में लाल बिंदी उनके समन्वय प्रणालियों के भीतर फ्रेम या सीमा की उत्पत्ति का प्रतिनिधित्व करती है।

Frame
    origin = (0, 0)
    width = 80
    height = 130

Bounds 
    origin = (0, 0)
    width = 80
    height = 130

यहां छवि विवरण दर्ज करें


उदाहरण 2

Frame
    origin = (40, 60)  // That is, x=40 and y=60
    width = 80
    height = 130

Bounds 
    origin = (0, 0)
    width = 80
    height = 130

यहां छवि विवरण दर्ज करें


उदाहरण 3

Frame
    origin = (20, 52)  // These are just rough estimates.
    width = 118
    height = 187

Bounds 
    origin = (0, 0)
    width = 80
    height = 130

यहां छवि विवरण दर्ज करें


उदाहरण 4

यह उदाहरण 2 के समान ही है, इस समय को छोड़कर दृश्य की पूरी सामग्री को दिखाया गया है क्योंकि यह ऐसा लगेगा जैसे कि यह दृश्य की सीमा से जुड़ा नहीं था।

Frame
    origin = (40, 60)
    width = 80
    height = 130

Bounds 
    origin = (0, 0)
    width = 80
    height = 130

यहां छवि विवरण दर्ज करें


उदाहरण 5

Frame
    origin = (40, 60)
    width = 80
    height = 130

Bounds 
    origin = (280, 70)
    width = 80
    height = 130

यहां छवि विवरण दर्ज करें

दोबारा, अधिक विवरण के साथ मेरे उत्तर के लिए यहां देखें।


2
धन्यवाद सुरगछ। यह वास्तव में फ्रेम और बाध्य अंतर की बहुत स्पष्ट तस्वीर है। मैं वास्तव में आपके प्रयास की सराहना करता हूं।
मोहम्मद हैदर

सभी सामान जो मैं एक संक्षिप्त और संक्षिप्त उत्तर में देखना चाहता हूं। धन्यवाद!
मैट चुआंग

बहुत बढ़िया! उदाहरण 3 के लिए: मुझे नहीं मिला। आपने केवल अपने फ्रेम की उत्पत्ति को थोड़ा बढ़ाया, यह आपकी छवि के रोटेशन को कैसे बदलता है?
हनी

@ asma22, उदाहरण 3 में मैं केवल यह दिखाने की कोशिश कर रहा था कि जब आप एक छवि को घुमाते हैं तो फ्रेम बदल जाता है लेकिन सीमा नहीं होती है। देखिए मेरा फुलर जवाब
सुरगाछ

89

मुझे यह चित्र फ्रेम, सीमा आदि को समझने के लिए सबसे अधिक उपयोगी लगा।

यहां छवि विवरण दर्ज करें

कृपया यह भी ध्यान दें कि frame.size != bounds.sizeजब छवि को घुमाया जाए।


14
हजार शब्दों का चित्र।
नरेंद्र कम्मा

3
सबसे अच्छा संभव स्पष्टीकरण
रतिकांत पात्रा

@ एबरन मो: हाय, आपके द्वारा जोड़ी गई स्लाइड कहती है: "बी के मध्य को अपने समन्वय स्थान में देखें: bounds.size. उपलब्धता / 2 + origin.x" - यह मामला क्यों है? चूंकि शीर्षक अपने स्वयं के समन्वय स्थान में कहता है , मैं कहूंगा कि यह है: bounds.size. उपलब्धता / 2 + bounds.origin.x ?? है ना ??

1
इस छवि का स्रोत क्या है? संपर्क?
डेविड

1
@David यह आईट्यून्स पर स्टैनफोर्ड के CS193p कोर्स से है: www.stanford.edu/class/cs193p/cgi-bin/drupal/downloads-2013-fall
preynolds

3

मुझे लगता है कि यदि आप इसे बिंदु से सोचते हैं CALayer, तो सब कुछ अधिक स्पष्ट है।

फ़्रेम वास्तव में दृश्य या परत का एक अलग गुण नहीं है, यह एक आभासी संपत्ति है, जो सीमा, स्थिति ( UIViewकेंद्र) और रूपांतरण से गणना की जाती है ।

तो मूल रूप से कैसे परत / दृश्य लेआउट वास्तव में इन तीन संपत्ति (और लंगर) द्वारा तय किया जाता है, और इन तीन संपत्ति में से किसी भी अन्य संपत्ति को नहीं बदलेगा, जैसे परिवर्तन बदलना सीमा नहीं बदलता है।


2

इस पोस्ट के विस्तृत विवरण के साथ बहुत अच्छे उत्तर हैं। मैं सिर्फ यह बताना चाहूंगा कि फ्रेमवर्क, बाउंड्स, सेंटर, ट्रांसफॉर्म, बाउंड्स के अर्थ के लिए विज़ुअल रिप्रेजेंटेशन के साथ एक और स्पष्टीकरण है WWDC 2011 के वीडियो में, UIKit रेंडरिंग को समझना शुरू @ 4: 22 से 20:10 तक


0

उपर्युक्त उत्तरों को पढ़ने के बाद, यहां मेरी व्याख्याओं को जोड़ा गया।

मान लीजिए कि ऑनलाइन ब्राउजिंग करना, वेब ब्राउजर आपका है frameजो यह तय करता है कि वेबपेज कहां और कितना बड़ा दिखाना है। ब्राउज़र का स्क्रोलर वह है bounds.originजो यह तय करता है कि वेबपेज के किस हिस्से को दिखाया जाएगा। bounds.originसमझना कठिन है। सीखने का सबसे अच्छा तरीका सिंगल व्यू एप्लिकेशन बनाना है, इन मापदंडों को संशोधित करने और यह देखने के लिए कि कैसे साक्षात्कार बदलते हैं।

- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.

UIView *view1 = [[UIView alloc] initWithFrame:CGRectMake(100.0f, 200.0f, 200.0f, 400.0f)];
[view1 setBackgroundColor:[UIColor redColor]];

UIView *view2 = [[UIView alloc] initWithFrame:CGRectInset(view1.bounds, 20.0f, 20.0f)];
[view2 setBackgroundColor:[UIColor yellowColor]];
[view1 addSubview:view2];

[[self view] addSubview:view1];

NSLog(@"Old view1 frame %@, bounds %@, center %@", NSStringFromCGRect(view1.frame), NSStringFromCGRect(view1.bounds), NSStringFromCGPoint(view1.center));
NSLog(@"Old view2 frame %@, bounds %@, center %@", NSStringFromCGRect(view2.frame), NSStringFromCGRect(view2.bounds), NSStringFromCGPoint(view2.center));

// Modify this part.
CGRect bounds = view1.bounds;
bounds.origin.x += 10.0f;
bounds.origin.y += 10.0f;

// incase you need width, height
//bounds.size.height += 20.0f;
//bounds.size.width += 20.0f;

view1.bounds = bounds;

NSLog(@"New view1 frame %@, bounds %@, center %@", NSStringFromCGRect(view1.frame), NSStringFromCGRect(view1.bounds), NSStringFromCGPoint(view1.center));
NSLog(@"New view2 frame %@, bounds %@, center %@", NSStringFromCGRect(view2.frame), NSStringFromCGRect(view2.bounds), NSStringFromCGPoint(view2.center));
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.