سؤال

UIView والفئات الفرعية جميعها خصائص frame و bounds.ما هو الفرق ؟

هل كانت مفيدة؟

المحلول

على حدود من UIView هو المستطيل, ، كما أعرب عن موقع (x,y) حجم (العرض والارتفاع) نسبة إلى نظام الإحداثيات الخاصة بها (0,0).

على frame من UIView هو المستطيل, ، كما أعرب عن موقع (x,y) حجم (العرض والارتفاع) نسبة إلى متطور فمن الواردة في.

تخيل وجهة النظر التي لديها حجم 100x100 (العرض x الارتفاع) المتمركزة في 25,25 (x,y) من متطور.التعليمة البرمجية التالية بطباعة هذا المنظر حدود الإطار:

// This method is in the view controller of the superview
- (void)viewDidLoad {
    [super viewDidLoad];

    NSLog(@"bounds.origin.x: %f", label.bounds.origin.x);
    NSLog(@"bounds.origin.y: %f", label.bounds.origin.y);
    NSLog(@"bounds.size.width: %f", label.bounds.size.width);
    NSLog(@"bounds.size.height: %f", label.bounds.size.height);

    NSLog(@"frame.origin.x: %f", label.frame.origin.x);
    NSLog(@"frame.origin.y: %f", label.frame.origin.y);
    NSLog(@"frame.size.width: %f", label.frame.size.width);
    NSLog(@"frame.size.height: %f", label.frame.size.height);
}

والناتج من هذا القانون هو:

bounds.origin.x: 0
bounds.origin.y: 0
bounds.size.width: 100
bounds.size.height: 100

frame.origin.x: 25
frame.origin.y: 25
frame.size.width: 100
frame.size.height: 100

لذا يمكننا أن نرى أنه في كلتا الحالتين ، وعرض وارتفاع الرأي هو نفسه بغض النظر عما إذا نحن نبحث في حدود أو الإطار.ما هو مختلف هو x,y المواقع من عرض.في قضية الحدود ، x و y إحداثيات في 0,0 هذه الإحداثيات النسبية إلى عرض نفسها.ومع ذلك ، فإن الإطار x و y إحداثيات بالنسبة إلى الموقف من وجهة نظر داخل وجهة نظر الوالدين (الذي قلنا في وقت سابق كان في 25,25).

هناك أيضا عرضا كبيرا التي تغطي UIViews.انظر الشرائح 1-20 الذي لا يفسر الفرق بين إطارات حدود ولكن أيضا تظهر الأمثلة البصرية.

نصائح أخرى

الجواب القصير

frame = عرض موقع الحجم باستخدام الوالد عرض تنسيق نظام

  • المهم:وضع عرض في الأصل

حدود = عرض موقع الحجم باستخدام نظام الإحداثيات الخاصة بها

  • المهم:وضع عرض المحتوى أو subviews داخل نفسه

إجابة مفصلة

مساعدة frame, أعتقد من إطار الصورة على الجدار.إطار الصورة هو مثل الحدود من وجهة نظر.أنا يمكن أن تعلق الصورة في أي مكان على الجدار.في نفس الطريق, لا يمكن وضع عرض في أي مكان داخل أحد الوالدين عرض (تسمى أيضا متطور).وجهة نظر الوالدين مثل الجدار.أصل نظام الإحداثيات في دائرة الرقابة الداخلية هو أعلى اليسار.يمكننا أن نضع وجهة نظرنا في أصل متطور من خلال وضع عرض الإطار x-y إحداثيات (0, 0), وهو مثل معلقة لدينا الصورة في أعلى الزاوية اليسرى من الحائط.لنقل ذلك الحق ، وزيادة x ، تحريكه إلى أسفل زيادة y.

مساعدة حدود, أعتقد من كرة السلة المحكمة حيث في بعض الأحيان كرة السلة يحصل خرج من حدود.أنت تنطيط الكرة في جميع أنحاء لكرة السلة ، ولكن كنت لا تهتم حقا فيها المحكمة نفسها.يمكن أن يكون في الصالة الرياضية أو خارجها في المدرسة الثانوية ، أو أمام منزلك.لا يهم.كنت ترغب فقط للعب كرة السلة.في نفس الطريق, تنسيق نظام المنظر حدود يهتم فقط عن الرأي نفسه.أنه لا يعرف أي شيء عن مكان عرض قائم في نظر الوالدين.حدود' الأصل (النقطة (0 ، 0) بشكل افتراضي) هو أعلى الزاوية اليسرى من رأي.أي subviews أن هذا الرأي قد وضعت في ما يتعلق بهذه النقطة.هو مثل أخذ الكرة على الجبهة اليسرى من المحكمة.

الآن يأتي الارتباك عند محاولة مقارنة إطار وساق.فإنه في الواقع ليس سيئا كما يبدو في البداية ، على الرغم من.دعونا استخدام بعض الصور تساعدنا على فهم.

الإطار vs حدود

في الصورة الأولى على اليسار لدينا وجهة النظر التي تقع في الجزء العلوي الأيسر من وجهة نظر الأم. الأصفر المستطيل يمثل رأي هذا الإطار. على اليمين نرى عرض مرة أخرى ولكن هذه المرة من وجهة نظر الوالدين لا يظهر.ذلك لأن الحدود لا أعرف عن وجهة نظر الوالدين. المستطيل الأخضر يمثل الرأي الحدود. على النقطة الحمراء في كل من الصور تمثل الأصل من إطار أو حدود.

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

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

enter image description here

لذا إطار وساق بالضبط نفس في الصورة.دعونا ننظر على سبيل المثال حيث أنها مختلفة.

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

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

enter image description here

لذلك يمكنك أن ترى أن تغيير x-y إحداثيات إطار التحركات في نظر الوالدين.ولكن محتوى عرض نفسها لا تزال تبدو بالضبط نفس الشيء.حدود ليس لديهم فكرة أن أي شيء مختلف.

حتى الآن العرض والارتفاع من كل إطار و حدود يكون بالضبط نفس الشيء.هذا ليس دائما صحيح.انظر ماذا يحدث إذا نحن تدوير العرض 20 درجة في اتجاه عقارب الساعة.(دوران يتم استخدام التحويلات.راجع الوثائق و هذه عرض و طبقة أمثلة للحصول على مزيد من المعلومات.)

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

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

enter image description here

يمكنك أن ترى أن الحدود لا تزال هي نفسها.فإنها لا تزال لا تعرف أي شيء حدث!الإطار القيم تغيرت كل ، على الرغم من.

الآن انها أسهل قليلا لنرى الفرق بين إطار وساق ، أليس كذلك ؟ المادة ربما كنت لا أفهم إطارات حدود يحدد عرض الإطار

...أصغر المربع المحيط من هذا الرأي فيما يتعلق والدي تنسيق النظام ، بما في ذلك أي التحولات تطبيق هذا الرأي.

من المهم أن نلاحظ أنه إذا كان يمكنك تحويل الرأي ، ثم يصبح إطار محدد.وفي الواقع ، فإن الإطار الأصفر التي وجهت حول استدارة الأخضر حدود في الصورة أعلاه أبدا موجود في الواقع.وهذا يعني إذا كنت تدوير واسع أو القيام ببعض التحول أخرى ثم يجب عدم استخدام إطار القيم أي أكثر من ذلك.لا يزال يمكنك استخدام حدود القيم ، على الرغم من.أبل الأطباء يحذرون:

المهم: إذا كان المنظر transform العقار لا يحتوي على هوية تحويل إطار هذا الرأي هو غير معروف و حتى هي نتائج autoresizing السلوكيات.

مؤسف عن autoresizing....هناك شيء يمكنك القيام به ، على الرغم من.

أبل مستندات الدولة:

عند تعديل transform الممتلكات الخاصة بك ، التحولات يتم تنفيذ نسبة إلى نقطة وسط عرض.

حتى إذا كنت لا تحتاج إلى تحريك الرأي حول الأم بعد التحول قد تم ذلك, يمكنك القيام بذلك عن طريق تغيير view.center الإحداثيات.مثل frame, center يستخدم نظام الإحداثيات من وجهة نظر الوالدين.

حسنا, دعونا نتخلص من دوران والتركيز على الحدود.حتى الآن حدود الأصل وقد بقيت دائما في (0, 0).فإنه لا يجب أن, على الرغم من.ماذا لو رأينا كبير subview كبير جدا لعرض كل مرة ؟ ونحن سوف تجعل من UIImageView مع صورة كبيرة.هنا هو لدينا الثاني صورة من فوق مرة أخرى, ولكن هذه المرة يمكننا أن نرى ما المحتوى كله من وجهة نظرنا هو subview ستبدو.

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

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

enter image description here

فقط أعلى الزاوية اليسرى من الصورة يمكن أن تناسب داخل المنظر حدود.الآن انظر ماذا يحدث إذا قمنا بتغيير حدود' أصل الإحداثيات.

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

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

enter image description here

الإطار لم تتحرك في متطور ولكن المحتوى داخل الإطار قد تغير لأن أصل حدود المستطيل يبدأ في جزء مختلف من الرأي.هذه هي الفكرة وراء UIScrollView وانها فرعية (على سبيل المثال ، UITableView).انظر فهم UIScrollView لمزيد من التوضيح.

عند استخدام الإطار عند استخدام حدود

منذ frame ويتعلق عرض موقع في الأصل عرض استخدامها عندما كنت صنع الخارج التغييرات, مثل تغيير العرض أو إيجاد المسافة بين عرض الجزء العلوي من وجهة نظر الأم.

استخدام bounds عندما كنت صنع الداخل التغييرات, مثل رسم الأشياء أو ترتيب subviews في الرأي.أيضا استخدام حدود على حجم عرض إذا كنت قد فعلت بعض transfomation على ذلك.

مقالات عن المزيد من البحوث:

أبل مستندات

ذات الصلة ستاكوفيرفلوو الأسئلة

الموارد الأخرى

الممارسة نفسك

بالإضافة إلى قراءة المواد المذكورة أعلاه ، فإنه يساعد لي الكثير لإجراء اختبار التطبيق.قد ترغب في محاولة للقيام بشيء مماثل.(لدي فكرة من هذا الفيديو الحال ولكن لسوء الحظ أنها ليست مجانية.)

enter image description here

هنا هو رمز للمرجع الخاص بك:

import UIKit

class ViewController: UIViewController {


    @IBOutlet weak var myView: UIView!

    // Labels
    @IBOutlet weak var frameX: UILabel!
    @IBOutlet weak var frameY: UILabel!
    @IBOutlet weak var frameWidth: UILabel!
    @IBOutlet weak var frameHeight: UILabel!
    @IBOutlet weak var boundsX: UILabel!
    @IBOutlet weak var boundsY: UILabel!
    @IBOutlet weak var boundsWidth: UILabel!
    @IBOutlet weak var boundsHeight: UILabel!
    @IBOutlet weak var centerX: UILabel!
    @IBOutlet weak var centerY: UILabel!
    @IBOutlet weak var rotation: UILabel!

    // Sliders
    @IBOutlet weak var frameXSlider: UISlider!
    @IBOutlet weak var frameYSlider: UISlider!
    @IBOutlet weak var frameWidthSlider: UISlider!
    @IBOutlet weak var frameHeightSlider: UISlider!
    @IBOutlet weak var boundsXSlider: UISlider!
    @IBOutlet weak var boundsYSlider: UISlider!
    @IBOutlet weak var boundsWidthSlider: UISlider!
    @IBOutlet weak var boundsHeightSlider: UISlider!
    @IBOutlet weak var centerXSlider: UISlider!
    @IBOutlet weak var centerYSlider: UISlider!
    @IBOutlet weak var rotationSlider: UISlider!

    // Slider actions
    @IBAction func frameXSliderChanged(sender: AnyObject) {
        myView.frame.origin.x = CGFloat(frameXSlider.value)
        updateLabels()
    }
    @IBAction func frameYSliderChanged(sender: AnyObject) {
        myView.frame.origin.y = CGFloat(frameYSlider.value)
        updateLabels()
    }
    @IBAction func frameWidthSliderChanged(sender: AnyObject) {
        myView.frame.size.width = CGFloat(frameWidthSlider.value)
        updateLabels()
    }
    @IBAction func frameHeightSliderChanged(sender: AnyObject) {
        myView.frame.size.height = CGFloat(frameHeightSlider.value)
        updateLabels()
    }
    @IBAction func boundsXSliderChanged(sender: AnyObject) {
        myView.bounds.origin.x = CGFloat(boundsXSlider.value)
        updateLabels()
    }
    @IBAction func boundsYSliderChanged(sender: AnyObject) {
        myView.bounds.origin.y = CGFloat(boundsYSlider.value)
        updateLabels()
    }
    @IBAction func boundsWidthSliderChanged(sender: AnyObject) {
        myView.bounds.size.width = CGFloat(boundsWidthSlider.value)
        updateLabels()
    }
    @IBAction func boundsHeightSliderChanged(sender: AnyObject) {
        myView.bounds.size.height = CGFloat(boundsHeightSlider.value)
        updateLabels()
    }
    @IBAction func centerXSliderChanged(sender: AnyObject) {
        myView.center.x = CGFloat(centerXSlider.value)
        updateLabels()
    }
    @IBAction func centerYSliderChanged(sender: AnyObject) {
        myView.center.y = CGFloat(centerYSlider.value)
        updateLabels()
    }
    @IBAction func rotationSliderChanged(sender: AnyObject) {
        let rotation = CGAffineTransform(rotationAngle: CGFloat(rotationSlider.value))
        myView.transform = rotation
        updateLabels()
    }

    private func updateLabels() {

        frameX.text = "frame x = \(Int(myView.frame.origin.x))"
        frameY.text = "frame y = \(Int(myView.frame.origin.y))"
        frameWidth.text = "frame width = \(Int(myView.frame.width))"
        frameHeight.text = "frame height = \(Int(myView.frame.height))"
        boundsX.text = "bounds x = \(Int(myView.bounds.origin.x))"
        boundsY.text = "bounds y = \(Int(myView.bounds.origin.y))"
        boundsWidth.text = "bounds width = \(Int(myView.bounds.width))"
        boundsHeight.text = "bounds height = \(Int(myView.bounds.height))"
        centerX.text = "center x = \(Int(myView.center.x))"
        centerY.text = "center y = \(Int(myView.center.y))"
        rotation.text = "rotation = \((rotationSlider.value))"

    }

}

ومحاولة تشغيل التعليمات البرمجية أدناه

- (void)viewDidLoad {
    [super viewDidLoad];
    UIWindow *w = [[UIApplication sharedApplication] keyWindow];
    UIView *v = [w.subviews objectAtIndex:0];

    NSLog(@"%@", NSStringFromCGRect(v.frame));
    NSLog(@"%@", NSStringFromCGRect(v.bounds));
}

والناتج من هذا الرمز:

واتجاه الجهاز الحالة هو صورة

{{0, 0}, {768, 1024}}
{{0, 0}, {768, 1024}}

واتجاه الجهاز حالة والمناظر الطبيعية

{{0, 0}, {768, 1024}}
{{0, 0}, {1024, 768}}

واضح، يمكنك أن ترى الفرق بين الإطار والحدود

على frame هو المستطيل الذي يحدد UIView مع يتعلق متطور.

على حدود المستطيل هو مجموعة من القيم التي تحدد ذلك NSView تنسيق النظام.

أيأي شيء في هذا المستطيل فعلا عرض في UIView.

frame هو الأصل (أعلى الزاوية اليسرى) و حجم عرض في عرض سوبر تنسيق نظام ، وهذا يعني أن تترجم في عرض سوبر طريق تغيير الإطار الأصل ، حدود من ناحية أخرى هو حجم الأصل في نظام الإحداثيات الخاصة بها ، وذلك بشكل افتراضي حدود الأصل (0,0).

معظم الوقت في إطار حدود متطابقة , ولكن إذا كان لديك عرض الإطار ((140,65),(200,250)) وساق ((0,0),(200,250))على سبيل المثال ، كان الرأي يميل بحيث أنها تقف على أسفل الزاوية اليمنى ، ثم حدود ستظل ((0,0),(200,250)) , لكن الإطار لا .

enter image description here

الإطار سوف تكون أصغر مستطيل التي تلخص/يحيط الرأي ، وذلك في إطار (كما في الصورة) سوف يكون ((140,65),(320,320)).

وثمة فرق آخر هو على سبيل المثال إذا كان لديك متطور الذين حدود هو ((0,0),(200,200)) وهذا متطور لديه subView الذين الإطار هو ((20,20),(100,100)) و قمت بتغيير متطور حدود ((20,20),(200,200)) , ثم العرض الفرعي الإطار سوف يكون لا يزال ((20,20),(100,100)) ولكن offseted من قبل (20,20) لأن متطور تنسيق نظام offseted من قبل (20,20).

آمل أن يساعد هذا شخص ما.

والإطار بالنسبة لSuperView في حين باوندز نسبة إلى NSView لها.

وعلى سبيل المثال: X = 40، Y = 60.Also يحتوي على 3 Views.This مخطط يظهر لك فكرة واضحة

الإجابات أعلاه أن أوضح الفرق بين الحدود و الإطارات.

الحدود :عرض حجم وموقع حسب نظام الإحداثيات الخاصة بها.

الإطار :عرض حجم وموقع بالنسبة متطور.

ثم هناك التباس في قضية الحدود X,Y سوف يكون دائما "0". هذا ليس صحيحا.هذا يمكن أن يكون مفهوما في UIScrollView و UICollectionView كذلك.

عند حدود' x, y لا 0.
دعونا نفترض أن لدينا UIScrollView.قمنا بتنفيذ ترقيم الصفحات.على UIScrollView 3 صفحات و ContentSize عرض ثلاثة أضعاف عرض الشاشة (نفترض ScreenWidth 320).إن الارتفاع المستمر (نفترض 200).

scrollView.contentSize = CGSize(x:320*3, y : 200)

إضافة ثلاثة UIImageViews كما subViews والحفاظ على نظرة فاحصة على x قيمة الإطار

let imageView0 = UIImageView.init(frame: CGRect(x:0, y: 0 , width : scrollView.frame.size.width, height : scrollView.frame.size.height))
let imageView1 :  UIImageView.init( frame: CGRect(x:320, y: 0 , width : scrollView.frame.size.width, height : scrollView.frame.size.height))
let imageView2 :  UIImageView.init(frame: CGRect(x:640, y: 0 , width : scrollView.frame.size.width, height : scrollView.frame.size.height))
scrollView.addSubview(imageView0)
scrollView.addSubview(imageView0)
scrollView.addSubview(imageView0)
  1. الصفحة 0:عندما ScrollView في 0 صفحة حدود سوف يكون (x:0,y:0, العرض :320, height :200)

  2. الصفحة 1:انتقل والانتقال إلى الصفحة 1.
    الآن حدود سوف يكون (س:320,y:0, العرض :320, height :200) تذكر أننا قلنا فيما يخص نظام الإحداثيات الخاصة بها.حتى الآن "الجزء المرئي" من ScrollView لها "x" في 320.نظرة في إطار imageView1.

  3. الصفحة 2:انتقل والانتقال إلى الصفحة 2 الحدود :(س:640,y:0, العرض :320, height :200) مرة أخرى نلقي نظرة على الإطار imageView2

نفس حالة UICollectionView.أسهل طريقة للبحث في collectionView هو التمرير و طباعة/سجل حدوده و سوف تحصل على فكرة.

كل الإجابات أعلاه غير صحيحة و هذا هو بلدي يأخذ على هذا:

التفريق بين إطار حدود المفاهيم المطور كالتالي:

  1. نسبة إلى متطور (أحد الوالدين رأي) هو الوارد في غضون = الإطار
  2. بالنسبة إلى نظام الإحداثيات الخاصة بها ، يحدد subview الموقع = حدود

"حدود" مربك لأنه يعطي الانطباع أن إحداثيات موقف الرأي التي يتم تعيينها.ولكن هذه هي في العلاقات تعديلها وفقا إطار الثوابت.

iPhone screen

إطار = موقع وجهة نظر وحجم باستخدام نظام الإحداثيات وجهة نظر الوالدين

وساق = موقع وجهة نظر وحجم باستخدام تنسيق نظامها الخاص

وجهة نظر المسارات حجمها وموقعها باستخدام اثنين من المستطيلات: مستطيل الإطار ومستطيل ساق. يحدد المستطيل إطار موقع وجهة وحجم في superview باستخدام تنسيق نظام superview ل. يحدد المستطيل الحدود الداخلية النظام الذي يستخدم عند رسم محتويات العرض، بما في ذلك المنشأ والتحجيم تنسيق. ويبين الشكل 2-1 العلاقة بين مستطيل الإطار، على اليسار، والمستطيل حدود، على حق ".

وباختصار، فإن الإطار هو فكرة superview من وجهة نظر، وساق هو فكرة وجهة النظر الخاصة. وجود عدة أنظمة، واحد لكل عرض وتنسيق جزء من التسلسل الهرمي الرأي.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top