Reputation: 121
I'm working on a document viewer. The document is displayed inside a UIScrollView
so that it can be scrolled and zoomed. I need to draw a border around the document in order to separate it visually from the background of the UIScrollView
. The border must not be zoomed together with the document -- it should maintain a constant thickness regardless of the zoom scale.
My current setup consists of a UIScrollView
with two UIView
children -- one for the document, and one for the border. I've overriden viewForZoomingInScrollView
: to return the document view. I've also overridden layoutSubviews
to center the document view (in case it's smaller than the UIScrollView
) and then resize and position the border view behind it so that it looks like a frame. This works OK when the user is scrolling and zooming manually. But when I use zoomToRect:animated:
to zoom programatically, layoutSubviews is called before the animation starts and my border view gets resized immediately with the document view catching up a bit later.
Clarification: The border needs to be tightly fitting around the document view and not around the UIScrollView
itself.
Upvotes: 2
Views: 5345
Reputation: 121
Finally, I was able to fix the problem with animated zooming. My setup is the same as described in the question. I just added some code to my layoutSubview
implementation in order to detect any running UIScrollView
animation and match it with a similar animation for resizing the border.
Here is the code:
- (void)layoutSubviews
{
[super layoutSubviews];
// _pageView displays the document
// _borderView represents the border around it
. . .
// _pageView is now centered -- we have to move/resize _borderView
// layers backing a view are not implicitly animated
// the following two lines work just fine if we don't need animation
_borderView.layer.bounds = CGRectMake(0.0, 0.0, frameToCenter.size.width + 2.0 * 15.0, frameToCenter.size.height + 2.0 * 15.0);
_borderView.layer.position = _pageView.center;
if (_pageView.layer.animationKeys.count > 0)
{
// UIScrollView is animating its content (_pageView)
// so we need to setup a matching animation for _borderView
[CATransaction begin];
CAAnimation *animation = [_pageView.layer animationForKey:[_pageView.layer.animationKeys lastObject]];
CFTimeInterval beginTime = animation.beginTime;
CFTimeInterval duration = animation.duration;
if (beginTime != 0.0) // 0.0 means the animation starts now
{
CFTimeInterval currentTime = [_pageView.layer convertTime:CACurrentMediaTime() fromLayer:nil];
duration = MAX(beginTime + duration - currentTime, 0.0);
}
[CATransaction setAnimationDuration:duration];
[CATransaction setAnimationTimingFunction:animation.timingFunction];
// calculate the initial state for _borderView animation from _pageView presentation layer
CGPoint presentationPos = [_pageView.layer.presentationLayer position];
CGRect presentationBounds = [_pageView.layer.presentationLayer frame];
presentationBounds.origin = CGPointZero;
presentationBounds.size.width += 2.0 * 15.0;
presentationBounds.size.height += 2.0 * 15.0;
CABasicAnimation *boundsAnim = [CABasicAnimation animationWithKeyPath:@"bounds"];
boundsAnim.fromValue = [NSValue valueWithCGRect:presentationBounds];
boundsAnim.toValue = [NSValue valueWithCGRect:_borderView.layer.bounds];
[_borderView.layer addAnimation:boundsAnim forKey:@"bounds"];
CABasicAnimation *posAnim = [CABasicAnimation animationWithKeyPath:@"position"];
posAnim.fromValue = [NSValue valueWithCGPoint:presentationPos];
posAnim.toValue = [NSValue valueWithCGPoint:_borderView.layer.position];
[_borderView.layer addAnimation:posAnim forKey:@"position"];
[CATransaction commit];
}
}
It looks hacky but it works. I wish I didn't have to reverse engineer UIScrollView
in order to make a simple border look good during animation...
Upvotes: 1
Reputation: 27225
Sample Code :
yourScrollView.layer.cornerRadius=8.0f;
yourScrollView.layer.masksToBounds=YES;
yourScrollView.layer.borderColor=[[UIColor redColor]CGColor];
yourScrollView.layer.borderWidth= 1.0f;
Don't Forget : #Import <QuartzCore/QuartzCore.h>
Upvotes: 3
Reputation: 896
First you need to Import QuartzCore framework to your App. then import that .h file on which class where you want to set the border. like this.
#import <QuartzCore/QuartzCore.h>
Setup for Border.
ScrollView.layer.cornerRadius=5.0f;
ScrollView.layer.masksToBounds=YES;
ScrollView.layer.borderColor=[[UIColor redColor]CGColor];
ScrollView.layer.borderWidth= 4.0f;
check this one really helpful to you.
Upvotes: 1
Reputation: 4934
Import QuartzCore framework:
#import <QuartzCore/QuartzCore.h>
Now Add color to its view:
[scrollViewObj.layer setBorderColor:[[UIColor redColor] CGColor]];
[scrollViewObj.layer setBorderWidth:2.0f];
Upvotes: 0