2013-02-12 2 views
2

4 개의 원형 핸들이있는 직사각형을 그리려합니다. 모양은 다음과 같습니다.원형 핸들이있는 UIBezierPath 사각형

o----o 
| | 
| | 
o----o 

원형 핸들이 "뜨겁습니다". 즉, 사용자가 손을 댈 때 손잡이를 움직일 수 있으며 나머지 점은 고정되어 있습니다. 누군가이 기능을 코딩하는 방법을 알고 있는지 알고 싶었습니다. UIBezierPath에서 원으로 직사각형을 그려보고 있지만 사용자가 서클 만 탭할 수 있도록하는 방법에 대해 생각하고 있습니다. 나는 그것이 5 개의 다른 UIBezierPath 객체 일 필요가 있다고 생각했지만 결국 UI는이 객체의 배수로 구성됩니다.

모든 의견을 크게 기뻐할 것입니다. 감사.

+0

'addArcWithCenter : radius : startAngle : endAngle : clockwise :'? 당신은 "직선"을 멈출 때를 알고 있습니다 ... – Larme

답변

3

난 전혀 복잡 UIBezierPath의 단일 형태로 그려하지 않을 것입니다. 나는 6 개의 다른 조각으로 그것에 대해 생각할 것입니다. 컨테이너, 직사각형 및 4 개의 원

간단한 컨테이너 UIView에는 직사각형보기가 있고 원형에는 4 개의 원형 구석이 있습니다 (UIViews). 그런 다음 각 서클에 UIPanGestureRecognizer을 넣으십시오. 제스처 핸들러에서 원의 중심을 이동하고 기본 사각형 rect를 동일한 양만큼 조정합니다. 이렇게하면 복잡한 경로 나 수학을 피할 수 있고 사각형 자체에 양을 더하고 빼기 만하면됩니다.

업데이트 : 코드!

모든 것을 처리하는 자체 포함 된 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 

이것은 단지 개념 증명 일뿐입니다. 상자 밖에서 끌 수있는 것과 같은 많은 누락 된 경고, 멀티 터치 합병증, 음수 크기가 있습니다. 이러한 모든 문제는 매우 다르게 처리 될 수 있으며 멋진 아이디어에서 멋진 사용자 인터페이스로 바뀌는 비밀의 소스입니다. 나는 그 부분을 너에게 맡길거야. :)

+0

나는이 접근 방식을 정말 좋아합니다. 매우 간단 해 보입니다. 한 번에 이러한 개체가 여러 개있을 수있는 경우이 접근 방식을 사용하면 성능 문제가 발생합니까? – Clay

+0

나는 기대하지 않습니다. 나는 그것에 약간의 코드를 던지기로 결심했다. 그러니 5 분만 주면 시험해 볼 수있는 작은 예가 나옵니다. –

+0

몇 가지 코드를 추가했습니다. 시작하는 데 도움이되기를 바랍니다. 도움이되는 의견을 남기려하지만 더 많은 질문이 있으면 주저하지 마십시오. –