2013-05-29 3 views
3

Каким будет лучший способ реализации интерфейса, который состоит из UIView, которые разделены линией, а строка может изменять размеры просмотров?Разделитель перетаскивания для изменения размера UIViews

В его простейшей форме, это может выглядеть следующим образом:

---------------- 
|    | 
| View A  | 
|    | 
|--------------| < line which can be moved up and down, resizing the views 
|    | 
| View B  | 
|    | 
---------------- 

Это может иметь много больше просмотров.

Моей первой мыслью было бы сделать линию перетаскиваемого UIView с чем-то вроде Touches, который изменил размеры представлений в соответствии с его положением, но я уверен, что должно быть более элегантное решение.

+0

Ответ будет отличаться в зависимости от того, используете ли вы автоопределение и ограничения, или это вопрос без автосохранения (т. Е. Вы поддерживаете версии iOS до 6.0). Но простой идеей было бы создать «UIPanGestureRecognizer», который изменил бы размеры изображений на основе того, куда вы перетаскиваете. – Rob

ответ

8

Во-первых, определить жест, который детектирует начал ли вы на границе, и если изменения жест, движения говорит границы:

#import <UIKit/UIGestureRecognizerSubclass.h> 

- (void)viewDidLoad 
{ 
    [super viewDidLoad]; 

    // I use long press gesture recognizer so it's recognized immediately 

    UILongPressGestureRecognizer *gesture = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(handlePan:)]; 
    gesture.minimumPressDuration = 0.0; 
    gesture.allowableMovement = CGFLOAT_MAX; 
    gesture.delegate = self; 
    [self.containerView addGestureRecognizer:gesture]; 
} 

- (void)handlePan:(UILongPressGestureRecognizer *)gesture 
{ 
    static NSArray *matches; 
    static CGPoint firstLocation; 

    if (gesture.state == UIGestureRecognizerStateBegan) 
    { 
     firstLocation = [gesture locationInView:gesture.view]; 
     matches = [BorderBeingDragged findBordersBeingDraggedForView:gesture.view fromLocation:firstLocation]; 
     if (!matches) 
     { 
      gesture.state = UIGestureRecognizerStateFailed; 
      return; 
     } 
    } 
    else if (gesture.state == UIGestureRecognizerStateChanged) 
    { 
     CGPoint location = [gesture locationInView:gesture.view]; 
     CGPoint translation = CGPointMake(location.x - firstLocation.x, location.y - firstLocation.y); 
     [BorderBeingDragged dragBorders:matches translation:translation]; 
    } 
} 

// if your subviews are scrollviews, you might need to tell the gesture recognizer 
// to allow simultaneous gestures 

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer 
{ 
    return TRUE; 
} 

Во-вторых, определить BordersBeingDragged класс, который делает обнаружение границ и изменение границ:

typedef enum NSInteger { 
    kBorderTypeNone = 0, 
    kBorderTypeLeft = 1 << 0, 
    kBorderTypeRight = 1 << 1, 
    kBorderTypeTop = 1 << 2, 
    kBorderTypeBottom = 1 << 3 
} BorderType; 

@interface BorderBeingDragged : NSObject 

@property (nonatomic, weak) UIView *view; 
@property (nonatomic) BorderType borderTypes; 
@property (nonatomic) CGRect originalFrame; 

@end 

static CGFloat const kTolerance = 15.0; 

@implementation BorderBeingDragged 

+ (NSArray *)findBordersBeingDraggedForView:(UIView *)view fromLocation:(CGPoint)point 
{ 
    NSMutableArray *matches = nil; 

    for (UIView *subview in view.subviews) 
    { 
     BorderType types = kBorderTypeNone; 
     CGRect frame = subview.frame; 

     // test top and bottom borders 

     if (point.x >= (frame.origin.x - kTolerance) && 
      point.x <= (frame.origin.x + frame.size.width + kTolerance)) 
     { 
      if (point.y >= (frame.origin.y - kTolerance) && point.y <= (frame.origin.y + kTolerance)) 
       types |= kBorderTypeTop; 
      else if (point.y >= (frame.origin.y + frame.size.height - kTolerance) && point.y <= (frame.origin.y + frame.size.height + kTolerance)) 
       types |= kBorderTypeBottom; 
     } 

     // test left and right borders 

     if (point.y >= (frame.origin.y - kTolerance) && 
      point.y <= (frame.origin.y + frame.size.height + kTolerance)) 
     { 
      if (point.x >= (frame.origin.x - kTolerance) && point.x <= (frame.origin.x + kTolerance)) 
       types |= kBorderTypeLeft; 
      else if (point.x >= (frame.origin.x + frame.size.width - kTolerance) && point.x <= (frame.origin.x + frame.size.width + kTolerance)) 
       types |= kBorderTypeRight; 
     } 

     // if we found any borders, add it to our array of matches 

     if (types != kBorderTypeNone) 
     { 
      if (!matches) 
       matches = [NSMutableArray array]; 

      BorderBeingDragged *object = [[BorderBeingDragged alloc] init]; 
      object.borderTypes = types; 
      object.view   = subview; 
      object.originalFrame = frame; 

      [matches addObject:object]; 
     } 
    } 

    return matches; 
} 

+ (void)dragBorders:(NSArray *)matches translation:(CGPoint)translation 
{ 
    for (BorderBeingDragged *object in matches) 
    { 
     CGRect newFrame = object.originalFrame; 

     if (object.borderTypes & kBorderTypeLeft) 
     { 
      newFrame.origin.x += translation.x; 
      newFrame.size.width -= translation.x; 
     } 
     else if (object.borderTypes & kBorderTypeRight) 
     { 
      newFrame.size.width += translation.x; 
     } 

     if (object.borderTypes & kBorderTypeTop) 
     { 
      newFrame.origin.y += translation.y; 
      newFrame.size.height -= translation.y; 
     } 
     else if (object.borderTypes & kBorderTypeBottom) 
     { 
      newFrame.size.height += translation.y; 
     } 

     object.view.frame = newFrame; 
    } 
} 

@end 
+0

Спасибо. Будет ли это работать, если Views A и B были scrollviews? Или UILongPressGestureRecognizer в целом containerView вмешивается в способность scrollviews нормально работать (прокрутка и масштабирование)? – cannyboy

+0

@cannyboy Добавление жестов в представление, содержащее прокрутки, проблематично. Одним из решений является разрешение одновременных жестов (как в моем пересмотренном ответе). Вы получаете немного любопытный эффект, хотя, если смещение содержимого прокрутки не является 'CGPointMake (0.0, 0.0)', то есть вы уже прокрутили subview. Поэтому, если вы изменяете размеры подзаголовков, вы можете попробовать установить 'contentOffset' в' CGPointMake (0.0, 0.0) '. Есть, вероятно, и другие подходы. Вы должны поиграть с ним. – Rob

2

Вам действительно необходимо сделать перетаскивание в виде линии, но это не должно быть сложным.

  1. Помещенный viewA и viewB в containerView
  2. Добавить панорамирование жест распознаватель к containerView сконфигурированной для одного прикосновения и установить его делегатом к контроллеру.
  3. Внесите gestureRecognizerShouldBegin: из протокола UIGestureRecognizerDelegate и разрешите его только в том случае, если касание находится вблизи линии.
  4. В обработчике жест получить позицию касания в containerView и установите положение линии обзора и рамки для viewA и viewB

Это довольно много его.

1

Я предлагаю другое поведение: 1. Нажмите и удерживайте 2 секунды на линии 2. Появляется некоторое ImageView который вы будете перетаскивать

0

Простейший способ - добавить распознаватель жестов к вашим представлениям и изменить их размер в соответствии с панорамированием.

Смежные вопросы