Setting the Min and Max width and height for resizable UIView - ios

I wanted to make a resizable UIView using touches from corners, and I've found this answer here and it worked well. But how can I add the ability to stop resizing when the width/height is 200 for example?
This is the code:
CGFloat kResizeThumbSize = 45.0f;
#interface MY_CLASS_NAME : UIView {
BOOL isResizingLR;
BOOL isResizingUL;
BOOL isResizingUR;
BOOL isResizingLL;
CGPoint touchStart;
}
And..
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [[event allTouches] anyObject];
touchStart = [[touches anyObject] locationInView:self];
isResizingLR = (self.bounds.size.width - touchStart.x < kResizeThumbSize && self.bounds.size.height - touchStart.y < kResizeThumbSize);
isResizingUL = (touchStart.x <kResizeThumbSize && touchStart.y <kResizeThumbSize);
isResizingUR = (self.bounds.size.width-touchStart.x < kResizeThumbSize && touchStart.y<kResizeThumbSize);
isResizingLL = (touchStart.x <kResizeThumbSize && self.bounds.size.height -touchStart.y <kResizeThumbSize);
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
CGPoint touchPoint = [[touches anyObject] locationInView:self];
CGPoint previous = [[touches anyObject] previousLocationInView:self];
CGFloat deltaWidth = touchPoint.x - previous.x;
CGFloat deltaHeight = touchPoint.y - previous.y;
// get the frame values so we can calculate changes below
CGFloat x = self.frame.origin.x;
CGFloat y = self.frame.origin.y;
CGFloat width = self.frame.size.width;
CGFloat height = self.frame.size.height;
if (isResizingLR) {
self.frame = CGRectMake(x, y, touchPoint.x+deltaWidth, touchPoint.y+deltaWidth);
} else if (isResizingUL) {
self.frame = CGRectMake(x+deltaWidth, y+deltaHeight, width-deltaWidth, height-deltaHeight);
} else if (isResizingUR) {
self.frame = CGRectMake(x, y+deltaHeight, width+deltaWidth, height-deltaHeight);
} else if (isResizingLL) {
self.frame = CGRectMake(x+deltaWidth, y, width-deltaWidth, height+deltaHeight);
} else {
// not dragging from a corner -- move the view
self.center = CGPointMake(self.center.x + touchPoint.x - touchStart.x,
self.center.y + touchPoint.y - touchStart.y);
}
}
Thanks

if (isResizingLR) {
if(touchPoint.x+deltaWidth < 200 && touchPoint.y+deltaWidth < 200)
self.frame = CGRectMake(x, y, touchPoint.x+deltaWidth, touchPoint.y+deltaWidth);
} else if (isResizingUL) {
if(width-deltaWidth < 200 && height-deltaHeight < 200)
self.frame = CGRectMake(x+deltaWidth, y+deltaHeight, width-deltaWidth, height-deltaHeight);
} else if (isResizingUR) {
if(width+deltaWidth < 200 && height-deltaHeight < 200)
self.frame = CGRectMake(x, y+deltaHeight, width+deltaWidth, height-deltaHeight);
} else if (isResizingLL) {
if(width-deltaWidth < 200 && height+deltaHeight < 200)
self.frame = CGRectMake(x+deltaWidth, y, width-deltaWidth, height+deltaHeight);
}
This should work.

#property(nonatomic) CGRect frame
Description The frame rectangle, which describes the view’s location and size in its superview’s coordinate system.
Before setting self.frame with CGRect, check for width and height!
CGRect CGRectMake(CGFloat x, CGFloat y, CGFloat width, CGFloat height);
Use width and height for actual size and delta for transformation.

Related

touchesmoved screen bounds, how can I restrict the movement of the rect out of the screen bounds

I'am trying to restrict the movement of the rect by the screen bounds. The logic is simple, you tap inside the rect (doesn't metter where) and drag it. It follows your finger, and it has to be stoped when the border of the rect reached the bounds of the screen.
- (void)viewDidLoad {
[super viewDidLoad];
rect.backgroundColor = [UIColor redColor];
}
then I try to figure out where the tap is and if its inside the rect I change the color of the rect
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
//NSLog(#"%s", __PRETTY_FUNCTION__);
UITouch *touch = touches.anyObject;
if (touch.view == rect) {
rect.backgroundColor = [UIColor greenColor];
isSelectedRect = YES;
CGPoint point = [touch locationInView:self.view];
CGPoint center = rect.center;
delta = CGPointMake(point.x - center.x,
point.y - center.y);
} else {
rect.backgroundColor = [UIColor redColor];
isSelectedRect = NO;
}
}
after that I move this rect
- (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
//NSLog(#"%s", __PRETTY_FUNCTION__);
if (isSelectedRect) {
UITouch *touch = touches.anyObject;
CGPoint point = [touch locationInView:self.view];
rect.center = CGPointMake(point.x - delta.x,
point.y - delta.y);
}
}
Eventualy, I need to write one line of the code which will limit the movement the rect by bounds of the screeen. I and it would be perfect to make it with ternary operator. I would appreciate any help.
Replace your touchesMoved method with the code below. Hope it can help you ;)
- (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
//NSLog(#"%s", __PRETTY_FUNCTION__);
if (isSelectedRect) {
UITouch *touch = touches.anyObject;
CGPoint point = [touch locationInView:self.view];
CGPoint newCenter = CGPointMake(point.x - delta.x,
point.y - delta.y);
CGFloat rectHeight = rect.frame.size.height;
CGFloat rectWidth = rect.frame.size.width;
CGFloat screenWidth = self.view.frame.size.width;
CGFloat screenHeight = self.view.frame.size.height;
if (newCenter.x + rectWidth / 2 > screenWidth) {
newCenter.x = screenWidth - rectWidth / 2;
}
if (newCenter.x - rectWidth / 2 < 0) {
newCenter.x = rectWidth / 2;
}
if (newCenter.y + rectHeight / 2 > screenHeight) {
newCenter.y = screenHeight - rectHeight / 2;
}
if (newCenter.y - rectHeight / 2 >= 0) {
newCenter.y = rectHeight / 2;
}
rect.center = newCenter;
}
}
if (CGRectContainsPoint(boundsRect, point)) {
rect.center = CGPointMake(point.x - delta.x,
point.y - delta.y);
}
Here, boundsRect will be the Rectangle of device.
You have to note that the point which you are moving in touchesMoved function is the center point of the view. In order to restrict them from going outside the viewBounds you must check whether the bounds of the draggable view is exceeding your translation point.
to get the actual bounds
CGPoint center = rect.center;
CGSize size = rect.size
CGRect originalRect = CGRectMake(center.x - size.width/2, center.y - size.height/2, size.width, size.height);
Now check whether the given rect is within the desired rect.
if (CGRectContainsRect(boundsRect, originalRect)) {
// Here change the center of the view
}
I Hope this helps.

how dragged image with a min and max value?

I have this code for increase height of a image.
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
UITouch *touch = [[event allTouches] anyObject];
touchStart = [[touches anyObject] locationInView:self.image];
touchStart2 = [[touches anyObject] locationInView:self.tableView];
isResizingLR = ( self.image.bounds.size.height - touchStart.y < kResizeThumbSize );
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{
CGPoint touchPoint = [[touches anyObject] locationInView:self.image];
CGPoint previous=[[touches anyObject]previousLocationInView:self.image];
float deltaWidth = touchPoint.x-previous.x;
float deltaHeight = touchPoint.y-previous.y;
if (isResizingLR) {
self.image.frame = CGRectMake(self.image.frame.origin.x, self.image.frame.origin.y, self.image.frame.size.width, touchPoint.y + deltaWidth);
self.tableView.frame = CGRectMake(self.tableView.frame.origin.x ,self.tableView.frame.origin.y + deltaHeight, self.tableView.frame.size.width, self.tableView.frame.size.height - deltaHeight );
self.viewTitle.frame = CGRectMake(self.viewTitle.frame.origin.x ,self.viewTitle.frame.origin.y + deltaHeight, self.viewTitle.frame.size.width, self.viewTitle.frame.size.height);
}
}
I want put a condition for a minimHeight =100 and maximHeight =300;
How can i do that?
I already try this :
if (isResizingLR) {
if (self.image.frame.size.height >100 && self.image.frame.size.height <300) {
self.image.frame = CGRectMake(self.image.frame.origin.x, self.image.frame.origin.y, self.image.frame.size.width, touchPoint.y + deltaWidth);
self.tableView.frame = CGRectMake(self.tableView.frame.origin.x ,self.tableView.frame.origin.y + deltaHeight, self.tableView.frame.size.width, self.tableView.frame.size.height - deltaHeight );
self.viewTitle.frame = CGRectMake(self.viewTitle.frame.origin.x ,self.viewTitle.frame.origin.y + deltaHeight, self.viewTitle.frame.size.width, self.viewTitle.frame.size.height);
}
}
but every time after dragged image at: self.image.frame.size.height =100 or 300, i can't resize image. He need to be draggable all time!
Thank you!
EDIT:
I don't want resize image when heightImage is 100.
My original height of image is 200. My user can click and resize image how he want, but no over 300 and less than 100. I just put a minimum and maximum height. I hope you understand now.
Have you try to test <= and >=?
if (self.image.frame.size.height >= 100 && self.image.frame.size.height <= 300) {
//...
}
I solved the problem.
int aux=touchPoint.y + deltaWidth;
if (aux>300) {
aux=300;
}
else if(aux<100){
aux=100;
}
self.image.frame = CGRectMake(self.image.frame.origin.x, self.image.frame.origin.y, self.image.frame.size.width, aux);

xcode resize and position coordinates

I would like my code (ipad app) to handle resizing of an image by touching it.
I am little confused with how xcode handle points coordinates.
I wrote my code considering that the origin of a frame (frame.origin) is located at the top left (as I read it somewhere), that touches location is the coordinates of the finger touching the screen and that the positive directions are left (x) and up (y). If I am wrong somewhere there that would explain why my code isn't working properly.
Here is my code:
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
CGFloat kResizeThumbSize = 45.0f;
touchStart = [[touches anyObject] locationInView:self.view];
CGFloat xO = _ImageView.frame.origin.x;
CGFloat yO = _ImageView.frame.origin.y;
CGFloat width = _ImageView.frame.size.width;
CGFloat height = _ImageView.frame.size.height;
isResizingUD = (xO - kResizeThumbSize < touchStart.x < xO + width + kResizeThumbSize &&
(yO - kResizeThumbSize < touchStart.y < yO + kResizeThumbSize ||
yO - height - kResizeThumbSize < touchStart.y < yO - height + kResizeThumbSize) );
isResizingLR = (yO + kResizeThumbSize < touchStart.x < xO + width - kResizeThumbSize &&
(xO - kResizeThumbSize < touchStart.x < xO + kResizeThumbSize ||
xO - width - kResizeThumbSize < touchStart.x < xO - width + kResizeThumbSize));
}
//moving the image
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
CGPoint touchPoint = [[touches anyObject] locationInView:self.view];
CGPoint previous = [[touches anyObject] previousLocationInView:self.view];
CGFloat deltaWidth = touchPoint.x - previous.x;
CGFloat deltaHeight = touchPoint.y - previous.y;
// get the frame values so we can calculate changes below
CGFloat x = _ImageView.frame.origin.x;
CGFloat y = _ImageView.frame.origin.y;
CGFloat width = _ImageView.frame.size.width;
CGFloat height = _ImageView.frame.size.height;
if (isResizingLR) {
_ImageView.frame = CGRectMake(x, y, width+deltaWidth, height);
} else if (isResizingUD) {
_ImageView.frame = CGRectMake(x, y, width, height+deltaHeight);
} else {
// not dragging from a corner -- move the view
_ImageView.center = CGPointMake(self.view.center.x + touchPoint.x - touchStart.x,
self.view.center.y + touchPoint.y - touchStart.y);
}
}
I would expect the image to be resize in the up/down direction only if the user touch the bottom or the top of the image within kResizeThumbSize (which actually, I am not sure of the unit it is expressed in) and in the right/left direction if the user touch the left or right border of the image within kResizeThumbSize. Unfortunately, what's happen is that the image can be resize in the right/left direction only and wherever I put my finger, it will be resized.
Any help would be greatly welcome.
Fixed!
For anyone needing help for this, I post my code.
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
CGFloat kResizeThumbSize = 10.0f;
touchStart = [[touches anyObject] locationInView:self.view];
CGFloat xO = _ImageView.frame.origin.x;
CGFloat yO = _ImageView.frame.origin.y;
CGFloat width = _ImageView.frame.size.width;
CGFloat height = _ImageView.frame.size.height;
isResizingUD = (xO - kResizeThumbSize < touchStart.x &&
touchStart.x < xO + width + kResizeThumbSize &&
yO + height - kResizeThumbSize < touchStart.y);
isResizingLR = (yO + kResizeThumbSize < touchStart.y &&
touchStart.y< yO + height - kResizeThumbSize &&
xO + width - kResizeThumbSize < touchStart.x);
isMoving = (xO+kResizeThumbSize< touchStart.x &&
touchStart.x < xO + width - kResizeThumbSize &&
yO + kResizeThumbSize < touchStart.y &&
touchStart.y< yO + height - kResizeThumbSize);
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
CGPoint touchPoint = [[touches anyObject] locationInView:self.view];
CGPoint previous = [[touches anyObject] previousLocationInView:self.view];
CGFloat deltaWidth = touchPoint.x - previous.x;
CGFloat deltaHeight = touchPoint.y - previous.y;
// get the frame values so we can calculate changes below
CGFloat x = _ImageView.frame.origin.x;
CGFloat y = _ImageView.frame.origin.y;
CGFloat width = _ImageView.frame.size.width;
CGFloat height = _ImageView.frame.size.height;
if (isResizingUD) {
_ImageView.frame = CGRectMake(x, y, width, height+deltaHeight);
} else if (isResizingLR) {
_ImageView.frame = CGRectMake(x, y, width+deltaWidth, height);
} else if (isMoving) {
// not dragging from a corner -- move the view
_ImageView.frame = CGRectMake(x+deltaWidth, y+deltaHeight, width, height);
}
}

Wrong touch point location in UIView after rotatation

I'm trying to make a custom button using a UIView and when touched on a specific part of the view perform an action, for example when touching the left part of the view log LEFT and when touching the Right part of the view log RIGHT.
I'm using touchesBegan and touchesEnded to detect touch.
Everything works fine when in portrait mode, however, once rotated to landscape mode it doesn't work, the view is displayed in the right place and the touch on the view is detected but it seems the touch point is not in the correct x,y coordinates so I can't detect the LEFT/RIGHT touches correctly.
Couldn't find any previous answers here that helped me.
Tried looking into CGAffineTransform, but still can't fix it.
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
self.backgroundColor = [[UIColor alloc] initWithPatternImage:[UIImage imageNamed:#"round_directions_button_default.png"]];
self.autoresizingMask = UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleTopMargin;
topLeft = CGPointMake(self.frame.origin.x, self.frame.origin.y);
topRight = CGPointMake(self.frame.origin.x + 105, self.frame.origin.y);
bottomLeft = CGPointMake(self.frame.origin.x, self.frame.origin.y + 105);
bottomRight = CGPointMake(self.frame.origin.x + 105, self.frame.origin.y + 105);
NSLog(#"topLeft: x = %f, y = %f", topLeft.x, topLeft.y);
NSLog(#"topRight: x = %f, y = %f", topRight.x, topRight.y);
NSLog(#"bottomLeft: x = %f, y = %f", bottomLeft.x, bottomLeft.y);
NSLog(#"bottomRight: x = %f, y = %f", bottomRight.x, bottomRight.y);
NSLog(#"self.center: x = %f, y = %f", self.center.x, self.center.y);
}
return self;
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
NSLog(#"topLeft: x = %f, y = %f", topLeft.x, topLeft.y);
NSLog(#"topRight: x = %f, y = %f", topRight.x, topRight.y);
NSLog(#"bottomLeft: x = %f, y = %f", bottomLeft.x, bottomLeft.y);
NSLog(#"bottomRight: x = %f, y = %f", bottomRight.x, bottomRight.y);
NSLog(#"self.center: x = %f, y = %f", self.center.x, self.center.y);
UITouch *touch = [touches anyObject];
CGPoint touchPoint = [touch locationInView:nil];
NSLog(#"touchesBegan: touchPoint: x = %f, y = %f", touchPoint.x, touchPoint.y);
if ([self isPoint:touchPoint inTriangle:topLeft :self.center :topRight]) {
NSLog(#"touchesBegan: UP");
direction = 1;
self.backgroundColor = [[UIColor alloc] initWithPatternImage:[UIImage imageNamed:#"round_directions_button_pressed_up.png"]];
} else if ([self isPoint:touchPoint inTriangle:bottomLeft :self.center :bottomRight]) {
NSLog(#"touchesBegan: DOWN");
direction = 2;
self.backgroundColor = [[UIColor alloc] initWithPatternImage:[UIImage imageNamed:#"round_directions_button_pressed_down.png"]];
} else if ([self isPoint:touchPoint inTriangle:topLeft :self.center :bottomLeft]) {
NSLog(#"touchesBegan: LEFT");
direction = 3;
self.backgroundColor = [[UIColor alloc] initWithPatternImage:[UIImage imageNamed:#"round_directions_button_pressed_left.png"]];
} else if ([self isPoint:touchPoint inTriangle:topRight :self.center :bottomRight]) {
NSLog(#"touchesBegan: RIGHT");
direction = 4;
self.backgroundColor = [[UIColor alloc] initWithPatternImage:[UIImage imageNamed:#"round_directions_button_pressed_right.png"]];
} else {
NSLog(#"touchesBegan: NOTHING");
}
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
self.backgroundColor = [[UIColor alloc] initWithPatternImage:[UIImage imageNamed:#"round_directions_button_default.png"]];
}
- (BOOL) isPoint:(CGPoint)point inTriangle:(CGPoint)v1 :(CGPoint)v2 :(CGPoint)v3 {
BOOL b1, b2, b3;
b1 = ((point.x - v2.x) * (v1.y - v2.y) - (v1.x - v2.x) * (point.y - v2.y)) < 0.0f;
b2 = ((point.x - v3.x) * (v2.y - v3.y) - (v2.x - v3.x) * (point.y - v3.y)) < 0.0f;
b3 = ((point.x - v1.x) * (v3.y - v1.y) - (v3.x - v1.x) * (point.y - v1.y)) < 0.0f;
return ((b1 == b2) && (b2 == b3));
}
in view controller viewDidLoad:
CustomButton *customButton = [[CustomButton alloc] initWithFrame:CGRectMake(1, self.view.bounds.size.height - 106, 105, 105)];
[self.view addSubview:customButton];
Any help will be appreciated.
Thanks
If the size of the button doesn't change with rotation you can set points just once inside initWithFrame and use bounds instead of frame.
topLeft = CGPointMake(0, 0);
topRight = CGPointMake(self.bounds.size.width, 0);
bottomLeft = CGPointMake(0, self.bounds.size.height);
bottomRight = CGPointMake(self.bounds.size.width, self.bounds.size.height);
Then in touchesBegan use [touch locationInView:self]; to get the touch location in the button own coordinate system.
If the size changes, a solution can be to recalculate points on every touch so place the above code inside touchesBegan.
EDIT:
If you want to use local button coordinate you have to calculate the center because self.center contains center point of the view in the superview’s coordinate system.

UIScrollView zoomed with subviews gets different position after back from background

All,
I have a viewController with a ScrollView. On this scrollView, I have a UIImage as subview.
UIImage *image = [UIImage imageNamed:#"greyblue_numbered_15x15_900x900.png"];
self.boardImage = [[UIImageView alloc] initWithImage:image];
self.boardImage.frame = (CGRect){.origin=CGPointMake(0.0f, 0.0f), .size=image.size};
[self.boardScrollView addSubview:self.boardImage];
self.boardScrollView.contentSize = image.size;
When I zoom, use home button and then call app again, everything is fine.
Now, I place an other subview on it by dragging the object to the scrollView:
- (void)myTouchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
CGPoint touchPointScreen = [[touches anyObject] locationInView:self.view];
CGPoint touchPointImage = [[touches anyObject] locationInView:self.boardImage];
if (touchPointScreen.x > self.boardScrollView.frame.origin.x &&
touchPointScreen.x < self.boardScrollView.frame.origin.x + self.boardScrollView.frame.size.width &&
touchPointScreen.y > self.boardScrollView.frame.origin.y &&
touchPointScreen.y < self.boardScrollView.frame.origin.y + self.boardScrollView.frame.size.height)
{
self.tmpDragObject.frame = CGRectMake(x,y,60,60);
[self.boardImage addSubview:self.tmpDragObject];
}
self.tmpDragObject = nil;
}
When I zoom, the subviews are also zoomed.
- (void)scrollViewDoubleTapped:(UITapGestureRecognizer*)recognizer {
CGPoint pointInView = [recognizer locationInView:self.boardScrollView];
CGFloat newZoomScale = self.boardScrollView.zoomScale * 1.5f;
newZoomScale = MIN(newZoomScale, self.boardScrollView.maximumZoomScale);
if (newZoomScale != 1.0f) {
CGSize scrollViewSize = self.boardScrollView.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);
[self.boardScrollView zoomToRect:rectToZoomTo animated:YES];
}
ISSUE: When I use the home button and then call the app again, the app repositions the subviews of the ScrollView. So all subviews are replaced downwards, about the size of the tmpDragObject or the size of the navigation bar.
Why is this happening? And how can I fix this?
Apparently, I had to set the automaticallyAdjustsScrollViewInsets on my view controller to NO.

Resources