我正在尝试绘制一个有四个圆形手柄的矩形。这就是它的样子:
o----o
| |
| |
o----o
圆形手柄“很热”。换句话说,当用户触摸它时,手柄可以移动,而其余的点被锚定。我想知道是否有人有编码此功能的方法。我正在看UIBezierPath用圆圈绘制矩形,但我很难想到如何让用户只点击圆圈。我认为可能需要五个不同的UIBezierPath对象,但最终UI将包含多个这些对象。
任何建议都将不胜感激。感谢。
答案 0 :(得分:4)
我不会将它绘制为具有复杂UIBezierPath
s的单个形状。我认为它有6个不同的部分。容器,矩形和4个圆圈。
我会有一个简单的容器UIView
,它的角落有一个矩形视图和四个圆形UIViews
。然后在每个圆圈上放置一个UIPanGestureRecognizer
。在手势处理程序中,移动圆心并以相同的量调整基础矩形矩形。这将避免任何复杂的路径或数学运算,并使矩形本身的加减量变得简单。
更新:代码!
我创建了一个自包含的UIView子类来处理所有事情。你可以这样创建一个:
HandlesView *view = [[HandlesView alloc] initWithFrame:self.view.bounds];
[view setAutoresizingMask:UIViewAutoresizingFlexibleHeight|UIViewAutoresizingFlexibleWidth];
[view setBackgroundColor:[UIColor redColor]];
[self.view addSubview:view];
// A custom property that contains the selected area of the rectangle. Its updated while resizing.
[view setSelectedFrame:CGRectMake(128.0, 128.0, 200.0, 200.0)];
视图的框架本身是可拖动的总区域。所选框架是内部可见矩形。
//
// HandlesView.h
// handles
//
// Created by Ryan Poolos on 2/12/13.
// Copyright (c) 2013 Ryan Poolos. All rights reserved.
//
#import <UIKit/UIKit.h>
#import <QuartzCore/QuartzCore.h>
@interface HandlesView : UIView
@property (nonatomic, readwrite) CGRect selectedFrame;
@end
这是实施。
//
// HandlesView.m
// handles
//
// Created by Ryan Poolos on 2/12/13.
// Copyright (c) 2013 Ryan Poolos. All rights reserved.
//
#import "HandlesView.h"
@interface HandlesView ()
{
UIView *rectangle;
NSArray *handles;
NSMutableArray *touchedHandles;
UIView *circleTL;
UIView *circleTR;
UIView *circleBL;
UIView *circleBR;
}
@end
@implementation HandlesView
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
rectangle = [[UIView alloc] initWithFrame:CGRectInset(self.bounds, 22.0, 22.0)];
[self addSubview:rectangle];
// Create the handles and position.
circleTL = [[UIView alloc] initWithFrame:CGRectMake(0.0, 0.0, 44.0, 44.0)];
[circleTL setCenter:CGPointMake(CGRectGetMinX(rectangle.frame), CGRectGetMinY(rectangle.frame))];
circleTR = [[UIView alloc] initWithFrame:CGRectMake(0.0, 0.0, 44.0, 44.0)];
[circleTR setCenter:CGPointMake(CGRectGetMaxX(rectangle.frame), CGRectGetMinY(rectangle.frame))];
circleBL = [[UIView alloc] initWithFrame:CGRectMake(0.0, 0.0, 44.0, 44.0)];
[circleBL setCenter:CGPointMake(CGRectGetMinX(rectangle.frame), CGRectGetMaxY(rectangle.frame))];
circleBR = [[UIView alloc] initWithFrame:CGRectMake(0.0, 0.0, 44.0, 44.0)];
[circleBR setCenter:CGPointMake(CGRectGetMaxX(rectangle.frame), CGRectGetMaxY(rectangle.frame))];
handles = @[ circleTL, circleTR, circleBL, circleBR ];
for (UIView *handle in handles) {
// Round the corners into a circle.
[handle.layer setCornerRadius:(handle.frame.size.width / 2.0)];
[self setClipsToBounds:YES];
// Add a drag gesture to the handle.
[handle addGestureRecognizer:[[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handlePan:)]];
// Add the handle to the screen.
[self addSubview:handle];
}
}
return self;
}
- (void)setSelectedFrame:(CGRect)selectedFrame
{
[rectangle setFrame:selectedFrame];
[circleTL setCenter:CGPointMake(CGRectGetMinX(rectangle.frame), CGRectGetMinY(rectangle.frame))];
[circleTR setCenter:CGPointMake(CGRectGetMaxX(rectangle.frame), CGRectGetMinY(rectangle.frame))];
[circleBL setCenter:CGPointMake(CGRectGetMinX(rectangle.frame), CGRectGetMaxY(rectangle.frame))];
[circleBR setCenter:CGPointMake(CGRectGetMaxX(rectangle.frame), CGRectGetMaxY(rectangle.frame))];
}
- (CGRect)selectedFrame
{
return rectangle.frame;
}
// Forward the background color.
- (void)setBackgroundColor:(UIColor *)backgroundColor
{
// Set the container to clear.
[super setBackgroundColor:[UIColor clearColor]];
// Set our rectangle's color.
[rectangle setBackgroundColor:[backgroundColor colorWithAlphaComponent:0.5]];
for (UIView *handle in handles) {
[handle setBackgroundColor:backgroundColor];
}
}
- (void)handlePan:(UIPanGestureRecognizer *)gesture
{
// The handle we're moving.
UIView *touchedHandle = gesture.view;
// Keep track of touched Handles.
if (!touchedHandles) {
touchedHandles = [NSMutableArray array];
}
switch (gesture.state) {
case UIGestureRecognizerStateBegan:
[touchedHandles addObject:touchedHandle];
break;
case UIGestureRecognizerStateChanged:
{
CGPoint tranlation = [gesture translationInView:self];
// Calculate this handle's new center
CGPoint newCenter = CGPointMake(touchedHandle.center.x + tranlation.x, touchedHandle.center.y + tranlation.y);
// Move corresponding circles
for (UIView *handle in handles) {
if (handle != touchedHandle && ![touchedHandles containsObject:handle]) {
// Match the handles horizontal movement
if (handle.center.x == touchedHandle.center.x) {
handle.center = CGPointMake(newCenter.x, handle.center.y);
}
// Match the handles vertical movement
if (handle.center.y == touchedHandle.center.y) {
handle.center = CGPointMake(handle.center.x, newCenter.y);
}
}
}
// Move this circle
[touchedHandle setCenter:newCenter];
// Adjust the Rectangle
// The origin and just be based on the Top Left handle.
float x = circleTL.center.x;
float y = circleTL.center.y;
// Get the width and height based on the difference between handles.
float width = abs(circleTR.center.x - circleTL.center.x);
float height = abs(circleBL.center.y - circleTL.center.y);
[rectangle setFrame:CGRectMake(x, y, width, height)];
[gesture setTranslation:CGPointZero inView:self];
}
break;
case UIGestureRecognizerStateEnded:
[touchedHandles removeObject:touchedHandle];
break;
default:
break;
}
}
@end
这只是一个概念证明。有许多缺失的警告,如能够在盒子外面拖动,多点触控并发症,负面大小。所有这些问题都可以用非常不同的方式处理,并且这样做的秘诀就是从一个好主意变成一个漂亮的自定义界面。我会把那部分留给你。 :)
答案 1 :(得分:1)
在实现手势识别器时,您需要在类中存储圆圈贝塞尔路径。
Apple文档描述了如何实现接受带图片和示例代码的触摸事件的UIView或UIControl。