我正在尝试在imageview上创建一个动态矩形。这意味着矩形应该在触摸时开始,只要用户移动触摸,它应该在那个方向上更大。 朋友建议我,拜托。
答案 0 :(得分:0)
您需要使用Core Graphics,尝试本教程:
答案 1 :(得分:0)
听起来好像你想在UIImage的之上选择一个矩形,而不仅仅是调整图像大小的能力。
如果是这种情况,我建议采用以下结构:
根据我的经验,这种性质的动画在使用震动和支柱以及-touchesBegan等时更容易实现,而不是Autolayout和UIGestureRecognizers,而是YMMV。
当然,你正在做的事情可能需要一些高级数学,基于你如何回答如下问题:
以下代码执行以下操作:
代码所做的假设:
此代码需要更新:
#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
答案 2 :(得分:-1)
您可以以编程方式创建imageview,并在触摸移动时调整其框架大小。请参阅以下链接,它可以帮助您。
How can I draw dynamic rectangle on screen according to touchMove event on iOS