ios - هل NSLayoutConstraints متحركة؟




animation autolayout (5)

هذا السؤال لديه بالفعل إجابة هنا:

أحاول تحريك بعض وجهات النظر بحيث يتم حظرها بواسطة لوحة المفاتيح العملاقة في المشهد. إنه يعمل بشكل جيد إذا قمت ببساطة بتحريك الإطارات ، لكن الآخرين قد اقترحوا أن هذا الأمر سيؤدي إلى نتائج عكسية ويجب أن أقوم بتحديث NSLayoutConstraints بدلاً من ذلك. ومع ذلك ، لا يبدو أنها قابلة للرسوم المتحركة. هل حصل أحدهم على العمل بنجاح؟

//heightFromTop is an NSLayoutConstraint referenced from IB
[UIView animateWithDuration:0.25 animations:^{
    self.heightFromTop.constant= 550.f;
}];

والنتيجة هي قفزة فورية إلى الارتفاع المعني.


Answers

كنت أواجه مشكلة مماثلة وكان هذا الخيط مساعدة كبيرة لتجاوزها.

وضعني الجواب من erurainon على الطريق الصحيح ، لكنني أود أن أقترح إجابة مختلفة قليلاً. لم ينجح الأمر في استخدام الرمز المقترح من erurainon ، حيث كان لازال أمامي قفزة بدلاً من الانتقال المتحرك. أعطاني الرابط المقدم من cnotethegr8 إجابة العمل:

دليل تخطيط السيارات https://developer.apple.com/library/ios/documentation/UserExperience/Conceptual/AutolayoutPG/AutoLayoutbyExample/AutoLayoutbyExample.html (كل الطريق إلى أسفل الصفحة).

بعض الاختلافات من إجابة erurainon:

  1. استدعاء callIfNeeded على عرض حاوية قبل استدعاء أسلوب حركة (بدلاً من setNeedsUpdateConstraints على myView).
  2. اضبط القيد الجديد في كتلة الرسوم المتحركة.
  3. استدعاء callIfNeeded على عرض الحاوية في طريقة الرسوم المتحركة (بعد تعيين القيد) ، بدلا من على myView.

سيتقيد هذا بالنمط المقترح من Apple في الرابط أعلاه.

مثال

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

// Code snippets

@property (weak, nonatomic) IBOutlet UIView *topView; // Container for minimalView
@property (weak, nonatomic) IBOutlet UIView *minimalView; // View to animate

@property (nonatomic) CGFloat minimalViewFullHeight; // Original height of minimalView

@property (weak, nonatomic) IBOutlet NSLayoutConstraint *minimalViewHeightConstraint;

@property (nonatomic) BOOL executedViewDidLayoutSubviews;


- (void)viewDidLayoutSubviews
{
    [super viewDidLayoutSubviews];


    // First execution of viewDidLayoutSubviews?
    if(!self.executedViewDidLayoutSubviews){
        self.executedViewDidLayoutSubviews = YES;


        // Record some original dimensions
        self.minimalViewFullHeight = self.minimalView.bounds.size.height;


        // Setup our initial view configuration & let system know that 
        // constraints need to be updated.
        self.minimalViewHeightConstraint.constant = 0.0;
        [self.minimalView setNeedsUpdateConstraints];

        [self.topView layoutIfNeeded];
    }
}

تغيير حجم مقتطف الإجراء الكامل

// An action to close our minimal view and show our normal (full) view
- (IBAction)resizeFullAction:(UIButton *)sender {

    [self.topView layoutIfNeeded];

    [UIView transitionWithView:self.minimalView
                  duration:1.0
                   options:UIViewAnimationOptionTransitionCrossDissolve
                animations:^{
                    self.minimalViewHeightConstraint.constant = 0.0;

                    // Following call to setNeedsUpdateConstraints may not be necessary
                    [self.minimalView setNeedsUpdateConstraints];

                    [self.topView layoutIfNeeded];

                } completion:^(BOOL finished) {
                    ;
                }];

    // Other code to show full view
    // ...
}

تغيير حجم مقتطف الإجراء الصغير

// An action to open our minimal view and hide our normal (full) view
- (IBAction)resizeSmallAction:(UIButton *)sender {

    [self.topView layoutIfNeeded];

    [UIView transitionWithView:self.minimalView
                  duration:1.0
                   options:UIViewAnimationOptionTransitionCrossDissolve
                animations:^{
                    self.minimalViewHeightConstraint.constant = self.minimalViewFullHeight;
                    [self.minimalView setNeedsUpdateConstraints];

                    [self.topView layoutIfNeeded];

                } completion:^(BOOL finished) {
                    ;
                }];

        // Other code to hide full view
        // ...
    }

يمكنك استخدام animateWithDuration بدلاً من transitionWithView إذا كنت ترغب في ذلك.

أتمنى أن يساعدك هذا.


لقد جربت أسلوب Centurion @ ، لكن بطريقة ما ، كان رأيي متحركًا في إطار خاطئ إذا تم تحميله من لوحة العمل. تختفي المشكلة إذا قمت باستبدال layoutIfNeeded updateConstraintsIfNeeded كنت layoutIfNeeded إلى updateConstraintsIfNeeded ، على الرغم من عدم وجود أي فكرة عن السبب. إذا كان أي شخص يمكن أن يعطي تفسيرا أنه سيكون موضع تقدير كبير.

[self.view updateConstraintsIfNeeded];
[UIView animateWithDuration:1.0 animations:^{
    self.myConstraint.constant= 100;
    [self.view layoutIfNeeded];
}];

فقط اتبع هذا النموذج بالضبط:

self.heightFromTop.constant = 550.0f;
[myView setNeedsUpdateConstraints];

[UIView animateWithDuration:0.25f animations:^{
   [myView layoutIfNeeded];
}];

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

في سويفت 2:

self.heightFromTop.constant = 550
myView.setNeedsUpdateConstraints()

UIView.animateWithDuration(0.25, animations: {
   myView.layoutIfNeeded()
})

طريقة Apple المقترحة هي مختلفة قليلاً ( انظر المثال في قسم "تنشيط التغييرات المتحركة بواسطة التصميم التلقائي" ). تحتاج أولاً إلى استدعاء layoutIfNeeded قبل الرسوم المتحركة. ثم أضف أشياء الرسوم المتحركة الخاصة بك داخل كتلة الرسوم المتحركة ثم اتصل على layoutإلنفيد في النهاية مرة أخرى. بالنسبة إلى الأشخاص من أمثالي الذين ينتقلون إلى autolayout ، فإن أسلوبه الأكثر تشابهًا مع الرسوم المتحركة السابقة التي كنا نفعلها مع الإطارات داخل كتل الرسوم المتحركة. نحتاج فقط إلى الاتصال layoutIfNeeded مرتين - قبل الرسوم المتحركة وبعد الرسوم المتحركة:

[self.view layoutIfNeeded]; // Ensures that all pending layout operations have been completed

[UIView animateWithDuration:1.0f animations:^{

  // Make all constraint changes here
  self.heightFromTop.constant= 550.f;

  [self.view layoutIfNeeded]; // Forces the layout of the subtree animation block and then captures all of the frame changes

}];

لا يمكنك إنشاء صفحات ويب بدون HTML. في الوقت الحاضر ، javascript هو نصوص الويب ، ولتحقيق معظم الأشياء ديناميكيًا ، تحتاج إلى استخدامه على الرغم من العديد من الأشياء التي يمكن لـ CSS3 القيام بها.







ios animation autolayout