Drag separator to resize UIViews

后端 未结 4 1703
旧时难觅i
旧时难觅i 2021-02-10 14:15

What would be to the best way of implementing an interface which consists of UIViews which are separated by a line, and the line can resize the views?

In it\'s simplest

4条回答
  •  逝去的感伤
    2021-02-10 14:45

    First, define a gesture that detects whether you started on a border, and if the gesture changes, moves said borders:

    #import 
    
    - (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;
    }
    

    Second, define a BordersBeingDragged class that does the detection of borders and the changing of borders:

    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
    

提交回复
热议问题