আমি কীভাবে সীমাবদ্ধতা পরিবর্তনগুলি প্রাণবন্ত করব?


959

আমি একটি পুরানো অ্যাপ্লিকেশন আপডেট করছি AdBannerViewএবং যখন কোনও বিজ্ঞাপন নেই, তখন এটি স্ক্রিন থেকে স্লাইড হয়ে যায়। যখন কোনও বিজ্ঞাপন থাকে তখন এটি স্ক্রিনে স্লাইড হয়। মৌলিক উপাদান.

পুরানো স্টাইল, আমি ফ্রেমটি অ্যানিমেশন ব্লকে সেট করেছি। নতুন শৈলীতে, আমার কাছে IBOutletস্বয়ং-বিন্যাসের সীমাবদ্ধতা রয়েছে যা Yঅবস্থানটি নির্ধারণ করে , এক্ষেত্রে এটি সুপারভিউয়ের নীচ থেকে দূরত্ব এবং ধ্রুবকটি সংশোধন করুন:

- (void)moveBannerOffScreen {
    [UIView animateWithDuration:5 animations:^{
        _addBannerDistanceFromBottomConstraint.constant = -32;
    }];
    bannerIsVisible = FALSE;
}

- (void)moveBannerOnScreen {
    [UIView animateWithDuration:5 animations:^{
        _addBannerDistanceFromBottomConstraint.constant = 0;
    }];
    bannerIsVisible = TRUE;
}

ব্যানারটি যেমন প্রত্যাশিত ঠিক তেমন সরানো হয়েছে তবে কোনও অ্যানিমেশন নেই।


আপডেট: আমি ডাব্লুডাব্লুডিসি 12 টি অ্যানিমেশন কভার করার মাস্টারিং অটো লেআউটের সেরা অভ্যাসগুলি পুনরায় দেখেছি । এটি কোরএ্যানিমেশন ব্যবহার করে সীমাবদ্ধতাগুলি কীভাবে আপডেট করবেন তা আলোচনা করে :

আমি নিম্নলিখিত কোড দিয়ে চেষ্টা করেছি, কিন্তু ঠিক একই ফলাফল পেতে:

- (void)moveBannerOffScreen {
    _addBannerDistanceFromBottomConstraint.constant = -32;
    [UIView animateWithDuration:2 animations:^{
        [self.view setNeedsLayout];
    }];
    bannerIsVisible = FALSE;
}

- (void)moveBannerOnScreen {
    _addBannerDistanceFromBottomConstraint.constant = 0;
    [UIView animateWithDuration:2 animations:^{
        [self.view setNeedsLayout];
    }];
    bannerIsVisible = TRUE;
}

পার্শ্ব নোটে, আমি বহুবার যাচাই করেছি এবং এটি মূল থ্রেডে কার্যকর করা হচ্ছে ।


11
আগে কখনও এসও-তে
টাইপকে

3
উত্তরে টাইপো থাকলে আপনার উত্তরটি সম্পাদনা করা উচিত। এ কারণেই এগুলি সম্পাদনযোগ্য।
i_am_jorf

@ জেফামফোন - আপনি টাইপটি নির্দেশ করেছেন তবে এটি আরও কার্যকর হবে যাতে আমি জানি কোথায় ভুল ছিল। আপনি নিজেই উত্তরটি সম্পাদনা করতে পারেন এবং আমাদের ডায়রিটিবকে বাঁচিয়ে টাইপো স্থির করতে পারেন। অ্যানিমেশন ব্লক থেকে ধ্রুবকটি সরাতে আমি এটি সম্পাদনা করেছি, যদি আপনি এটি উল্লেখ করছেন।
ডিবিডি

1
টাইপো কী তা আমি জানি না। আমি উপরের মন্তব্যে সাড়া দিচ্ছিলাম।
i_am_jorf

9
তারপরে টাইপো হ'ল প্রশ্ন। মূর্খতার সাথে আমি "লেআউটআইফনিয়েড" এর পরিবর্তে "সেটনিডস লেআউট" টাইপ করছিলাম। আমি আমার কোডটি ত্রুটি এবং স্ক্রিনশটগুলি সঠিক কমান্ড দিয়ে কাটা এবং পেস্ট করার সময় এটি আমার প্রশ্নের মধ্যে পরিষ্কারভাবে প্রদর্শিত হয়। তবুও কেউ এটি উল্লেখ না করা পর্যন্ত এটি লক্ষ্য করা যায়নি।
ডিবিডি

উত্তর:


1696

দুটি গুরুত্বপূর্ণ নোট:

  1. আপনাকে layoutIfNeededঅ্যানিমেশন ব্লকের মধ্যে কল করতে হবে । সমস্ত মুলতুবি লেআউট ক্রিয়াকলাপ সম্পন্ন হয়েছে তা নিশ্চিত করতে অ্যাপল আসলে অ্যানিমেশন ব্লকের আগে একবার কল করার পরামর্শ দেয়

  2. আপনার এটিকে বিশেষভাবে পিতামাতার ভিউতে কল করতে হবে (উদাঃ self.view), সন্তানের দৃশ্যে নয় যা এর সাথে সীমাবদ্ধ রয়েছে। এটি করার ফলে সমস্ত সীমাবদ্ধ দৃষ্টিভঙ্গি আপডেট হবে , এমন অন্যান্য ভিউ যা আপনার সীমাবদ্ধতা পরিবর্তিত হয়েছে এমন দৃশ্যের সাথে সীমাবদ্ধ হতে পারে (যেমন দেখুন ভি দেখুন ভি এর নীচের সাথে সংযুক্ত এবং আপনি কেবল ভি এ এর ​​শীর্ষ অফসেট পরিবর্তন করেছেন এবং আপনি ভি বি দেখতে চান এটি দিয়ে প্রাণবন্ত করতে)

এটা চেষ্টা কর:

উদ্দেশ্য গ

- (void)moveBannerOffScreen {
    [self.view layoutIfNeeded];

    [UIView animateWithDuration:5
        animations:^{
            self._addBannerDistanceFromBottomConstraint.constant = -32;
            [self.view layoutIfNeeded]; // Called on parent view
        }];
    bannerIsVisible = FALSE;
}

- (void)moveBannerOnScreen { 
    [self.view layoutIfNeeded];

    [UIView animateWithDuration:5
        animations:^{
            self._addBannerDistanceFromBottomConstraint.constant = 0;
            [self.view layoutIfNeeded]; // Called on parent view
        }];
    bannerIsVisible = TRUE;
}

সুইফট 3

UIView.animate(withDuration: 5) {
    self._addBannerDistanceFromBottomConstraint.constant = 0
    self.view.layoutIfNeeded()
}

199
আপনি জানেন কি ... আপনার উত্তর কাজ করে। ডাব্লুডাব্লুডিসি কাজ করে .... আমার দৃষ্টি ব্যর্থ। কিছু কারণে আমি setNeedsLayoutপরিবর্তে ফোন করছি বুঝতে বুঝতে আমার এক সপ্তাহ লেগেছে layoutIfNeeded। আমি কেবলমাত্র ভুল পদ্ধতির নামটি টাইপ করেছি তা না দেখে আমি কত ঘন্টা ব্যয় করেছি তা থেকে আমি কিছুটা আতঙ্কিত হয়েছি।
ডিবিডি

23
সমাধানটি কাজ করে তবে অ্যানিমেশন ব্লকের মধ্যে আপনার সীমাবদ্ধতার ধ্রুবক পরিবর্তন করার দরকার নেই । অ্যানিমেশনটি লাথি মারার আগে একবার প্রতিবন্ধকতা নির্ধারণ করা পুরোপুরি ঠিক। আপনার উত্তরটি সম্পাদনা করা উচিত।
অর্টউইন জেন্টজ

74
এটি প্রাথমিকভাবে আমার পক্ষে কাজ করে নি এবং তখন আমি বুঝতে পেরেছিলাম যে আপনাকে প্যারেন্ট ভিউতে লেআউটটি কল করতে হবে, এই সীমাবদ্ধতাগুলি দেখার জন্য নয়।
অলিভার পিয়ারমাইন

20
লেআউটআইফেনিড ব্যবহার করে সমস্ত সাবভিউ রিফ্রেশ করে কেবল সীমাবদ্ধ পরিবর্তন নয়। আপনি কীভাবে কেবল সীমাবদ্ধতা পরিবর্তন পরিবর্তন করতে পারেন?
এনজিবি

11
"অ্যাপল আসলে সমস্ত মুলতুবি লেআউট ক্রিয়াকলাপ সম্পন্ন হয়েছে তা নিশ্চিত করার জন্য আপনাকে অ্যানিমেশন ব্লকের আগে একবার ফোন করার পরামর্শ দেয়", আপনাকে ধন্যবাদ, কখনই সে সম্পর্কে ভাবেনি, তবে এটি উপলব্ধি করে।
রিক ভ্যান ডের লিন্ডে

109

আমি প্রদত্ত উত্তরটির প্রশংসা করি, তবে আমি মনে করি এটি আরও কিছুটা এগিয়ে নিয়ে ভাল লাগবে।

ডকুমেন্টেশন থেকে বেসিক ব্লক অ্যানিমেশন

[containerView layoutIfNeeded]; // Ensures that all pending layout operations have been completed
[UIView animateWithDuration:1.0 animations:^{
     // Make all constraint changes here
     [containerView layoutIfNeeded]; // Forces the layout of the subtree animation block and then captures all of the frame changes
}];

তবে সত্যিই এটি খুব সরল পরিস্থিতি। আমি যদি updateConstraintsপদ্ধতির মাধ্যমে সাবভিউ সীমাবদ্ধতাগুলি অ্যানিমেট করতে চাই তবে কী হবে ?

একটি অ্যানিমেশন ব্লক যা সাবভিউগুলিকে আপডেটকন্ট্রেন্টস পদ্ধতিতে কল করে

[self.view layoutIfNeeded];
[self.subView setNeedsUpdateConstraints];
[self.subView updateConstraintsIfNeeded];
[UIView animateWithDuration:1.0f delay:0.0f options:UIViewAnimationOptionLayoutSubviews animations:^{
    [self.view layoutIfNeeded];
} completion:nil];

আপডেটউন্সট্রেটস পদ্ধতিটি ইউআইভিউ সাবক্লাসে ওভাররাইড করা হয় এবং পদ্ধতির শেষে অবশ্যই সুপারকে কল করা উচিত।

- (void)updateConstraints
{
    // Update some constraints

    [super updateConstraints];
}

অটোলআউট গাইডটি পছন্দসই হওয়ার জন্য অনেকগুলি ছেড়ে যায় তবে এটি পড়ার মতো। আমি নিজে এটিকে এমন একটি অংশ হিসাবে ব্যবহার করছি যা একটি সাধারণ এবং সূক্ষ্ম ধসের অ্যানিমেশন (0.2 সেকেন্ড দীর্ঘ) UISwitchসহ একটি জুড়ির সাথে একটি সাবউভি টগল করে UITextField। সাবউভিউয়ের সীমাবদ্ধতাগুলি ইউআইভিউ সাবক্লাস আপডেটকন্ট্রেন্টস পদ্ধতিগুলিতে উপরে বর্ণিত হিসাবে পরিচালনা করা হচ্ছে।


যখন সমস্ত পদ্ধতিগুলি উপরের কলিং self.view(এবং যে একটি দেখুন subview না), কলিং updateConstraintsIfNeededপ্রয়োজন নেই (কারণ setNeedsLayoutট্রিগারগুলির updateConstraintsযে দৃশ্য)। বেশিরভাগের জন্য তুচ্ছ হতে পারে তবে এখন পর্যন্ত এটি আমার পক্ষে ছিল না;)
অ্যানাবলু

আপনার নির্দিষ্ট ক্ষেত্রে অটোলেআউট এবং স্প্রিংস এবং স্ট্রুটস লেআউটের পুরো ইন্টারপ্লে না জেনে মন্তব্য করা শক্ত। আমি পুরোপুরি খাঁটি অটোলেআউট দৃশ্যের কথা বলছি। আপনার লেআউটসভিউজ পদ্ধতিতে ঠিক কী ঘটছে তা জানতে আগ্রহী হব।
ক্যামেরন লোয়েল পামার

অনুবাদসমূহঅটোরসাইজিংমাস্কআইন্টো কনস্ট্রাইনস = না; আপনি যদি খাঁটি-অটোলেআউট করতে চান তবে আপনার অবশ্যই এটি অক্ষম করা উচিত।
ক্যামেরন লোয়েল পামার

আমি এটি দেখিনি, তবে আমি কিছু কোড ছাড়া ইস্যুতে সত্যই কথা বলতে পারি না। হতে পারে আপনি কোনও টেবিলভিউ উপহাস করে এটি গিটহাবের উপর আটকে রাখতে পারেন?
ক্যামেরন লোয়েল পামার

দুঃখিত, আমি gitHub ব্যবহার করি না :(
anneblue

74

সাধারণত, আপনার সীমাবদ্ধতাগুলি আপডেট করতে হবে এবং layoutIfNeededঅ্যানিমেশন ব্লকের ভিতরে কল করতে হবে । এটি হয় কোনওটির .constantসম্পত্তি পরিবর্তন করা NSLayoutConstraint, সীমাবদ্ধতাগুলি (আইওএস 7) যুক্ত করা বা পরিবর্তন করা যেতে পারে.active সীমাবদ্ধতার সম্পত্তি (আইওএস 8 এবং 9) হতে পারে।

কোডের উদাহরণ:

[UIView animateWithDuration:0.3 animations:^{
    // Move to right
    self.leadingConstraint.active = false;
    self.trailingConstraint.active = true;

    // Move to bottom
    self.topConstraint.active = false;
    self.bottomConstraint.active = true;

    // Make the animation happen
    [self.view setNeedsLayout];
    [self.view layoutIfNeeded];
}];

নমুনা সেটআপ:

এক্সকোড প্রকল্প তাই নমুনা অ্যানিমেশন প্রকল্প।

বিতর্ক

অ্যানিমেশন ব্লকের আগে বা ভিতরে বাধা পরিবর্তন করা উচিত কিনা সে সম্পর্কে কিছু প্রশ্ন রয়েছে (পূর্ববর্তী উত্তরগুলি দেখুন) ।

নীচে আইওএস পড়ায় মার্টিন পিলিংটন এবং অটো লেআউট লিখেছেন কেন ফেরির মধ্যে একটি টুইটার কথোপকথন রয়েছে। কেন ব্যাখ্যা করেছেন যে অ্যানিমেশন ব্লকের বাইরে স্থির পরিবর্তনগুলি বর্তমানে কাজ করতে পারে তবে এটি নিরাপদ নয় এবং তাদের সত্যই অ্যানিমেশন ব্লকের ভিতরে পরিবর্তন হওয়া উচিত । https://twitter.com/kongtomorrow/status/440627401018466305

অ্যানিমেশন:

নমুনা প্রকল্প

এখানে একটি দৃষ্টিকোণ কীভাবে অ্যানিমেটেড করা যায় তা দেখানো একটি সহজ প্রকল্প। এটি অবজেক্টিভ সি ব্যবহার করছে এবং .activeবিভিন্ন সীমাবদ্ধতার সম্পত্তি পরিবর্তন করে ভিউটিকে অ্যানিমেট করে । https://github.com/shepting/SampleAutoLayoutAnimation


নতুন সক্রিয় পতাকা ব্যবহার করে উদাহরণ দেখানোর জন্য +1। এছাড়াও, অ্যানিমেশন ব্লকের বাইরে সীমাবদ্ধতা পরিবর্তন করা আমার কাছে সবসময় হ্যাকের মতো মনে হয়েছিল
কোরি হিন্টন

আমি গিথুবে একটি ইস্যু উত্থাপন করেছি কারণ ভিউটি যেখানে ছিল সেখানে ফিরে যাওয়ার পক্ষে এই সমাধান কাজ করে না। আমি বিশ্বাস করি সক্রিয় পরিবর্তন করা সঠিক সমাধান নয় এবং পরিবর্তে আপনার অগ্রাধিকার পরিবর্তন করা উচিত। শীর্ষে 750 এবং নীচে 250 এ সেট করুন, তারপরে ইউআইআইএলআউটপ্রাইরিটি ডেফল্টহাই এবং ইউআইআইআলআউটপ্রাইরিটি ডিফল্টলোর মধ্যে বিকল্প বিকল্পে কোড করুন।
মলহাল

ব্লকের অভ্যন্তরে আপডেট হওয়ার আর একটি কারণ হ'ল এটি কলিং কোড থেকে পরিবর্তনগুলি পৃথক করে যা লেআউটআইফনেডকেও কল করতে পারে। (এবং টুইটার লিঙ্কের জন্য ধন্যবাদ)
ক্রিস কনভার

1
দুর্দান্ত উত্তর। বিশেষ কারণ আপনি এই বিষয়ে মার্টিন এবং কেনের কথোপকথনের উল্লেখ করেছেন।
জোনা

আমি আপডেট সীমাবদ্ধতার পদ্ধতিতে সম্পর্কে বিভ্রান্ত ও তাতে লিখলেন করছি এই । আপনি কি একবার দেখে নিতে পারেন?
মধু 20

36
// Step 1, update your constraint
self.myOutletToConstraint.constant = 50; // New height (for example)

// Step 2, trigger animation
[UIView animateWithDuration:2.0 animations:^{

    // Step 3, call layoutIfNeeded on your animated view's parent
    [self.view layoutIfNeeded];
}];

29

সুইফট 4 সমাধান

UIView.animate

তিনটি সহজ পদক্ষেপ:

  1. সীমাবদ্ধতাগুলি পরিবর্তন করুন, যেমন:

    heightAnchor.constant = 50
  2. এতে viewথাকা লেখনটি বলুন যে এটির বিন্যাসটি নোংরা এবং অটোলেআউটটি লেআউটটিকে পুনরায় গণনা করা উচিত:

    self.view.setNeedsLayout()
  3. অ্যানিমেশন ব্লকে বিন্যাসটিকে পুনরায় গণনা করতে বলুন যা সরাসরি ফ্রেম সেট করার সমতুল্য (এই ক্ষেত্রে অটোলেআউট ফ্রেম সেট করবে):

    UIView.animate(withDuration: 0.5) {
        self.view.layoutIfNeeded()
    }

সম্পূর্ণ সহজ উদাহরণ:

heightAnchor.constant = 50
self.view.setNeedsLayout()
UIView.animate(withDuration: 0.5) {
    self.view.layoutIfNeeded()
}

সাইড নোট

Anচ্ছিক 0 তম পদক্ষেপ রয়েছে - সীমাবদ্ধতা পরিবর্তন করার আগে আপনি self.view.layoutIfNeeded()যে অ্যানিমেশনটির প্রারম্ভিক বিন্দু প্রযোজ্য তা পুরানো বাধার সাথে রাজ্য থেকে এসেছে তা নিশ্চিত করতে কল করতে পারেন (যদি এমন কিছু বাধা পরিবর্তন ঘটেছিল যা অ্যানিমেশনে অন্তর্ভুক্ত করা উচিত নয়) ):

otherConstraint.constant = 30
// this will make sure that otherConstraint won't be animated but will take effect immediately
self.view.layoutIfNeeded()

heightAnchor.constant = 50
self.view.setNeedsLayout()
UIView.animate(withDuration: 0.5) {
    self.view.layoutIfNeeded()
}

UIViewPropertyAnimator

যেহেতু আইওএস 10 এর সাথে আমরা একটি নতুন অ্যানিমেটিং মেকানিজম পেয়েছি - তাই UIViewPropertyAnimatorআমাদের জানা উচিত যে মূলত একই পদ্ধতি এটিতে প্রযোজ্য। পদক্ষেপগুলি মূলত একই:

heightAnchor.constant = 50
self.view.setNeedsLayout()
let animator = UIViewPropertyAnimator(duration: 0.5, timingParameters: UICubicTimingParameters(animationCurve: .linear))
animator.addAnimations {
    self.view.layoutIfNeeded()
}
animator.startAnimation()

যেহেতু animatorঅ্যানিমেশনের একটি এনক্যাপসুলেশন তাই আমরা এটির রেফারেন্স রাখতে পারি এবং পরে এটি কল করতে পারি। তবে অ্যানিমেশন ব্লকে যেহেতু আমরা কেবল অটোলেআউটকে ফ্রেমগুলি পুনরায় গণনা করতে বলি, আমাদের কল করার আগে বাধা পরিবর্তন করতে হবে startAnimation। সুতরাং এর মতো কিছু সম্ভব:

// prepare the animator first and keep a reference to it
let animator = UIViewPropertyAnimator(duration: 0.5, timingParameters: UICubicTimingParameters(animationCurve: .linear))
animator.addAnimations {
    self.view.layoutIfNeeded()
}

// at some other point in time we change the constraints and call the animator
heightAnchor.constant = 50
self.view.setNeedsLayout()
animator.startAnimation()

সীমাবদ্ধতা পরিবর্তন করার এবং অ্যানিমেটার শুরু করার ক্রমটি গুরুত্বপূর্ণ - আমরা যদি কেবল সীমাবদ্ধতাগুলি পরিবর্তন করি এবং আমাদের অ্যানিম্যাটরটি পরে কিছু পয়েন্টের জন্য ছেড়ে রাখি তবে পরবর্তী পুনরায় আঁকানো চক্রটি অটোলেআউট পুনরায় গণনা করতে পারে এবং পরিবর্তনটি অ্যানিমেটেড হবে না।

এছাড়াও, মনে রাখবেন যে একটি একক অ্যানিম্যাটর পুনরায় ব্যবহারযোগ্য - আপনি একবার এটি চালানোর পরে আপনি এটি "পুনরায় চালু করতে পারবেন না"। সুতরাং আমি অনুমান করি যে অ্যানিম্যাটরটিকে চারপাশে রাখার পক্ষে আসলেই কোনও ভাল কারণ নেই, যদি না আমরা এটি ইন্টারেক্টিভ অ্যানিমেশন নিয়ন্ত্রণের জন্য ব্যবহার করি।


👍 ওয়ার্কসটি সুইফট 5-এও দুর্দান্ত
spnkr

লেআউটআইফনেড () কী
মেধী

15

স্টোরিবোর্ড, কোড, টিপস এবং কয়েকটি গোছা

অন্যান্য উত্তরগুলি ঠিক আছে তবে এটি একটি সাম্প্রতিক উদাহরণ ব্যবহার করে অ্যানিমেটিং সীমাবদ্ধতার কয়েকটি মোটামুটি গুরুত্বপূর্ণ গ্যাচচাকে হাইলাইট করে। নিম্নলিখিতগুলি উপলব্ধি করার আগে আমি অনেকগুলি প্রকরণের মধ্য দিয়ে গিয়েছিলাম:

শক্তিশালী রেফারেন্স ধরে রাখতে আপনি ক্লাস ভেরিয়েবলগুলিতে লক্ষ্য করতে চান এমন প্রতিবন্ধকতা তৈরি করুন। সুইফটে আমি অলস ভেরিয়েবল ব্যবহার করেছি:

lazy var centerYInflection:NSLayoutConstraint = {
       let temp =  self.view.constraints.filter({ $0.firstItem is MNGStarRating }).filter ( { $0.secondItem is UIWebView }).filter({ $0.firstAttribute == .CenterY }).first
        return temp!
}()

কিছু পরীক্ষা আমি লক্ষনীয় যে এক ভিউ থেকে বাধ্যতা প্রাপ্ত করা আবশ্যক উপরে (ওরফে superview) দুটি ভিউ যেখানে বাধ্যতা সংজ্ঞায়িত করা হয়। নীচের উদাহরণে (এমএনজিস্টাররেটিং এবং ইউআইউইউভিউ ভিউ উভয়ই আমি দুটি ধরণের আইটেমের মধ্যে সীমাবদ্ধতা তৈরি করছি এবং সেগুলি স্ব-ভিউয়ের মধ্যে সাবউভিউ রয়েছে)।

ফিল্টার চেইনিং

আমি স্যুইফ্টের ফিল্টার পদ্ধতির সুবিধা গ্রহণ করে কাঙ্ক্ষিত সীমাবদ্ধতা আলাদা করতে যা প্রতিস্থাপনের পয়েন্ট হিসাবে পরিবেশন করবে। একটি আরও জটিল হতে পারে তবে ফিল্টার এখানে দুর্দান্ত কাজ করে।

সুইফ্ট ব্যবহার করে অ্যানিমেশন সীমাবদ্ধতা

নোটা বেন - এই উদাহরণটি স্টোরিবোর্ড / কোড সমাধান এবং ধরে নেওয়া হয়েছে যে কেউ স্টোরিবোর্ডে ডিফল্ট সীমাবদ্ধতা তৈরি করেছে। এরপরে কোড ব্যবহার করে পরিবর্তনগুলি প্রাণবন্ত করা যায়।

ধরে নিচ্ছি যে আপনি সঠিক মানদণ্ডের সাথে ফিল্টার করার জন্য একটি সম্পত্তি তৈরি করেছেন এবং আপনার অ্যানিমেশনের জন্য একটি নির্দিষ্ট প্রতিস্থাপন পয়েন্টে পৌঁছাবেন (অবশ্যই যদি আপনি একাধিক সীমাবদ্ধতার প্রয়োজন হয় তবে আপনি একটি অ্যারের জন্য ফিল্টারও করতে পারেন)

lazy var centerYInflection:NSLayoutConstraint = {
    let temp =  self.view.constraints.filter({ $0.firstItem is MNGStarRating }).filter ( { $0.secondItem is UIWebView }).filter({ $0.firstAttribute == .CenterY }).first
    return temp!
}()

....

একটু পরে...

@IBAction func toggleRatingView (sender:AnyObject){

    let aPointAboveScene = -(max(UIScreen.mainScreen().bounds.width,UIScreen.mainScreen().bounds.height) * 2.0)

    self.view.layoutIfNeeded()


    //Use any animation you want, I like the bounce in springVelocity...
    UIView.animateWithDuration(1.0, delay: 0.0, usingSpringWithDamping: 0.3, initialSpringVelocity: 0.75, options: [.CurveEaseOut], animations: { () -> Void in

        //I use the frames to determine if the view is on-screen
        if CGRectContainsRect(self.view.frame, self.ratingView.frame) {

            //in frame ~ animate away
            //I play a sound to give the animation some life

            self.centerYInflection.constant = aPointAboveScene
            self.centerYInflection.priority = UILayoutPriority(950)

        } else {

            //I play a different sound just to keep the user engaged
            //out of frame ~ animate into scene
            self.centerYInflection.constant = 0
            self.centerYInflection.priority = UILayoutPriority(950)
            self.view.setNeedsLayout()
            self.view.layoutIfNeeded()
         }) { (success) -> Void in

            //do something else

        }
    }
}

অনেক ভুল পালা

এই নোটগুলি সত্যই টিপসের একটি সেট যা আমি নিজের জন্য লিখেছিলাম। আমি ব্যক্তিগতভাবে এবং বেদনাদায়ক সমস্ত করণীয় না করেছিলাম। আশা করি এই গাইড অন্যকে বাঁচাতে পারবে।

  1. জেডপজিশনিংয়ের জন্য সতর্কতা অবলম্বন করুন। কখনও কখনও যখন দৃশ্যত কিছুই ঘটছে না তখন আপনার অন্যান্য ভিউগুলি লুকিয়ে রাখা উচিত বা আপনার অ্যানিমেটেড ভিউ সনাক্ত করতে ভিউ ডিবাগারটি ব্যবহার করা উচিত। এমনকি এমন কোনও ঘটনা আমি খুঁজে পেয়েছি যেখানে কোনও স্টোরবোর্ডের এক্সএমএল-তে ব্যবহারকারী সংজ্ঞায়িত রানটাইম অ্যাট্রিবিউট হারিয়ে গিয়েছিল এবং অ্যানিমেটেড ভিউটি কভার করা হয়েছিল (কাজ করার সময়)।

  2. ডকুমেন্টেশন (নতুন এবং পুরানো), দ্রুত সহায়তা এবং শিরোনামগুলি পড়তে সর্বদা এক মিনিট সময় নিন। অ্যাপল অটোলআউট সীমাবদ্ধতাগুলি আরও ভালভাবে পরিচালনা করতে (স্ট্যাকের দেখুন দেখুন) অনেকগুলি পরিবর্তন করে রাখে। অথবা কমপক্ষে অটোলআউট কুকবুক । মনে রাখবেন যে কখনও কখনও সেরা সমাধানগুলি পুরানো ডকুমেন্টেশন / ভিডিওগুলিতে থাকে।

  3. অ্যানিমেশনটিতে মানগুলি নিয়ে প্রায় খেলুন এবং অন্যান্য অ্যানিমেটডিউরডেরেশন ভেরিয়েন্টগুলি ব্যবহার করে বিবেচনা করুন।

  4. অন্যান্য ধ্রুবকগুলিতে পরিবর্তনগুলি নির্ধারণের মানদণ্ড হিসাবে নির্দিষ্ট বিন্যাস মানগুলিকে হার্ডকোড করবেন না, পরিবর্তে এমন মানগুলি ব্যবহার করুন যা আপনাকে দেখার অবস্থান নির্ধারণ করতে দেয়। CGRectContainsRectএকটি উদাহরণ

  5. প্রয়োজনে সীমাবদ্ধতার সংজ্ঞাতে অংশ নেওয়া ভিউয়ের সাথে যুক্ত লেআউট মার্জিনটি ব্যবহার করতে দ্বিধা করবেন না let viewMargins = self.webview.layoutMarginsGuide: উদাহরণস্বরূপ
  6. আপনার যে কাজটি করতে হবে না এমন কাজ করবেন না, স্টোরিবোর্ডে সীমাবদ্ধতা সহ সমস্ত দর্শনগুলির সম্পত্তি হিসাবে স্ব-সংযুক্তি রয়েছে view
  7. যে কোনও প্রতিবন্ধকতার জন্য আপনার অগ্রাধিকারগুলি 1000 এরও কম পরিবর্তন করুন I আমি স্টোরিবোর্ডে আমার 250 (নিম্ন) বা 750 (উচ্চ) তে সেট করেছি; (যদি আপনি কোডের যে কোনও কিছুতে 1000 টি অগ্রাধিকার পরিবর্তন করার চেষ্টা করেন তবে অ্যাপ্লিকেশনটি ক্রাশ হবে কারণ 1000 প্রয়োজন)
  8. তাত্ক্ষণিকভাবে অ্যাক্টিভেট কনস্ট্রেন্টস এবং নিষ্ক্রিয়করণ কনট্রেনটগুলি ব্যবহার করার চেষ্টা না করার বিষয়টি বিবেচনা করুন (তাদের জায়গা রয়েছে তবে কেবল শিখতে গিয়ে বা আপনি যদি কোনও স্টোরিবোর্ড ব্যবহার করছেন সম্ভবত এটি আপনার অত্যধিক কাজ করার অর্থ রয়েছে - নীচে যেমন দেখানো হয়েছে তবুও তাদের একটি জায়গা রয়েছে)
  9. আপনি যদি কোডটিতে সত্যিকার অর্থে একটি নতুন বাধা না যোগ করেন তবে অ্যাডকন্ট্রেন্টস / রিমুভ কনট্রেন্টগুলি ব্যবহার না করার বিষয়টি বিবেচনা করুন। আমি দেখতে পেলাম যে বেশিরভাগ সময় আমি স্টোরিবোর্ডে পছন্দসই সীমাবদ্ধতাগুলি দিয়ে দেখি (ভিউটি অফস্ক্রিন স্থাপন করে), তারপরে কোডে, স্টোরিবোর্ডে পূর্বে তৈরি হওয়া সীমাবদ্ধতাগুলিকে ঘুরিয়ে দেওয়ার জন্য আমি সঞ্চার করি।
  10. আমি নতুন এনএসএনচরলআউট ক্লাস এবং সাবক্লাসগুলির সাথে সীমাবদ্ধতা তৈরি করতে প্রচুর অপচয় করার সময় ব্যয় করেছি। এই কাজগুলি ঠিকঠাক তবে এটি বুঝতে আমার কিছুটা সময় লেগেছিল যে আমার যে সমস্ত প্রতিবন্ধকতাগুলির প্রয়োজন ছিল সেগুলি স্টোরবোর্ডে ইতিমধ্যে বিদ্যমান। আপনি যদি কোডটিতে সীমাবদ্ধতা তৈরি করেন তবে অবশ্যই আপনার সীমাবদ্ধতাগুলিকে একত্রিত করতে এই পদ্ধতিটি ব্যবহার করুন:

স্টোরিবোর্ডগুলি ব্যবহার করার সময় AVOID এর সমাধানের দ্রত নমুনা

private var _nc:[NSLayoutConstraint] = []
    lazy var newConstraints:[NSLayoutConstraint] = {

        if !(self._nc.isEmpty) {
            return self._nc
        }

        let viewMargins = self.webview.layoutMarginsGuide
        let minimumScreenWidth = min(UIScreen.mainScreen().bounds.width,UIScreen.mainScreen().bounds.height)

        let centerY = self.ratingView.centerYAnchor.constraintEqualToAnchor(self.webview.centerYAnchor)
        centerY.constant = -1000.0
        centerY.priority = (950)
        let centerX =  self.ratingView.centerXAnchor.constraintEqualToAnchor(self.webview.centerXAnchor)
        centerX.priority = (950)

        if let buttonConstraints = self.originalRatingViewConstraints?.filter({

            ($0.firstItem is UIButton || $0.secondItem is UIButton )
        }) {
            self._nc.appendContentsOf(buttonConstraints)

        }

        self._nc.append( centerY)
        self._nc.append( centerX)

        self._nc.append (self.ratingView.leadingAnchor.constraintEqualToAnchor(viewMargins.leadingAnchor, constant: 10.0))
        self._nc.append (self.ratingView.trailingAnchor.constraintEqualToAnchor(viewMargins.trailingAnchor, constant: 10.0))
        self._nc.append (self.ratingView.widthAnchor.constraintEqualToConstant((minimumScreenWidth - 20.0)))
        self._nc.append (self.ratingView.heightAnchor.constraintEqualToConstant(200.0))

        return self._nc
    }()

আপনি যদি এই টিপসগুলির একটি বা আরও সাধারণ বিষয়গুলি ভুলে যান তবে লেফটটি আইফনপিডটি কোথায় যুক্ত করতে চান তবে সম্ভবত কিছুই ঘটবে না: সেক্ষেত্রে আপনার অর্ধ বেকড সমাধান থাকতে পারে:

এনবি - নীচে অটোলআউট বিভাগ এবং মূল গাইডটি পড়তে কিছুক্ষণ সময় নিন। আপনার গতিশীল অ্যানিমেটারগুলির পরিপূরক করতে এই কৌশলগুলি ব্যবহার করার একটি উপায় রয়েছে।

UIView.animateWithDuration(1.0, delay: 0.0, usingSpringWithDamping: 0.3, initialSpringVelocity: 1.0, options: [.CurveEaseOut], animations: { () -> Void in

            //
            if self.starTopInflectionPoint.constant < 0  {
                //-3000
                //offscreen
                self.starTopInflectionPoint.constant = self.navigationController?.navigationBar.bounds.height ?? 0
                self.changeConstraintPriority([self.starTopInflectionPoint], value: UILayoutPriority(950), forView: self.ratingView)

            } else {

                self.starTopInflectionPoint.constant = -3000
                 self.changeConstraintPriority([self.starTopInflectionPoint], value: UILayoutPriority(950), forView: self.ratingView)
            }

        }) { (success) -> Void in

            //do something else
        }

    }

অটোলআউট গাইড থেকে স্নিপেট (দ্বিতীয় স্নিপেটটি ওএস এক্স ব্যবহারের জন্য নোট করুন)। বিটিডাব্লু - এটি যতদূর আমি দেখতে পাচ্ছি বর্তমান গাইডে আর নেই। পছন্দসই কৌশলগুলি বিকশিত হতে থাকে।

অটো লেআউট দ্বারা তৈরি অ্যানিমেটিং পরিবর্তনগুলি

অটো লেআউট দ্বারা করা অ্যানিমেটরিং পরিবর্তনগুলির উপরে যদি আপনার পুরো নিয়ন্ত্রণের প্রয়োজন হয় তবে আপনাকে অবশ্যই নিজের বাধা পরিবর্তন করতে হবে প্রোগ্রামিয়ালি। আইওএস এবং ওএস এক্স উভয়ের ক্ষেত্রে প্রাথমিক ধারণাটি একই, তবে কয়েকটি ছোটখাটো পার্থক্য রয়েছে।

কোনও আইওএস অ্যাপ্লিকেশনে, আপনার কোডটি নীচের মতো কিছু দেখাচ্ছে:

[containerView layoutIfNeeded]; // Ensures that all pending layout operations have been completed
[UIView animateWithDuration:1.0 animations:^{
     // Make all constraint changes here
     [containerView layoutIfNeeded]; // Forces the layout of the subtree animation block and then captures all of the frame changes
}];

ওএস এক্স-এ, স্তর-ব্যাকযুক্ত অ্যানিমেশনগুলি ব্যবহার করার সময় নিম্নলিখিত কোডটি ব্যবহার করুন:

[containterView layoutSubtreeIfNeeded];
[NSAnimationContext runAnimationGroup:^(NSAnimationContext *context) {
     [context setAllowsImplicitAnimation: YES];
     // Make all constraint changes here
     [containerView layoutSubtreeIfNeeded];
}];

আপনি যখন স্তর-ব্যাকযুক্ত অ্যানিমেশন ব্যবহার করছেন না, তখন আপনাকে অবশ্যই সীমাবদ্ধতার অ্যানিম্যাটর ব্যবহার করে ধ্রুবকটি অ্যানিমেট করতে হবে:

[[constraint animator] setConstant:42];

যারা আরও ভালভাবে শিখেন তাদের জন্য অ্যাপল থেকে এই প্রাথমিক ভিডিওটি দেখুন

গভীর মনোযোগ দাও

ডকুমেন্টেশনে প্রায়শই ছোট ছোট নোট বা কোডের টুকরা থাকে যা বড় আইডিয়াগুলিতে নিয়ে যায়। উদাহরণস্বরূপ গতিশীল অ্যানিমেটারগুলিতে অটো লেআউট সীমাবদ্ধতা যুক্ত করা একটি বড় ধারণা।

শুভকামনা এবং বাহিনী আপনার সাথে থাকুক।



6

ওয়ার্কিং সলিউশন 100% সুইফট 3.1

আমি সমস্ত উত্তর পড়েছি এবং আমার সমস্ত অ্যাপ্লিকেশনগুলিতে সঠিকভাবে অ্যানিমেট করার জন্য আমি যে সমস্ত লাইন ব্যবহার করেছি সেগুলি কোড এবং লাইনগুলি ভাগ করতে চাই, কিছু সমাধান এখানে কাজ করছে না, আপনার এই মুহুর্তে ধীর ডিভাইসগুলি যেমন আইফোন 5 এ তাদের পরীক্ষা করা উচিত।

self.view.layoutIfNeeded() // Force lays of all subviews on root view
UIView.animate(withDuration: 0.5) { [weak self] in // allowing to ARC to deallocate it properly
       self?.tbConstraint.constant = 158 // my constraint constant change
       self?.view.layoutIfNeeded() // Force lays of all subviews on root view again.
}

4

আমি সীমাবদ্ধতা সক্রিয় করার চেষ্টা করছিলাম এবং একটি ভাল ব্যাখ্যা পাওয়া খুব সহজ ছিল না।

অন্যান্য উত্তরগুলি যা বলছে তা সম্পূর্ণ সত্য: আপনাকে [self.view layoutIfNeeded];ভিতরে কল করা দরকার animateWithDuration: animations:। যাইহোক, অন্যান্য গুরুত্বপূর্ণ পয়েন্টটি হ'ল NSLayoutConstraintযে আপনি প্রাণবন্ত করতে চান তার জন্য পয়েন্টার থাকা ।

আমি গিটহাবে একটি উদাহরণ তৈরি করেছি


4

এক্সকোড 8.3.3 দিয়ে সুইফ্ট 3 এর জন্য কাজ করা এবং সবেমাত্র পরীক্ষিত সমাধান:

self.view.layoutIfNeeded()
self.calendarViewHeight.constant = 56.0

UIView.animate(withDuration: 0.5, delay: 0.0, options: UIViewAnimationOptions.curveEaseIn, animations: {
        self.view.layoutIfNeeded()
    }, completion: nil)

কেবল মনে রাখবেন যে স্বতঃপ্রেমক্যালেন্ডারভিউহাইটটি একটি কাস্টমভিউ (ক্যালেন্ডারভিউ) -কে উল্লেখ করা বাধা। আমি .layoutIfNeeded () কে সেলফ.উভিউতে কল করেছি এবং সেলফ্যাঙ্কল্যান্ডের ভিউতে নয়

এই সাহায্য আশা করি।


3

এটি সম্পর্কে একটি নিবন্ধের আলোচনা আছে: http://weblog.invasivecode.com/post/42362079291/auto-layout-and-core-animation-auto-layout-was

যা তিনি এইভাবে কোড করেছেন:

- (void)handleTapFrom:(UIGestureRecognizer *)gesture {
    if (_isVisible) {
        _isVisible = NO;
        self.topConstraint.constant = -44.;    // 1
        [self.navbar setNeedsUpdateConstraints];  // 2
        [UIView animateWithDuration:.3 animations:^{
            [self.navbar layoutIfNeeded]; // 3
        }];
    } else {
        _isVisible = YES;
        self.topConstraint.constant = 0.;
        [self.navbar setNeedsUpdateConstraints];
        [UIView animateWithDuration:.3 animations:^{
            [self.navbar layoutIfNeeded];
        }];
    }
}

আশা করি এটা সাহায্য করবে.


1

সীমাবদ্ধ অ্যানিমেশন প্রসঙ্গে, আমি একটি নির্দিষ্ট পরিস্থিতি উল্লেখ করতে চাই যেখানে আমি কীবোর্ড_বিষ্ট বিজ্ঞপ্তির মধ্যে অবিলম্বে একটি সীমাবদ্ধতা অ্যানিমেটেড করেছি।

প্রতিবন্ধক একটি টেক্সটফিল্ড থেকে ধারকের শীর্ষে শীর্ষ স্থানকে সংজ্ঞায়িত করে। কীবোর্ড খোলার পরে, আমি কেবল ধ্রুবকটি 2 দ্বারা বিভক্ত করি।

আমি সরাসরি কীবোর্ড বিজ্ঞপ্তির মধ্যে একটি সামঞ্জস্যপূর্ণ মসৃণ সীমাবদ্ধ অ্যানিমেশন অর্জন করতে অক্ষম ছিল। অ্যানিমেটেড ছাড়াই প্রায় অর্ধবার দর্শনটি তার নতুন অবস্থানে চলে যাবে।

এটি আমার কাছে ঘটেছিল কীবোর্ড খোলার ফলে কিছু অতিরিক্ত লেআউটিং ঘটতে পারে। 10 মিমি দেরি করে একটি সাধারণ প্রেরণ_পর ব্লক যুক্ত করা অ্যানিমেশনটি প্রতিবার চালিত করে - কোনও জাম্পিং হয় না।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.