2013-05-29 20 views
3

实现由UIViews组成的界面的最佳方式是什么?UIView由一行分隔,并且该行可以调整视图的大小?拖动分隔符以调整UIViews的大小

在它最简单的形式,它可能是这样的:

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

它可能有更多的看法。

我的第一个想法是让这条线成为一个可拖动的UIView,像Touches,根据它的位置调整视图的大小,但我确定必须有一个更优雅的解决方案。

+0

根据您是否使用自动布局和约束,或者这是否为非自动布局问题(即您支持6.0之前的iOS版本),答案会有所不同。但简单的想法是创建一个“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

谢谢。如果视图A和B是滚动视图,这会起作用吗?或者UILongPressGestureRecognizer在整个容器视图中是否会干扰滚动视图的正常动作(滚动和缩放)? – cannyboy

+0

@cannyboy将手势添加到包含滚动视图的视图是有问题的。一种解决方案是允许同时进行手势操作(就像我修改后的答案)。不过,如果滚动视图的内容偏移量不是“CGPointMake(0.0,0.0)”,即您已经滚动子视图,您会得到一些好奇的效果。因此,如果您要调整子视图的大小,您可能需要尝试将'contentOffset'设置为'CGPointMake(0.0,0.0)'。也可能有其他方法。你应该玩弄它。 – Rob

2

你基本上需要使行视图可拖动,但它并不需要很复杂。

  1. viewAviewBcontainerView
  2. 全景手势识别器添加到配置为单点触摸的containerView及其委托设为您的控制器。
  3. UIGestureRecognizerDelegate协议实施gestureRecognizerShouldBegin:协议,并只允许它开始,如果触摸在线视图附近。
  4. 在手势处理机获得在containerView触摸位置,并设置线视图位置和框架viewAviewB

这几乎是它。

1

我建议其他行为: 1.按住上线 2.2秒显得有些ImageView的,你将拖累

0

最简单的方法是将手势识别器添加到您的视图并根据平移调整它们。

相关问题