I want to drag resizable UIView from its corner?
Like on desktop we Click the mouse button and hold on click and drag the mouse then a transparent view is visible like this.
I want this in my Project in iPhone. I want when the user touch and drag the finger one resizable transparent view will visible.
I have done so far on click on button the view is visible and that is resizable also. But it is not my solution, I want on touch on any iphone screen the resizable UIView will come.
Any Idea and suggestions would be highly welcome.
This is my code what I have done so far:
- (void)viewDidLoad
{
tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleTap:)];
tap.numberOfTapsRequired = 1;
[imageVw addGestureRecognizer:tap];
tap.delegate=self;
pan=[[UIPanGestureRecognizer alloc]initWithTarget:self action:#selector(panAction:)];
[pan setMinimumNumberOfTouches:1];
[pan setMaximumNumberOfTouches:2];
[pan setDelegate:self];
count=0;
// [pan minimumNumberOfTouches:1];
// [pan maximumNumberOfTouches:2];
[imageVw addGestureRecognizer:pan];
}
-(void)handleTap:(UIPanGestureRecognizer *)gestureRecognizer
{
userResizableView = [[SPUserResizableView alloc] init];
userResizableView.frame = CGRectMake(x,y,w,h);
//UIView *content_View = [[UIView alloc] initWithFrame:userResizableView.bounds];
//[content_View setBackgroundColor:[UIColor whiteColor]];
imageVw1 = [[UIImageView alloc]initWithFrame:userResizableView.bounds];
//imageVw1.image = [UIImage imageNamed:#"redacted2.jpg"];
imageVw1.backgroundColor = [UIColor blackColor];
imageVw1.userInteractionEnabled=YES;
imageVw1.autoresizesSubviews = YES;
imageVw1.alpha = 0.13; // for opacity
userResizableView.contentView = imageVw1;
//[content_View addSubview:imageVw1];
//userResizableView.contentView = content_View;
userResizableView.delegate = self;
[userResizableView showEditingHandles];
currentlyEditingView = userResizableView;
lastEditedView = userResizableView;
// [self.view addSubview:userResizableView];
// [imageVw addSubview: dview];
[self.view addSubview: userResizableView];
[userResizableView release];
}
- (void)userResizableViewDidBeginEditing:(SPUserResizableView *)userResizableView1 {
width = userResizableView.frame.size.width;
height = userResizableView.frame.size.height;
width1 = width;
height1 = height;
width = width + width;
height = height + height;
[currentlyEditingView hideEditingHandles];
currentlyEditingView = userResizableView1;
}
- (void)userResizableViewDidEndEditing:(SPUserResizableView *)userResizableView1 {
lastEditedView = userResizableView1;
x1 = x;
y1 = y;
x = userResizableView.frame.origin.x;
y = userResizableView.frame.origin.y;
}
First you have to declare two global variables
CGPoint startPoint;
BOOL _shouldResize;
Then you have to override two touch event methods in your view as given
1.TouchesBegan
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
CGPoint touchPoint = [[touches anyObject] locationInView:[self superview]];
/*
Here you have to check user tap to the corner of your view by using the method
CGRectContainsPoint(CGRect rect, touchPoint);
Here the parameter rect should be the corner of your view
if(!CGRectContainsPoint(CGRect rect, touchPoint)) { // Here user did not tap in your specific rect. so no need of resizing
_shouldResize = NO;
return;
}
*/
_shouldResize = YES;
startPoint = touchPoint;
}
2.TouchesMoved
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
if(!_shouldResize)
return;
CGPoint touchPoint = [[touches anyObject] locationInView:[self superview]];
CGFloat displacementX = touchPoint.x - startPoint.x;
CGFloat displacementY = touchPoint.y - startPoint.y;
startPoint.x = touchPoint.x;
startPoint.y = touchPoint.y;
CGRect frame = [self frame];
frame.size.width += displacementX;
frame.size.height += displacementY;
[self setFrame:frame];
}
Hope this will help you :)
Related
I am doing a project in which i need two imageviews in single Scrollview with zooming options. UIScrollView allows one view to make zoom easily. But my problem is not like that. I have two imageviews side by side in the scroll view.When I try to zoom the images its not working Is there is any option to zoom two image views at the same time.Please suggest me some idea.
Thanks in advance
Here is code for Zooming two images in single scrollview
I have added two UIImageView's in One UIView and then I have added the UIView to UIScrollView. Following is my code :
- (void)viewDidLoad {
[super viewDidLoad];
self.vwImages = [[UIView alloc]initWithFrame:CGRectMake(0, 0,100,200)];
// 1
UIImage *image = [UIImage imageNamed:#"imgBaskteBall2.jpeg"];
UIImageView *imageView1 = [[UIImageView alloc] initWithImage:image];
imageView1.frame = CGRectMake(0,0,100,100);
[self.vwImages addSubview:imageView1];
UIImage *image2 = [UIImage imageNamed:#"imgBaskteBall1.jpeg"];
UIImageView *imageView2 = [[UIImageView alloc] initWithImage:image2];
imageView2.frame = CGRectMake(0, 100, 100, 100);
[self.vwImages addSubview:imageView2];
// 2
[self.scrollView addSubview:self.vwImages];
self.scrollView.contentSize = self.vwImages.frame.size;
// 3
UITapGestureRecognizer *doubleTapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(scrollViewDoubleTapped:)];
doubleTapRecognizer.numberOfTapsRequired = 2;
doubleTapRecognizer.numberOfTouchesRequired = 1;
[self.scrollView addGestureRecognizer:doubleTapRecognizer];
UITapGestureRecognizer *twoFingerTapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(scrollViewTwoFingerTapped:)];
twoFingerTapRecognizer.numberOfTapsRequired = 1;
twoFingerTapRecognizer.numberOfTouchesRequired = 2;
[self.scrollView addGestureRecognizer:twoFingerTapRecognizer];
}
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
// 4
CGRect scrollViewFrame = self.scrollView.frame;
CGFloat scaleWidth = scrollViewFrame.size.width / self.scrollView.contentSize.width;
CGFloat scaleHeight = scrollViewFrame.size.height / self.scrollView.contentSize.height;
CGFloat minScale = MIN(scaleWidth, scaleHeight);
self.scrollView.minimumZoomScale = minScale;
// 5
self.scrollView.maximumZoomScale = 10.0f;
self.scrollView.zoomScale = minScale;
// 6
[self centerScrollViewContents];
}
- (void)centerScrollViewContents {
CGSize boundsSize = self.scrollView.bounds.size;
CGRect contentsFrame = self.vwImages.frame;
if (contentsFrame.size.width < boundsSize.width) {
contentsFrame.origin.x = (boundsSize.width - contentsFrame.size.width) / 2.0f;
} else {
contentsFrame.origin.x = 0.0f;
}
if (contentsFrame.size.height < boundsSize.height) {
contentsFrame.origin.y = (boundsSize.height - contentsFrame.size.height) / 2.0f;
} else {
contentsFrame.origin.y = 0.0f;
}
self.vwImages.frame = contentsFrame;
}
- (void)scrollViewDoubleTapped:(UITapGestureRecognizer*)recognizer {
// 1
CGPoint pointInView = [recognizer locationInView:self.imageView];
// 2
CGFloat newZoomScale = self.scrollView.zoomScale * 1.5f;
newZoomScale = MIN(newZoomScale, self.scrollView.maximumZoomScale);
// 3
CGSize scrollViewSize = self.scrollView.bounds.size;
CGFloat w = scrollViewSize.width / newZoomScale;
CGFloat h = scrollViewSize.height / newZoomScale;
CGFloat x = pointInView.x - (w / 2.0f);
CGFloat y = pointInView.y - (h / 2.0f);
CGRect rectToZoomTo = CGRectMake(x, y, w, h);
// 4
[self.scrollView zoomToRect:rectToZoomTo animated:YES];
}
- (void)scrollViewTwoFingerTapped:(UITapGestureRecognizer*)recognizer {
// Zoom out slightly, capping at the minimum zoom scale specified by the scroll view
CGFloat newZoomScale = self.scrollView.zoomScale / 1.5f;
newZoomScale = MAX(newZoomScale, self.scrollView.minimumZoomScale);
[self.scrollView setZoomScale:newZoomScale animated:YES];
}
- (UIView*)viewForZoomingInScrollView:(UIScrollView *)scrollView {
// Return the view that you want to zoom
return self.vwImages;
}
- (void)scrollViewDidZoom:(UIScrollView *)scrollView {
// The scroll view has zoomed, so you need to re-center the contents
[self centerScrollViewContents];
}
Make object of UIView as container for example viewContainer
[viewContainer addSubView:imageView1];
[viewContainer addSubView:imageView2];
[scrollView addSubView:viewContainer];
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView
{
return viewContainer;
}
Add
You can use this
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView
{
return [self.scrollView.subviews objectAtIndex:0];
}
the viewForZoomingInScrollView delegate method return the object at Index 0.
From Properly zooming a UIScrollView that contains many subviews
add both the imageView in the view and replace this method
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView
{
return view;
}
I've got a view on screen with a UIImageView inside it. The user can pan, scale, and rotate.
I have a rotation gesture setup, and everything is fine with rotation except for when rotating the image moves off the screen/out of the view.
Any idea what would cause this to behavior? The expected behavior I'm looking for is when you rotate the image it does not move at all (other than rotating).
I've tried setting an anchor point of the layer of the parent view, but it doesn't seem to be helping any.
EDIT: I've put some logging on the rotation gesture and what's happening is the image views center (X) is what is getting off hence it going off the screen.
Why would this coordinate change upon rotation? The Y is staying the same. I've even tried turning the other gestures off and it's definitely something whacky with the rotation gesture.
Code Below:
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
CALayer *l = [self.viewCase layer];
[l setMasksToBounds:YES];
[l setCornerRadius:30.0];
self.imgUserPhoto.userInteractionEnabled = YES;
[self.imgUserPhoto setClipsToBounds:NO];
UIPanGestureRecognizer *panRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:#selector(panDetected:)];
panRecognizer.maximumNumberOfTouches = 1;
[self.view addGestureRecognizer:panRecognizer];
UIPinchGestureRecognizer *pinchRecognizer = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:#selector(pinchDetected:)];
[self.view addGestureRecognizer:pinchRecognizer];
UIRotationGestureRecognizer *rotationRecognizer = [[UIRotationGestureRecognizer alloc] initWithTarget:self action:#selector(rotationDetected:)];
[self.view addGestureRecognizer:rotationRecognizer];
UITapGestureRecognizer *tapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(tapDetected:)];
tapRecognizer.numberOfTapsRequired = 2;
[self.view addGestureRecognizer:tapRecognizer];
panRecognizer.delegate = self;
pinchRecognizer.delegate = self;
rotationRecognizer.delegate = self;
}
- (void)panDetected:(UIPanGestureRecognizer *)panRecognizer
{
CGPoint translation = [panRecognizer translationInView:self.view];
CGPoint imageViewPosition = self.imageView.center;
imageViewPosition.x += translation.x;
imageViewPosition.y += translation.y;
self.imageView.center = imageViewPosition;
[panRecognizer setTranslation:CGPointZero inView:self.view];
}
- (void)pinchDetected:(UIPinchGestureRecognizer *)pinchRecognizer
{
CGFloat scale = pinchRecognizer.scale;
self.imageView.transform = CGAffineTransformScale(self.imageView.transform, scale, scale);
pinchRecognizer.scale = 1.0;
}
- (void)rotationDetected:(UIRotationGestureRecognizer *)rotationRecognizer
{
CGFloat angle = rotationRecognizer.rotation;
self.imageView.transform = CGAffineTransformRotate(self.imageView.transform, angle);
rotationRecognizer.rotation = 0.0;
}
- (void)tapDetected:(UITapGestureRecognizer *)tapRecognizer
{
[UIView animateWithDuration:0.25 animations:^{
self.imageView.center = CGPointMake(CGRectGetMidX(self.view.bounds), CGRectGetMidY(self.view.bounds));
self.imageView.transform = CGAffineTransformIdentity;
}];
}
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
return YES;
}
Maybe because the pan gesture is also getting called : try setting the maximumNumberOfTouches to 1 on your UIPanGestureRecognizer
Sorry for bad title :(
I've a controller that has a scrollview where I display some other views, in this case an IngredientImage, that is a subclass of uiimageview:
#import "IngredientImage.h"
#implementation IngredientImage
- (id) initWithImage:(UIImage *)image {
if (self = [super initWithImage:image]) {
}
[self setUserInteractionEnabled:YES];
return self;
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
CGPoint location = [[touches anyObject] locationInView:self];
if (CGRectContainsPoint([self frame], location)) {
NSLog(#"This works...");
}
}
- (void)dealloc {
[super dealloc];
}
#end
and there is the code that puts the views in the scrollview
- (void)viewDidLoad {
[super viewDidLoad];
[self addIngredients];
}
- (void)addIngredients {
NSUInteger i;
for (i = 1; i <= 10; i++) {
UIImage *image = [UIImage imageNamed:#"ing.png"];
IngredientImage *imageView = [[IngredientImage alloc] initWithImage:image];
// setup each frame to a default height and width, it will be properly placed when we call "updateScrollList"
CGRect rect = imageView.frame;
rect.size.height = 50;
rect.size.width = 50;
imageView.frame = rect;
imageView.tag = i; // tag our images for later use when we place them in serial fashion
[ingredientsView addSubview:imageView];
[imageView release];
[image release];
}
UIImageView *view = nil;
NSArray *subviews = [ingredientsView subviews];
// reposition all image subviews in a horizontal serial fashion
CGFloat curYLoc = INGREDIENT_PADDING;
for (view in subviews) {
if ([view isKindOfClass:[IngredientImage class]] && view.tag > 0) {
CGRect frame = view.frame;
frame.origin = CGPointMake(INGREDIENT_PADDING, curYLoc);
view.frame = frame;
curYLoc += (INGREDIENT_PADDING + INGREDIENT_HEIGHT);
}
}
// set the content size so it can be scrollable
[ingredientsView setContentSize:CGSizeMake([ingredientsView bounds].size.width, (10 * (INGREDIENT_PADDING + INGREDIENT_HEIGHT)))];
}
the problem is that only the first view handles the touch event, and I don't know why :(
Can you help me?
Thanks
When you call
CGPoint location = [[touches anyObject] locationInView:self];
you are setting location with respect to the bounds of your imageView. But then in your if statement,
if (CGRectContainsPoint([self frame], location))
you are asking if the location is within your frame. But frame and bounds are different. Frame gives coordinates relative to your superview; bounds gives it relative to the view itself.
To fix this, change your if statement to read
if (CGRectContainsPoint([self bounds], location))
Now you are consistently using the same coordinate system in both calls, and your problem should go away.
I have been playing around with one of the iPhone examples from Apple' web site (ScrollViewSuite) . I am trying to tweak it a bit so that when I rotate the the iPad the image will fit into the screen in landscape mode vertical. I have been successful in getting the image to rotate, but the image is larger than the height of the landscape screen, so the bottom is below the screen. I would like to image to scale to the height of the landscape screen.
I have been playing around with various autoSizingMask attributes without success.
The imageView is called "zoomView" this is the actual image which loads into a scrollView called imageScrollView.
I am trying to achieve the screen to rotate and look like this.... sorry only 1 link allowed new user :(
olsonvox.com/photos/correct.png
However, this is what My screen is looking like.
http://www.olsonvox.com/photos/incorrect.png
I would really appreciate some advice or guidance. Below is the RootViewController.m for the project.
Blade
#
import "RootViewController.h"
#define ZOOM_VIEW_TAG 100
#define ZOOM_STEP 1.5
#define THUMB_HEIGHT 150
#define THUMB_V_PADDING 25
#define THUMB_H_PADDING 25
#define CREDIT_LABEL_HEIGHT 25
#define AUTOSCROLL_THRESHOLD 30
#interface RootViewController (ViewHandlingMethods)
- (void)toggleThumbView;
- (void)pickImageNamed:(NSString *)name;
- (NSArray *)imageNames;
- (void)createThumbScrollViewIfNecessary;
- (void)createSlideUpViewIfNecessary;
#end
#interface RootViewController (AutoscrollingMethods)
- (void)maybeAutoscrollForThumb:(ThumbImageView *)thumb;
- (void)autoscrollTimerFired:(NSTimer *)timer;
- (void)legalizeAutoscrollDistance;
- (float)autoscrollDistanceForProximityToEdge:(float)proximity;
#end
#interface RootViewController (UtilityMethods)
- (CGRect)zoomRectForScale:(float)scale withCenter:(CGPoint)center;
#end
#implementation RootViewController
- (void)loadView {
[super loadView];
imageScrollView = [[UIScrollView alloc] initWithFrame:[[self view]bounds]];
// this code makes the image resize to the width and height properly.
imageScrollView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin| UIViewAutoresizingFlexibleBottomMargin| UIViewAutoresizingFlexibleBottomMargin;
// TRY SETTNG CENTER HERE SOMEHOW>....
[imageScrollView setBackgroundColor:[UIColor blackColor]];
[imageScrollView setDelegate:self];
[imageScrollView setBouncesZoom:YES];
[[self view] addSubview:imageScrollView];
[self toggleThumbView];
// intitializes with the first image.
[self pickImageNamed:#"lookbook1"];
}
- (void)dealloc {
[imageScrollView release];
[slideUpView release];
[thumbScrollView release];
[super dealloc];
}
#pragma mark UIScrollViewDelegate methods
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView {
UIView *view = nil;
if (scrollView == imageScrollView) {
view = [imageScrollView viewWithTag:ZOOM_VIEW_TAG];
}
return view;
}
/************************************** NOTE **************************************/
/* The following delegate method works around a known bug in zoomToRect:animated: */
/* In the next release after 3.0 this workaround will no longer be necessary */
/**********************************************************************************/
- (void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(float)scale {
[scrollView setZoomScale:scale+0.01 animated:NO];
[scrollView setZoomScale:scale animated:NO];
}
#pragma mark TapDetectingImageViewDelegate methods
- (void)tapDetectingImageView:(TapDetectingImageView *)view gotSingleTapAtPoint:(CGPoint)tapPoint {
// Single tap shows or hides drawer of thumbnails.
[self toggleThumbView];
}
- (void)tapDetectingImageView:(TapDetectingImageView *)view gotDoubleTapAtPoint:(CGPoint)tapPoint {
// double tap zooms in
float newScale = [imageScrollView zoomScale] * ZOOM_STEP;
CGRect zoomRect = [self zoomRectForScale:newScale withCenter:tapPoint];
[imageScrollView zoomToRect:zoomRect animated:YES];
}
- (void)tapDetectingImageView:(TapDetectingImageView *)view gotTwoFingerTapAtPoint:(CGPoint)tapPoint {
// two-finger tap zooms out
float newScale = [imageScrollView zoomScale] / ZOOM_STEP;
CGRect zoomRect = [self zoomRectForScale:newScale withCenter:tapPoint];
[imageScrollView zoomToRect:zoomRect animated:YES];
}
#pragma mark ThumbImageViewDelegate methods
- (void)thumbImageViewWasTapped:(ThumbImageView *)tiv {
[self pickImageNamed:[tiv imageName]];
[self toggleThumbView];
}
- (void)thumbImageViewStartedTracking:(ThumbImageView *)tiv {
[thumbScrollView bringSubviewToFront:tiv];
}
// CONTROLS DRAGGING AND DROPPING THUMBNAILS...
- (void)thumbImageViewMoved:(ThumbImageView *)draggingThumb {
// check if we've moved close enough to an edge to autoscroll, or far enough away to stop autoscrolling
[self maybeAutoscrollForThumb:draggingThumb];
/* The rest of this method handles the reordering of thumbnails in the thumbScrollView. See */
/* ThumbImageView.h and ThumbImageView.m for more information about how this works. */
// we'll reorder only if the thumb is overlapping the scroll view
if (CGRectIntersectsRect([draggingThumb frame], [thumbScrollView bounds])) {
BOOL draggingRight = [draggingThumb frame].origin.x > [draggingThumb home].origin.x ? YES : NO;
/* we're going to shift over all the thumbs who live between the home of the moving thumb */
/* and the current touch location. A thumb counts as living in this area if the midpoint */
/* of its home is contained in the area. */
NSMutableArray *thumbsToShift = [[NSMutableArray alloc] init];
// get the touch location in the coordinate system of the scroll view
CGPoint touchLocation = [draggingThumb convertPoint:[draggingThumb touchLocation] toView:thumbScrollView];
// calculate minimum and maximum boundaries of the affected area
float minX = draggingRight ? CGRectGetMaxX([draggingThumb home]) : touchLocation.x;
float maxX = draggingRight ? touchLocation.x : CGRectGetMinX([draggingThumb home]);
// iterate through thumbnails and see which ones need to move over
for (ThumbImageView *thumb in [thumbScrollView subviews]) {
// skip the thumb being dragged
if (thumb == draggingThumb) continue;
// skip non-thumb subviews of the scroll view (such as the scroll indicators)
if (! [thumb isMemberOfClass:[ThumbImageView class]]) continue;
float thumbMidpoint = CGRectGetMidX([thumb home]);
if (thumbMidpoint >= minX && thumbMidpoint <= maxX) {
[thumbsToShift addObject:thumb];
}
}
// shift over the other thumbs to make room for the dragging thumb. (if we're dragging right, they shift to the left)
float otherThumbShift = ([draggingThumb home].size.width + THUMB_H_PADDING) * (draggingRight ? -1 : 1);
// as we shift over the other thumbs, we'll calculate how much the dragging thumb's home is going to move
float draggingThumbShift = 0.0;
// send each of the shifting thumbs to its new home
for (ThumbImageView *otherThumb in thumbsToShift) {
CGRect home = [otherThumb home];
home.origin.x += otherThumbShift;
[otherThumb setHome:home];
[otherThumb goHome];
draggingThumbShift += ([otherThumb frame].size.width + THUMB_H_PADDING) * (draggingRight ? 1 : -1);
}
// change the home of the dragging thumb, but don't send it there because it's still being dragged
CGRect home = [draggingThumb home];
home.origin.x += draggingThumbShift;
[draggingThumb setHome:home];
}
}
- (void)thumbImageViewStoppedTracking:(ThumbImageView *)tiv {
// if the user lets go of the thumb image view, stop autoscrolling
[autoscrollTimer invalidate];
autoscrollTimer = nil;
}
#pragma mark Autoscrolling methods
- (void)maybeAutoscrollForThumb:(ThumbImageView *)thumb {
autoscrollDistance = 0;
// only autoscroll if the thumb is overlapping the thumbScrollView
if (CGRectIntersectsRect([thumb frame], [thumbScrollView bounds])) {
CGPoint touchLocation = [thumb convertPoint:[thumb touchLocation] toView:thumbScrollView];
float distanceFromLeftEdge = touchLocation.x - CGRectGetMinX([thumbScrollView bounds]);
float distanceFromRightEdge = CGRectGetMaxX([thumbScrollView bounds]) - touchLocation.x;
if (distanceFromLeftEdge < AUTOSCROLL_THRESHOLD) {
autoscrollDistance = [self autoscrollDistanceForProximityToEdge:distanceFromLeftEdge] * -1; // if scrolling left, distance is negative
} else if (distanceFromRightEdge < AUTOSCROLL_THRESHOLD) {
autoscrollDistance = [self autoscrollDistanceForProximityToEdge:distanceFromRightEdge];
}
}
// if no autoscrolling, stop and clear timer
if (autoscrollDistance == 0) {
[autoscrollTimer invalidate];
autoscrollTimer = nil;
}
// otherwise create and start timer (if we don't already have a timer going)
else if (autoscrollTimer == nil) {
autoscrollTimer = [NSTimer scheduledTimerWithTimeInterval:(1.0 / 60.0)
target:self
selector:#selector(autoscrollTimerFired:)
userInfo:thumb
repeats:YES];
}
}
- (float)autoscrollDistanceForProximityToEdge:(float)proximity {
// the scroll distance grows as the proximity to the edge decreases, so that moving the thumb
// further over results in faster scrolling.
return ceilf((AUTOSCROLL_THRESHOLD - proximity) / 5.0);
}
- (void)legalizeAutoscrollDistance {
// makes sure the autoscroll distance won't result in scrolling past the content of the scroll view
float minimumLegalDistance = [thumbScrollView contentOffset].x * -1;
float maximumLegalDistance = [thumbScrollView contentSize].width - ([thumbScrollView frame].size.width + [thumbScrollView contentOffset].x);
autoscrollDistance = MAX(autoscrollDistance, minimumLegalDistance);
autoscrollDistance = MIN(autoscrollDistance, maximumLegalDistance);
}
- (void)autoscrollTimerFired:(NSTimer*)timer {
[self legalizeAutoscrollDistance];
// autoscroll by changing content offset
CGPoint contentOffset = [thumbScrollView contentOffset];
contentOffset.x += autoscrollDistance;
[thumbScrollView setContentOffset:contentOffset];
// adjust thumb position so it appears to stay still
ThumbImageView *thumb = (ThumbImageView *)[timer userInfo];
[thumb moveByOffset:CGPointMake(autoscrollDistance, 0)];
}
#pragma mark View handling methods
- (void)toggleThumbView {
[self createSlideUpViewIfNecessary]; // no-op if slideUpView has already been created
CGRect frame = [slideUpView frame];
if (thumbViewShowing) {
frame.origin.y = 0;
} else {
frame.origin.y = -225;
}
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.3];
[slideUpView setFrame:frame];
[UIView commitAnimations];
thumbViewShowing = !thumbViewShowing;
}
- (void)pickImageNamed:(NSString *)name {
// first remove previous image view, if any
[[imageScrollView viewWithTag:ZOOM_VIEW_TAG] removeFromSuperview];
UIImage *image = [UIImage imageNamed:[NSString stringWithFormat:#"%#.jpg", name]];
TapDetectingImageView *zoomView = [[TapDetectingImageView alloc] initWithImage:image];
zoomView.autoresizingMask = UIViewAutoresizingFlexibleWidth ;
[zoomView setDelegate:self];
[zoomView setTag:ZOOM_VIEW_TAG];
[imageScrollView addSubview:zoomView];
[imageScrollView setContentSize:[zoomView frame].size];
[zoomView release];
// choose minimum scale so image width fits screen
float minScale = [imageScrollView frame].size.width / [zoomView frame].size.width;
[imageScrollView setMinimumZoomScale:minScale];
[imageScrollView setZoomScale:minScale];
[imageScrollView setContentOffset:CGPointZero];
}
- (NSArray *)imageNames {
// the filenames are stored in a plist in the app bundle, so create array by reading this plist
NSString *path = [[NSBundle mainBundle] pathForResource:#"Images" ofType:#"plist"];
NSData *plistData = [NSData dataWithContentsOfFile:path];
NSString *error; NSPropertyListFormat format;
NSArray *imageNames = [NSPropertyListSerialization propertyListFromData:plistData
mutabilityOption:NSPropertyListImmutable
format:&format
errorDescription:&error];
if (!imageNames) {
NSLog(#"Failed to read image names. Error: %#", error);
[error release];
}
return imageNames;
}
- (void)createSlideUpViewIfNecessary {
if (!slideUpView) {
[self createThumbScrollViewIfNecessary];
CGRect bounds = [[self view] bounds];
float thumbHeight = [thumbScrollView frame].size.height;
float labelHeight = CREDIT_LABEL_HEIGHT;
// create label giving credit for images
UILabel *creditLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, thumbHeight, bounds.size.width, labelHeight)];
[creditLabel setBackgroundColor:[UIColor clearColor]];
[creditLabel setTextColor:[UIColor whiteColor]];
// [creditLabel setFont:[UIFont fontWithName:#"Helvetica" size:16]];
// [creditLabel setText:#"SAMPLE TEXT"];
[creditLabel setTextAlignment:UITextAlignmentCenter];
// create container view that will hold scroll view and label
CGRect frame = CGRectMake(0.0, -225.00, bounds.size.width+256, thumbHeight + labelHeight);
slideUpView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleTopMargin;
slideUpView = [[UIView alloc] initWithFrame:frame];
[slideUpView setBackgroundColor:[UIColor blackColor]];
[slideUpView setOpaque:NO];
[slideUpView setAlpha:.75];
[[self view] addSubview:slideUpView];
// add subviews to container view
[slideUpView addSubview:thumbScrollView];
[slideUpView addSubview:creditLabel];
[creditLabel release];
}
}
- (void)createThumbScrollViewIfNecessary {
if (!thumbScrollView) {
float scrollViewHeight = THUMB_HEIGHT + THUMB_V_PADDING;
float scrollViewWidth = [[self view] bounds].size.width;
thumbScrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, scrollViewWidth, scrollViewHeight)];
[thumbScrollView setCanCancelContentTouches:NO];
[thumbScrollView setClipsToBounds:NO];
// now place all the thumb views as subviews of the scroll view
// and in the course of doing so calculate the content width
float xPosition = THUMB_H_PADDING;
for (NSString *name in [self imageNames]) {
UIImage *thumbImage = [UIImage imageNamed:[NSString stringWithFormat:#"%#_thumb.jpg", name]];
if (thumbImage) {
ThumbImageView *thumbView = [[ThumbImageView alloc] initWithImage:thumbImage];
[thumbView setDelegate:self];
[thumbView setImageName:name];
CGRect frame = [thumbView frame];
frame.origin.y = THUMB_V_PADDING;
frame.origin.x = xPosition;
[thumbView setFrame:frame];
[thumbView setHome:frame];
[thumbScrollView addSubview:thumbView];
[thumbView release];
xPosition += (frame.size.width + THUMB_H_PADDING);
}
}
[thumbScrollView setContentSize:CGSizeMake(xPosition, scrollViewHeight)];
}
}
#pragma mark Utility methods
- (CGRect)zoomRectForScale:(float)scale withCenter:(CGPoint)center {
CGRect zoomRect;
// the zoom rect is in the content view's coordinates.
// At a zoom scale of 1.0, it would be the size of the imageScrollView's bounds.
// As the zoom scale decreases, so more content is visible, the size of the rect grows.
zoomRect.size.height = [imageScrollView frame].size.height / scale;
zoomRect.size.width = [imageScrollView frame].size.width / scale;
// choose an origin so as to get the right center.
zoomRect.origin.x = center.x - (zoomRect.size.width / 2.0);
zoomRect.origin.y = center.y - (zoomRect.size.height / 2.0);
return zoomRect;
}
#pragma mark -
#pragma mark Rotation support
// Ensure that the view controller supports rotation and that the split view can therefore show in both portrait and landscape.
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
return YES;
}
#end
If you've set up your UIScrollView in a Nib file, make sure it is resizing properly when rotated (Use the Autosizing controls in the Size Inspector in Interface Builder: Both sets of arrows inside the box should be red)
Then use this to rescale when the iPad changes orientation:
- (void)willAnimateSecondHalfOfRotationFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation duration:(NSTimeInterval)duration{
//if your UIImageView is called zoomView use this
CGRect zoomRect=CGRectMake(0,0,zoomView.frame.size.width, zoomView.frame.size.height);
[scrollView zoomToRect:zoomRect animated:YES];}
(Sorry about the bad placement of the {} but it wasn't pasting properly as code for some reason)
Hope this helps!
This is my code, i'm trying to drag and drop a card which will animate on touchesBegan, but the animationImages are larger than the initial card image before touches begin.
How can i change the UIImageView to accomdate the animateImages sizes?
cardAnimationArray is an array with 19 images xxx1.png, xxx2.png... which have various sizes.
cardMovedImage is the last image in the series of 19 images.
Thank you in advance!!
- (void) touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event {
CGPoint pt = [[touches anyObject] locationInView:self.superview];
self.center = pt;
self.animationImages = [NSArray arrayWithArray:cardAnimationArray];
[cardAnimationArray release];
[self setAnimationRepeatCount:1];
self.animationDuration= 1;
[self startAnimating];
self.image = [UIImage imageNamed:cardMovedImageName];
}
- (void) touchesMoved:(NSSet*)touches withEvent:(UIEvent*)event {
CGPoint pt = [[touches anyObject] locationInView:self.superview];
CGRect frame = [self frame];
frame.origin.x += pt.x - self.center.x;
frame.origin.y += pt.y - self.center.y;
[self setFrame: frame];
}
self.clipsToBounds = NO; is the solution
Set the scale mode to "Center"
Haha, there is actually a simple solution;
just set self.clipsToBounds = NO;
where self represents the UIImageView