Reputation: 5201
i am trying to crate a dynamic rectangle on imageview. it means rectangle should start on the touch and as long as user move the touch it should be bigger in that direction. friend suggest me, please.
Upvotes: 1
Views: 1339
Reputation: 1427
You can create imageview programmatically and resize its frame as touch moves. See below link may it help you.
How can I draw dynamic rectangle on screen according to touchMove event on iOS
Upvotes: 0
Reputation: 11598
It sounds like maybe you want a selection rectangle on top of the UIImage, not just the ability to resize the image.
If that's the case, I'd recommend the following structure:
In my experience, animations of this nature are easier to make functional when using shocks and struts and -touchesBegan, etc, as opposed to Autolayout and UIGestureRecognizers, but YMMV.
Of course, what you're doing might require some advanced math, based on how you answer questions like the following:
The following code does the following:
Assumptions made by the code:
Possible updates needed by this code:
#define GRAB_DISTANCE 10
#define VIEW_PLACEMENT_ANIMATION_DURATION 0.1
#define VIEW_SIZING_ANIMATION_DURATION 0.1
typedef enum {
kMSSLineTypeDashed,
kMSSLineTypeSolid
} MSSLineType;
typedef enum {
kMSSRectangleGrabZoneBottom,
kMSSRectangleGrabZoneBottomLeft,
kMSSRectangleGrabZoneBottomRight,
kMSSRectangleGrabZoneLeft,
kMSSRectangleGrabZoneNone,
kMSSRectangleGrabZoneRight,
kMSSRectangleGrabZoneTop,
kMSSRectangleGrabZoneTopLeft,
kMSSRectangleGrabZoneTopRight
} MSSRectangleGrabZone;
typedef enum {
kMSSRectangleStatusNone,
kMSSRectangleStatusPlacement,
kMSSRectangleStatusResizing
} MSSRectangleStatus;
@interface MSSSelectionView : UIView
@property (assign, nonatomic) MSSLineType currentLineType;
@property (strong, nonatomic) UIColor *borderColor;
@end
@implementation MSSSelectionView
- (void)awakeFromNib {
[super awakeFromNib];
self.currentLineType = kMSSLineTypeSolid;
}
- (void)drawRect:(CGRect)rect {
// Just make a border, 2 points wide, 1 point inset (so it is all contained by the view)
CGContextRef context = UIGraphicsGetCurrentContext();
CGRect borderRect = CGRectInset(rect, 1, 1);
CGContextSetLineCap(context, kCGLineCapRound);
CGContextSetLineWidth(context, 2.0f);
switch (self.currentLineType) {
case kMSSLineTypeDashed:
{
CGFloat lengths[2] = {3, 4};
CGContextSetLineDash(context, 0.0f, lengths, 2);
}
break;
case kMSSLineTypeSolid:
{
CGContextSetLineDash(context, 0.0f, NULL, 0);
}
break;
default:
break;
}
[self.borderColor setStroke];
CGContextStrokeRect(context, borderRect);
}
@end
#import "MSSViewController.h"
@interface MSSViewController ()
@property (assign, nonatomic) BOOL selectionIsVisible;
@property (assign, nonatomic) MSSRectangleGrabZone currentGrabZone;
@property (assign, nonatomic) MSSRectangleStatus currentStatus;
@property (strong, nonatomic) IBOutlet MSSSelectionView *selectionView;
@property (strong, nonatomic) IBOutlet UIImageView *imageView;
@end
@implementation MSSViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.imageView.image = [UIImage imageNamed:@"image.jpg"];
self.currentGrabZone = kMSSRectangleGrabZoneNone;
self.currentStatus = kMSSRectangleStatusNone;
}
#pragma mark - Touch Handling
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
// Get a touch object (assuming just a 1-finger touch here)
UITouch *touch = [touches anyObject];
CGPoint location = [touch locationInView:self.view];
if (self.selectionIsVisible == NO) {
// Showing the selection view for the first time
// Update instance property
self.selectionIsVisible = YES;
// Place the rectangle (centered around touch)
self.selectionView.center = location;
// Unhide the rectangle
self.selectionView.hidden = NO;
// Set the status flag to placement
self.currentStatus = kMSSRectangleStatusPlacement;
// Change the border color to indicate that it's active
self.selectionView.borderColor = [UIColor lightGrayColor];
self.selectionView.currentLineType = kMSSLineTypeDashed;
[self.selectionView setNeedsDisplay];
} else {
// Selection view already visible, so first make sure the touch was inside the selection view
if (CGRectContainsPoint(self.selectionView.frame, location)) {
// The touch was inside the selection view, so update the selection view's line drawing properties
self.selectionView.borderColor = [UIColor lightGrayColor];
self.selectionView.currentLineType = kMSSLineTypeDashed;
[self.selectionView setNeedsDisplay];
// Set status flag based on proximity to edge
BOOL edgeGrabbed = [self location:location inGrabZoneForRect:self.selectionView.frame];
if (edgeGrabbed == YES) {
// The user has grabbed the edge, so allow selection view resizing
self.currentStatus = kMSSRectangleStatusResizing;
self.currentGrabZone = [self zoneGrabbedForPoint:location inRect:self.selectionView.frame];
} else {
// The user has touched the interior, so allow selection view movement/placement
self.currentStatus = kMSSRectangleStatusPlacement;
self.currentGrabZone = kMSSRectangleGrabZoneNone;
}
}
}
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
// Get a touch object (assuming just a 1-finger touch here)
UITouch *touch = [touches anyObject];
CGPoint currentLocation = [touch locationInView:self.view];
CGPoint previousLocation = [touch previousLocationInView:self.view];
CGFloat xDelta = currentLocation.x - previousLocation.x;
CGFloat yDelta = currentLocation.y - previousLocation.y;
CGRect frame = self.selectionView.frame;
switch (self.currentStatus) {
case kMSSRectangleStatusNone:
// Do nothing
break;
case kMSSRectangleStatusPlacement:
{
// The entire selection view should be moved under the user's finger
frame.origin.x = frame.origin.x + xDelta;
frame.origin.y = frame.origin.y + yDelta;
}
break;
case kMSSRectangleStatusResizing:
{
switch (self.currentGrabZone) {
case kMSSRectangleGrabZoneBottom:
{
// Make the view's frame taller or shorter based on yDelta
frame.size.height = frame.size.height + yDelta;
}
break;
case kMSSRectangleGrabZoneBottomLeft:
{
// Make the view's frame taller or shorter based on yDelta
// Make the view's frame wider or narrower PLUS move origin based on xDelta
frame.origin.x = frame.origin.x + xDelta;
frame.size.height = frame.size.height + yDelta;
frame.size.width = frame.size.width - xDelta;
}
break;
case kMSSRectangleGrabZoneBottomRight:
{
// Make the view's frame taller or shorter based on yDelta
// Make the view's frame wider or narrower based on xDelta
frame.size.height = frame.size.height + yDelta;
frame.size.width = frame.size.width + xDelta;
}
break;
case kMSSRectangleGrabZoneLeft:
{
// Make the view's frame wider or narrower PLUS move origin based on xDelta
frame.origin.x = frame.origin.x + xDelta;
frame.size.width = frame.size.width - xDelta;
}
break;
case kMSSRectangleGrabZoneNone:
// Do nothing
break;
case kMSSRectangleGrabZoneRight:
{
// Make the view's frame wider or narrower based on xDelta
frame.size.width = frame.size.width + xDelta;
}
break;
case kMSSRectangleGrabZoneTop:
{
// Make the view's frame taller or shorter PLUS move origin based on yDelta
frame.origin.y = frame.origin.y + yDelta;
frame.size.height = frame.size.height - yDelta;
}
break;
case kMSSRectangleGrabZoneTopLeft:
{
// Make the view's frame wider or narrower PLUS move origin based on xDelta
// Make the view's frame taller or shorter PLUS move origin based on yDelta
frame.origin.x = frame.origin.x + xDelta;
frame.origin.y = frame.origin.y + yDelta;
frame.size.width = frame.size.width - xDelta;
frame.size.height = frame.size.height - yDelta;
}
break;
case kMSSRectangleGrabZoneTopRight:
{
// Make the view's frame wider or narrower based on xDelta
// Make the view's frame taller or shorter PLUS move origin based on yDelta
frame.origin.y = frame.origin.y + yDelta;
frame.size.height = frame.size.height - yDelta;
frame.size.width = frame.size.width + xDelta;
}
break;
default:
break;
}
}
break;
default:
break;
}
// Any frame changes made above should be animated here
[UIView animateWithDuration:VIEW_PLACEMENT_ANIMATION_DURATION
animations:^{
self.selectionView.frame = frame;
}
completion:^(BOOL finished) {
[self.selectionView setNeedsDisplay];
}
];
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
// Nothing much to do, just make the border black to indicate activity is done
self.currentGrabZone = kMSSRectangleGrabZoneNone;
self.currentStatus = kMSSRectangleStatusNone;
self.selectionView.borderColor = [UIColor blackColor];
self.selectionView.currentLineType = kMSSLineTypeSolid;
[self.selectionView setNeedsDisplay];
}
#pragma mark - Rectangle helper methods
- (BOOL)location:(CGPoint)location inGrabZoneForRect:(CGRect)rect {
if (CGRectContainsPoint(rect, location)) {
// The point is inside the rectangle, so determine if it's in the grab zone or the interior
CGRect nonGrabZoneRect = CGRectInset(rect, GRAB_DISTANCE, GRAB_DISTANCE);
if (CGRectContainsPoint(nonGrabZoneRect, location)) {
// This point is in the interior (non-grab zone)
return NO;
} else {
// This point is in the grab zone
return YES;
}
} else {
// The point is not inside the rectangle, which means they didn't grab the edge/border
return NO;
}
}
- (MSSRectangleGrabZone)zoneGrabbedForPoint:(CGPoint)point inRect:(CGRect)rect {
CGRect topLeftGrabZone = CGRectMake(rect.origin.x, rect.origin.y, GRAB_DISTANCE, GRAB_DISTANCE);
CGRect topGrabZone = CGRectMake(rect.origin.x + GRAB_DISTANCE, rect.origin.y, rect.size.width - (2 * GRAB_DISTANCE), GRAB_DISTANCE);
CGRect topRightGrabZone = CGRectMake(rect.origin.x + rect.size.width - GRAB_DISTANCE, rect.origin.y, GRAB_DISTANCE, GRAB_DISTANCE);
CGRect leftGrabZone = CGRectMake(rect.origin.x, rect.origin.y + GRAB_DISTANCE, GRAB_DISTANCE, rect.size.height - (2 * GRAB_DISTANCE));
CGRect rightGrabZone = CGRectMake(rect.origin.x + rect.size.width - GRAB_DISTANCE, rect.origin.y + GRAB_DISTANCE, GRAB_DISTANCE, rect.size.height - (2 * GRAB_DISTANCE));
CGRect bottomLeftGrabZone = CGRectMake(rect.origin.x, rect.origin.y + rect.size.height - GRAB_DISTANCE, GRAB_DISTANCE, GRAB_DISTANCE);
CGRect bottomGrabZone = CGRectMake(rect.origin.x + GRAB_DISTANCE, rect.origin.y + rect.size.height - GRAB_DISTANCE, rect.size.width - (2 * GRAB_DISTANCE), GRAB_DISTANCE);
CGRect bottomRightGrabZone = CGRectMake(rect.origin.x + rect.size.width - GRAB_DISTANCE, rect.origin.y + rect.size.height - GRAB_DISTANCE, GRAB_DISTANCE, GRAB_DISTANCE);
if (CGRectContainsPoint(topLeftGrabZone, point)) {
return kMSSRectangleGrabZoneTopLeft;
} else if (CGRectContainsPoint(topGrabZone, point)) {
return kMSSRectangleGrabZoneTop;
} else if (CGRectContainsPoint(topRightGrabZone, point)) {
return kMSSRectangleGrabZoneTopRight;
} else if (CGRectContainsPoint(leftGrabZone, point)) {
return kMSSRectangleGrabZoneLeft;
} else if (CGRectContainsPoint(rightGrabZone, point)) {
return kMSSRectangleGrabZoneRight;
} else if (CGRectContainsPoint(bottomLeftGrabZone, point)) {
return kMSSRectangleGrabZoneBottomLeft;
} else if (CGRectContainsPoint(bottomGrabZone, point)) {
return kMSSRectangleGrabZoneBottom;
} else if (CGRectContainsPoint(bottomRightGrabZone, point)) {
return kMSSRectangleGrabZoneBottomRight;
} else {
return kMSSRectangleGrabZoneNone;
}
}
@end
Upvotes: 1