අවහිරතා වෙනස්කම් සජීවීකරණය කරන්නේ කෙසේද?


966

මම පැරණි යෙදුමක් සමඟ යාවත්කාලීන කරන අතර 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;
}

බැනරය චලනය වන අතර, හරියටම අපේක්ෂා කළ පරිදි, නමුත් සජීවිකරණයක් නොමැත .


යාවත්කාලීන කිරීම: සජීවිකරණය ආවරණය කරන මාස්ටර් ඔටෝ පිරිසැලසුම සඳහා WWDC 12 talk හොඳම භාවිතයන් මම නැවත බැලුවෙමි . CoreAnimation භාවිතයෙන් බාධක යාවත්කාලීන කරන්නේ කෙසේද යන්න එහි සාකච්ඡා කරයි :

මම පහත කේතය සමඟ උත්සාහ කර ඇත්තෙමි, නමුත් එකම ප්‍රති results ල ලබා ගන්න:

- (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;
}

පැත්තක සටහනක, මම කිහිප වතාවක් පරීක්ෂා කර ඇති අතර මෙය ප්‍රධාන නූලෙන් ක්‍රියාත්මක වේ.



3
පිළිතුරෙහි අක්ෂර වින්‍යාසයක් තිබේ නම්, ඔබ පිළිතුර සංස්කරණය කළ යුතුය. ඒවා සංස්කරණය කළ හැකි වන්නේ එබැවිනි.
i_am_jorf

@ ජෙෆමාෆෝන් - ඔබ යතුරු ලියනය පෙන්වා දුන්නොත් එය වඩාත් ප්‍රයෝජනවත් වනු ඇත, එවිට වැරැද්ද කොතැනදැයි මම දැන සිටියෙමි. ඔබට පිළිතුර ඔබ විසින්ම සංස්කරණය කළ හැකි අතර අපගේ ඩයබ්‍රිබය අනෙක් සියල්ලන්ම ඉතිරි කර යතුරු ලියනය සවි කර ඇත. මම එය සංස්කරණය කළේ සජීවීකරණ කොටසෙන් නියතය ඉවත් කිරීමටයි, එය ඔබ සඳහන් කරන්නේ නම්.
ඩීබීඩී

1
යතුරු ලියනය යනු කුමක්දැයි මම නොදනිමි. මම ඉහත අදහස් වලට ප්‍රතිචාර දැක්වුවෙමි.
i_am_jorf

9
එවිට යතුරු ලියනය යනු ප්‍රශ්නයයි. මෝඩ ලෙස මම "පිරිසැලසුම IFNeeded" වෙනුවට "setNeedsLayout" ටයිප් කරමින් සිටියෙමි. දෝෂය සමඟ මගේ කේතය කපා නිවැරදි විධාන සමඟ තිරපිටපත් කරන විට එය මගේ ප්‍රශ්නයේ පැහැදිලිව පෙන්වා ඇත. කවුරුහරි එය පෙන්වා දෙන තුරු එය දුටු බවක් නොපෙනේ.
ඩීබීඩී

Answers:


1709

වැදගත් සටහන් දෙකක්:

  1. ඔබට layoutIfNeededසජීවිකරණ කොටස තුළට ඇමතිය යුතුය . ඇපල් සැබවින්ම නිර්දේශ කරන්නේ ඔබ විසින් සජීවීකරණ වාරණයට පෙර එක් වරක් එය අමතන්න

  2. ඔබට එය විශේෂයෙන් ඇමතිය යුත්තේ මවුපියන්ගේ දෘෂ්ටිය මත ය (උදා self.view), නමුත් ළමයින්ගේ දෘෂ්ටිය එයට අවහිරතා ඇති බව නොවේ. එසේ කිරීමෙන් ඔබ සීමා කර ඇති දෘෂ්ටියට සීමා විය හැකි වෙනත් අදහස් සජීවිකරණය කිරීම ඇතුළුව සියලු සීමා සහිත අදහස් යාවත්කාලීන වනු ඇත (උදා: View B යනු View A හි පහළට අමුණා ඇති අතර ඔබ View A හි ඉහළ ඕෆ්සෙට් එක වෙනස් කර ඇති අතර ඔබට View B අවශ්‍ය වේ එය සමඟ සජීවීකරණය කිරීමට)

මේක උත්සාහ කරන්න:

පරමාර්ථය-සී

- (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()
}

207
ඔබ දන්නවා මොකක්ද ... ඔබේ පිළිතුර ක්‍රියාත්මක වේ. WWDC වැඩ කරයි .... මගේ දැක්ම අසාර්ථකයි. කිසියම් හේතුවක් නිසා මා setNeedsLayoutඒ වෙනුවට කතා කරන බව වටහා ගැනීමට සතියක් ගත විය layoutIfNeeded. මම වැරදි ක්‍රමයේ නම ටයිප් කළෙමි.
ඩීබීඩී

23
විසඳුම ක්‍රියාත්මක වන නමුත් සජීවිකරණ කොටස තුළ ඇති අවහිරතා නියතය වෙනස් කිරීමට ඔබට අවශ්‍ය නැත . සජීවිකරණය පයින් ගැසීමට පෙර එක් වරක් අවහිරතා සකස් කිරීම මුළුමනින්ම හොඳයි. ඔබ ඔබේ පිළිතුර සංස්කරණය කළ යුතුය.
ඕට්වින් ජෙන්ට්ස්

75
මෙය මුලින් මට වැඩ නොකළ අතර පසුව ඔබට වැටහී ඇත්තේ ඔබට පිරිසැලසුම ඇමතිය යුතු බව PARENT දැක්ම මත මිස අවහිරතා අදාළ නොවන බවයි.
ඔලිවර් පියර්මේන්

20
LayoutIfNeeded භාවිතා කිරීමෙන් අවහිරතා වෙනස පමණක් නොව සියලු උපසිරැසි නැවුම් කරයි. අවහිරතා වෙනස පමණක් ඔබ සජීවීකරණය කරන්නේ කෙසේද?
ngb

11
"ඇපල් සැබවින්ම නිර්දේශ කර ඇත්තේ සජීවීකරණ වාරණයට පෙර එක් වරක් ඇමතීමටයි. අපේක්ෂිත පිරිසැලසුම් මෙහෙයුම් සියල්ල අවසන් වී ඇති බව සහතික කර ගන්න", ස්තූතියි, ඒ ගැන කිසි විටෙකත් නොසිතූ නමුත් එය අර්ථවත් කරයි.
රික් වැන් ඩර් ලින්ඩේ

111

ලබා දී ඇති පිළිතුර මම අගය කරමි, නමුත් එය තව ටිකක් ඉදිරියට ගෙන යාම සතුටක් යැයි මම සිතමි.

ප්‍රලේඛනයෙන් මූලික බ්ලොක් සජීවිකරණය

[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];

යාවත්කාලීකරණ ක්‍රමය UIView උප පංතියේ අභිබවා ගොස් ඇති අතර ක්‍රමයේ අවසානයේ සුපිරි ලෙස ඇමතිය යුතුය.

- (void)updateConstraints
{
    // Update some constraints

    [super updateConstraints];
}

ස්වයංක්‍රීය සැකසුම් මාර්ගෝපදේශය අපේක්‍ෂා කිරීමට බොහෝ දේ ඉතිරිව ඇති නමුත් එය කියවීම වටී. සරල හා සියුම් බිඳවැටීමේ සජීවිකරණයක් (තත්පර 0.2 ක් දිග) UISwitchසහිත යුගල යුගලයක් සමඟ උප දර්ශනයක් ටොගල් කරන කොටසක කොටසක් ලෙස මම මෙය භාවිතා කරමි UITextField. ඉහත විස්තර කර ඇති පරිදි UIView උප පංති යාවත්කාලීනයන්හි උපලේඛනය සඳහා වන බාධක හසුරුවනු ලැබේ.


ඉහත සියලු ක්‍රම self.viewඇමතීමේදී (සහ එම දර්ශනයේ උප දර්ශනයක නොවේ), ඇමතීම updateConstraintsIfNeededඅවශ්‍ය නොවේ (මන්ද එම දෘෂ්ටිය setNeedsLayoutද අවුලුවන updateConstraints). බොහෝ දුරට සුළු කාරණයක් විය හැකි නමුත් එය මේ වන තෙක් මට නොවීය;)
ඇනෙබ්ලූ

ඔබේ විශේෂිත අවස්ථාවෙහිදී ස්වයංක්‍රීය සැකැස්ම සහ උල්පත් සහ නූල් පිරිසැලසුම පිළිබඳ සම්පූර්ණ අන්තර් ක්‍රියාකාරීත්වය නොදැන අදහස් දැක්වීම අපහසුය. මම මුළුමනින්ම කතා කරන්නේ පිරිසිදු ස්වයංක්‍රීය වාතාවරණයක් ගැන ය. ඔබගේ පිරිසැලසුම සබ්වීව්ස් ක්‍රමයේ හරියටම සිදුවන්නේ කුමක්ද යන්න දැන ගැනීමට මට කුතුහලයක් ඇත.
කැමරන් ලෝවෙල් පාමර්

translatesAutoresizingMaskIntoConstraints = නැත; ඔබට ස්වයංක්‍රීයව ස්වයංක්‍රීයව ක්‍රියා කිරීමට අවශ්‍ය නම් මෙය අනිවාර්යයෙන්ම අක්‍රිය කළ යුතුය.
කැමරන් ලෝවෙල් පාමර්

මම එය දැක නැත, නමුත් කිසියම් කේතයක් නොමැතිව මට ඇත්ත වශයෙන්ම ගැටලුව සමඟ කතා කළ නොහැක. සමහර විට ඔබට මේස දර්ශනයක් සමච්චලයට ලක් කර එය GitHub හි ඇලවිය හැකිද?
කැමරන් ලෝවෙල් පාමර්

කණගාටුයි, මම gitHub භාවිතා නොකරමි :(
ඇනෙබ්ලූ

75

සාමාන්‍යයෙන්, ඔබට අවශ්‍ය වන්නේ අවහිරතා යාවත්කාලීන layoutIfNeededකර සජීවිකරණ කොටස තුළට ඇමතීමයි. මෙය එක්කෝ .constantදේපල වෙනස් කිරීම NSLayoutConstraint, ඉවත් කිරීමේ අවහිරතා (iOS 7) එකතු කිරීම හෝ .activeඅවහිරතා වල දේපල වෙනස් කිරීම (iOS 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];
}];

නියැදි සැකසුම:

Xcode Project එබැවින් නියැදි සජීවිකරණ ව්‍යාපෘතිය.

මතභේදය

සජීවිකරණ වාරණයට පෙර හෝ එහි ඇතුළත අවහිරතා වෙනස් කළ යුතුද යන්න පිළිබඳ ප්‍රශ්න කිහිපයක් තිබේ (පෙර පිළිතුරු බලන්න).

පහත දැක්වෙන්නේ iOS උගන්වන මාටින් පිල්කින්ටන් සහ ඔටෝ පිරිසැලසුම ලියූ කෙන් ෆෙරී අතර ට්විටර් සංවාදයකි. කෙන් පැහැදිලි කරන්නේ සජීවිකරණ බ්ලොක් එකෙන් පිටත නියතයන් වෙනස් කිරීම දැනට ක්‍රියාත්මක වුවද එය ආරක්ෂිත නොවන අතර ඒවා ඇත්ත වශයෙන්ම සජීවිකරණ කොටස තුළ වෙනස් විය යුතු බවයි . https://twitter.com/kongtomorrow/status/440627401018466305

සජීවිකරණය:

නියැදි ව්‍යාපෘතිය

දර්ශනයක් සජීවිකරණය කළ හැකි ආකාරය පෙන්වන සරල ව්‍යාපෘතියක් මෙන්න. එය පරමාර්ථ C භාවිතා .activeකරන අතර අවහිරතා කිහිපයක දේපල වෙනස් කිරීමෙන් දර්ශනය සජීවිකරණය කරයි . https://github.com/shepting/SampleAutoLayoutAnimation


නව ක්‍රියාකාරී ධජය භාවිතා කරමින් උදාහරණයක් පෙන්වීම සඳහා +1. එසේම, සජිවිකරණ බ්ලොක් එකෙන් පිටත ඇති බාධකය වෙනස් කිරීම සැමවිටම මට
කරදරයක්

මම ගිතුබ් හි ප්‍රශ්නයක් මතු කළේ දර්ශනය නැවත තිබූ ස්ථානයට ගෙනයාමට මෙම විසඳුම ක්‍රියා නොකරන බැවිනි. ක්‍රියාකාරී ලෙස වෙනස් කිරීම නිවැරදි විසඳුම නොවන බවත්, ඒ වෙනුවට ඔබ ප්‍රමුඛතාවය වෙනස් කළ යුතු බවත් මම විශ්වාස කරමි. ඉහළ සිට 750 දක්වාත්, පහළ කොටස 250 දක්වාත්, පසුව UILayoutPriorityDefaultHigh සහ UILayoutPriorityDefaultLow අතර කේත විකල්පයක් ලෙස සකසන්න.
malhal

වාරණය තුළ යාවත්කාලීන වීමට තවත් හේතුවක් නම්, එය ඇමතුම් කේතයෙන් සිදුවන වෙනස්කම් හුදකලා වීමයි. (සහ ට්විටර් සබැඳියට ස්තූතියි)
ක්‍රිස් කොනෝවර්

1
නියම පිළිතුර. විශේෂයෙන් ඔබ මේ ගැන මාටින්ගේ සහ කෙන්ගේ සංවාදය සඳහන් කළ නිසා.
ජෝනා

අවහිරතා යාවත්කාලීන කරන ආකාරය ගැන මම ව්‍යාකූල වී මෙය ලිවීය . කරුණාකර බලන්න පුළුවන්ද?
මී පැණි

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];
}];

30

ස්විෆ්ට් 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()
}

Sidenote

විකල්ප 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

IOS 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සජීවිකරණ ක encapsulation වන අතර, අප එය සඳහන් තබා පසුව එය අමතන්න හැක. කෙසේ වෙතත්, සජීවිකරණ වාරණයේදී අපි ස්වයංක්‍රීයව රාමු නැවත ගණනය කරන ලෙස පවසන බැවින්, ඇමතීමට පෙර සීමාවන් වෙනස් කළ 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()

අවහිරතා වෙනස් කිරීම සහ සජීවිකරණයක් ආරම්භ කිරීමේ අනුපිළිවෙල වැදගත් වේ - අප විසින් සීමාවන් වෙනස් කර අපගේ සජිවිකරණය පසුකාලීනව තබන්නේ නම්, ඊළඟ නැවත ඇඳීමේ චක්‍රයට ස්වයංක්‍රීයව නැවත ගණනය කිරීමක් කළ හැකි අතර වෙනස සජීවීකරණය නොකෙරේ.

එසේම, තනි සජීවිකරණයක් නැවත භාවිතා කළ නොහැකි බව මතක තබා ගන්න - ඔබ එය ක්‍රියාත්මක කළ පසු ඔබට එය "නැවත ධාවනය" කළ නොහැක. එබැවින් අන්තර්ක්‍රියාකාරී සජීවිකරණයක් පාලනය කිරීම සඳහා අප එය භාවිතා නොකරන්නේ නම්, සජීවිකරණය වටා තබා ගැනීමට හොඳ හේතුවක් නොමැති බව මම අනුමාන කරමි.


layoutIfNeeded () යතුරයි
Medhi

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 හෙවත්) එම අවහිරතා අර්ථ දක්වා ඇත එහිදී දෙදෙනා අදහස්. පහත උදාහරණයේ (MNGStarRating සහ UIWebView යන දෙකම මා අතර අවහිරයක් නිර්මාණය කරන අයිතම වර්ග දෙක වන අතර ඒවා ස්වයං දර්ශනය තුළ උප දර්ශන වේ).

පෙරහන් දාමය

මම ස්විෆ්ට් හි පෙරහන් ක්‍රමයෙන් ප්‍රයෝජන ගන්නේ අපේක්ෂිත අවහිරතා වෙන් කිරීමටයි. කෙනෙකුට වඩාත් සංකීර්ණ විය හැකි නමුත් පෙරණය මෙහි හොඳ කාර්යයක් කරයි.

ස්විෆ්ට් භාවිතයෙන් අවහිරතා සජීවිකරණය කිරීම

Nota Bene - මෙම උදාහරණය කතන්දර පුවරුව / කේත විසඳුම වන අතර යමෙකු කතන්දර පුවරුවේ පෙරනිමි බාධක ඇති කර ඇතැයි උපකල්පනය කරයි. එවිට කෙනෙකුට කේත භාවිතයෙන් වෙනස්කම් සජීවීකරණය කළ හැකිය.

නිවැරදි නිර්ණායකයන් සමඟ පෙරීමට සහ ඔබේ සජීවිකරණය සඳහා නිශ්චිත ප්‍රේරක ලක්ෂ්‍යයකට පිවිසීමට ඔබ දේපලක් නිර්මාණය කර ඇතැයි උපකල්පනය කිරීම (ඇත්ත වශයෙන්ම ඔබට අරාව සඳහා පෙරහන් කළ හැකි අතර ඔබට බහු අවහිරතා අවශ්‍ය නම් ඒවා හරහා ලූපයක් ලබා ගත හැකිය):

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. ZPositioning ගැන විමසිල්ලෙන් සිටින්න. සමහර විට කිසිවක් පෙනෙන්නට නැති විට, ඔබ වෙනත් දර්ශන කිහිපයක් සැඟවිය යුතුය, නැතහොත් ඔබේ සජීවිකරණ දර්ශනය සොයා ගැනීමට දර්ශන නිදොස්කරණය භාවිතා කළ යුතුය. කතන්දර පුවරුවේ එක්ස්එම්එල් තුළ පරිශීලක අර්ථ දක්වන ලද ධාවන කාල ගුණාංගයක් නැතිවී ගොස් සජීවිකරණ දර්ශනය ආවරණය කිරීමට හේතු වූ අවස්ථා (වැඩ කරන අතරතුර) මම සොයාගෙන ඇත.

  2. ප්‍රලේඛනය (නව සහ පැරණි), ඉක්මන් උදව් සහ ශීර්ෂ කියවීමට සෑම විටම විනාඩියක් ගත කරන්න. ස්වයංක්‍රීය සැකසුම් අවහිරතා වඩා හොඳින් කළමනාකරණය කිරීම සඳහා ඇපල් විසින් බොහෝ වෙනස්කම් සිදු කරයි (තොග දර්ශන බලන්න). නැතහොත් අවම වශයෙන් ස්වයංක්‍රීය සැකසුම් කුක් පොත . සමහර විට හොඳම විසඳුම් පැරණි ලියකියවිලි / වීඩියෝවල ඇති බව මතක තබා ගන්න.

  3. සජීවිකරණයේ අගයන් සමඟ සෙල්ලම් කර වෙනත් සජීවිකරණ විත් ඩියුරේෂන් ප්‍රභේද භාවිතා කිරීම ගැන සලකා බලන්න.

  4. වෙනත් නියතයන්හි වෙනස්කම් තීරණය කිරීමේ නිර්ණායකයක් ලෙස නිශ්චිත පිරිසැලසුම් අගයන් දෘඩ කේතනය නොකරන්න, ඒ වෙනුවට දර්ශනයේ පිහිටීම තීරණය කිරීමට ඔබට ඉඩ සලසන අගයන් භාවිතා කරන්න. CGRectContainsRectඑක් උදාහරණයක්

  5. අවශ්‍ය නම්, අවහිරතා අර්ථ දැක්වීමට සහභාගී වන දර්ශනයක් හා සම්බන්ධ පිරිසැලසුම් ආන්තිකයන් භාවිතා කිරීමට පසුබට නොවන්න let viewMargins = self.webview.layoutMarginsGuide: උදාහරණයක් ලෙස
  6. ඔබට කළ යුතු වැඩ නොකරන්න, කතන්දර පුවරුවේ ඇති සීමාවන් සහිත සියලුම දර්ශන වලට දේපල ස්වයං අවහිරතා ඇත. View.ameName.constraints
  7. ඕනෑම බාධාවක් සඳහා ඔබේ ප්‍රමුඛතා 1000 ට අඩු කරන්න. මම කතන්දර පුවරුවේ මගේ 250 (අඩු) හෝ 750 (ඉහළ) ලෙස සකසා ඇත; (ඔබ කේතයේ ඇති ඕනෑම දෙයකට ප්‍රමුඛතාවය 1000 ක් වෙනස් කිරීමට උත්සාහ කළහොත් 1000 ක් අවශ්‍ය බැවින් යෙදුම බිඳ වැටෙනු ඇත)
  8. සක්‍රීය කොන්ස්ට්‍රයින්ට්ස් සහ අක්‍රිය කිරීමේ කොන්ක්‍රීට් භාවිතා කිරීමට වහාම උත්සාහ නොකිරීම ගැන සලකා බලන්න (ඒවාට ඒවායේ ස්ථානයක් ඇත, නමුත් ඉගෙන ගන්නා විට හෝ ඔබ මේවා භාවිතා කරමින් කතන්දර පුවරුවක් භාවිතා කරන්නේ නම් බොහෝ විට එයින් අදහස් කරන්නේ ඔබ ඕනෑවට වඩා වැඩ කිරීමයි ~ පහත දැක්වෙන පරිදි ඔවුන්ට ස්ථානයක් ඇත)
  9. ඔබ කේතයේ නව බාධකයක් සැබවින්ම එකතු කරන්නේ නම් මිස addConstraints / removeConstraints භාවිතා නොකිරීමට සලකා බලන්න. බොහෝ විට මම කතන්දර පුවරුවේ අදහස් අපේක්ෂිත බාධක සහිතව (දර්ශනය ඕෆ්ස්ක්‍රීන් මත තැබීම) සැකසූ බව මට පෙනී ගියේය, ඉන්පසු කේතයෙන්, දර්ශනය වටා ගමන් කිරීම සඳහා කතන්දර පුවරුවේ කලින් නිර්මාණය කර ඇති බාධක සජීවීකරණය කරමි.
  10. නව NSAnchorLayout පන්තිය සහ උප පංති සමඟ බාධක ගොඩ නැගීමට මම බොහෝ කාලයක් නාස්ති කළෙමි. මේවා ඉතා හොඳින් ක්‍රියාත්මක වන නමුත් මට අවශ්‍ය සියලු අවහිරතා දැනටමත් කතන්දර පුවරුවේ පවතින බව වටහා ගැනීමට මට යම් කාලයක් ගත විය. ඔබ කේතයේ සීමාවන් ගොඩනඟන්නේ නම්, ඔබේ අවහිරතා සමනය කිරීමට මෙම ක්‍රමය භාවිතා කරන්න:

කතන්දර පුවරු භාවිතා කරන විට 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
        }

    }

ස්වයංක්‍රීය සැකසුම් මාර්ගෝපදේශයේ ස්නිපටය (දෙවන ස්නිපටය OS X භාවිතා කිරීම සඳහා බව සලකන්න). BTW - මෙය මට පෙනෙන පරිදි වර්තමාන මාර්ගෝපදේශයේ තවදුරටත් නොමැත. කැමති තාක්ෂණික ක්‍රම අඛණ්ඩව විකාශනය වෙමින් පවතී.

ස්වයංක්‍රීය පිරිසැලසුම මඟින් සිදුකරන වෙනස්කම් සජීවිකරණය කිරීම

ස්වයංක්‍රීය පිරිසැලසුම මගින් සිදුකරන සජීවිකරණ වෙනස්කම් පිළිබඳ පූර්ණ පාලනයක් ඔබට අවශ්‍ය නම්, ඔබ ඔබේ බාධක ක්‍රමලේඛන වෙනස් කළ යුතුය. මූලික සංකල්පය iOS සහ OS X යන දෙකටම සමාන වේ, නමුත් සුළු වෙනස්කම් කිහිපයක් තිබේ.

IOS යෙදුමක, ඔබගේ කේතය පහත දැක්වෙන ආකාරයට පෙනේ:

[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
}];

OS X හි, ස්ථර-පිටුබලය සහිත සජීවිකරණ භාවිතා කරන විට පහත කේතය භාවිතා කරන්න:

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

ඔබ ස්ථර-පිටුබලය සහිත සජීවිකරණ භාවිතා නොකරන විට, අවහිරතා සජීවිකරණය භාවිතා කරමින් නියතය සජීවීකරණය කළ යුතුය:

[[constraint animator] setConstant:42];

දෘශ්‍යමය වශයෙන් වඩා හොඳින් ඉගෙන ගන්නා අය සඳහා ඇපල් වෙතින් මෙම මුල් වීඩියෝව බලන්න .

සමීප අවධානයට

බොහෝ විට ලියකියවිලි වල කුඩා සටහන් හෝ කේත කැබලි විශාල අදහස් වලට තුඩු දෙයි. උදාහරණයක් ලෙස ගතික සජීවිකරණ යන්ත්‍ර සඳහා ස්වයංක්‍රීය පිරිසැලසුම් සීමාවන් ඇමිණීම විශාල අදහසකි.

සුභ පැතුම් සහ බලවේගය ඔබ සමඟ වේවා.



7

ක්‍රියාකාරී විසඳුම 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දෙයක් සඳහාම දර්ශක තිබීමයි.

මම GitHub හි උදාහරණයක් නිර්මාණය කළෙමි .


4

Xcode 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)

Self.calendarViewHeight යනු අභිරුචි දර්ශනයක් (CalendarView) වෙත යොමු කරන ලද බාධකයක් බව මතක තබා ගන්න. මම .layoutIfNeeded () යන්න self.view සහ self.calendarView මත නොවේ

මෙම උපකාරය බලාපොරොත්තු වේ.


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 ක ප්‍රමාදයක් සහිත සරල ඩිස්පැච්_ඇෆ්ට් බ්ලොක් එකක් එක් කිරීමෙන් සෑම විටම සජීවිකරණය ක්‍රියාත්මක විය - පැනීම නැත.

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.