Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>If you're using auto layout, then I don't see how manually setting position will serve in the long run because eventually auto layout will clobber the position value you've set when it calculates its own layout.</p> <p>Rather, what's needed is to modify the layout constraints themselves to compensate for the changes produced by setting the anchorPoint. The following function does that for untransformed views.</p> <pre><code>/** Set the anchorPoint of view without changing is perceived position. @param view view whose anchorPoint we will mutate @param anchorPoint new anchorPoint of the view in unit coords (e.g., {0.5,1.0}) @param xConstraint an NSLayoutConstraint whose constant property adjust's view x.center @param yConstraint an NSLayoutConstraint whose constant property adjust's view y.center As multiple constraints can contribute to determining a view's center, the user of this function must specify which constraint they want modified in order to compensate for the modification in anchorPoint */ void SetViewAnchorPointMotionlesslyUpdatingConstraints(UIView * view,CGPoint anchorPoint, NSLayoutConstraint * xConstraint, NSLayoutConstraint * yConstraint) { // assert: old and new anchorPoint are in view's unit coords CGPoint const oldAnchorPoint = view.layer.anchorPoint; CGPoint const newAnchorPoint = anchorPoint; // Calculate anchorPoints in view's absolute coords CGPoint const oldPoint = CGPointMake(view.bounds.size.width * oldAnchorPoint.x, view.bounds.size.height * oldAnchorPoint.y); CGPoint const newPoint = CGPointMake(view.bounds.size.width * newAnchorPoint.x, view.bounds.size.height * newAnchorPoint.y); // Calculate the delta between the anchorPoints CGPoint const delta = CGPointMake(newPoint.x-oldPoint.x, newPoint.y-oldPoint.y); // get the x &amp; y constraints constants which were contributing to the current // view's position, and whose constant properties we will tweak to adjust its position CGFloat const oldXConstraintConstant = xConstraint.constant; CGFloat const oldYConstraintConstant = yConstraint.constant; // calculate new values for the x &amp; y constraints, from the delta in anchorPoint // when autolayout recalculates the layout from the modified constraints, // it will set a new view.center that compensates for the affect of the anchorPoint CGFloat const newXConstraintConstant = oldXConstraintConstant + delta.x; CGFloat const newYConstraintConstant = oldYConstraintConstant + delta.y; view.layer.anchorPoint = newAnchorPoint; xConstraint.constant = newXConstraintConstant; yConstraint.constant = newYConstraintConstant; [view setNeedsLayout]; } </code></pre> <p>I admit this is probably not everything you were hoping for, since usually the only reason you'd want to modify the anchorPoint is to set a transform. That would require a more complex function that updates the layout constraints to reflect <em>all</em> the frame changes that could be caused by the transform property itself. This is tricky because transforms can do a lot to the frame. A scaling or rotation transform would make the frame bigger, so we'd need to update any width or height constraints, etc..</p> <p>If you're only using the transform for a temporary animation, then what's above may suffice since I don't believe auto layout will prevent the in-flight animation from presenting images that represent purely transient violations of the constraints.</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload