是否可以合并相交的两个UIViews而不是让它们重叠?

问题描述 投票:-1回答:1

给定两个 UIViews 有边框 UIPanGestureRecognizers 附在他们身上。

enter image description here

如果我拖动... UIView 左边 UIView 在右边,这是通常的行为。

enter image description here

有没有可能让他们做下面的行为 看起来像他们合并?enter image description here:

寻找最简单的方法来实现这个功能!

ios cocoa-touch uiview core-graphics
1个回答
10
投票

一种方法是使用多个UIPanGestureRecognizers。同胞 层和 zPosition. 为了达到效果,你要添加两个图层,一个是边框,一个是内容。而边框层有一个较小的 zPosition 比内容。当然,也可以用它来移动图层。UIPanGestureRecognizer.

Showcase

MP4版本

Swift。

import UIKit

class MergingView: UIView {

    let borderLayer = CALayer()
    let backgroundLayer = CALayer()

    override func layoutSubviews() {
        super.layoutSubviews()

        addGestureRecognizer(UIPanGestureRecognizer(target: self, action: #selector(handlePan(_:))))

        borderLayer.borderWidth = 5
        borderLayer.frame = frame
        borderLayer.zPosition = 10
        borderLayer.borderColor = UIColor.black.cgColor
        superview?.layer.addSublayer(borderLayer)

        backgroundLayer.frame = CGRect(x: frame.origin.x + 5, y: frame.origin.y + 5, width: frame.width - 10, height: frame.height - 10)
        backgroundLayer.zPosition = 20
        backgroundLayer.backgroundColor = UIColor.white.cgColor
        superview?.layer.addSublayer(backgroundLayer);
    }

    @objc func handlePan(_ recognizer: UIPanGestureRecognizer) {
        CATransaction.begin()
        CATransaction.setValue(kCFBooleanTrue, forKey: kCATransactionDisableActions)

        let translation = recognizer.translation(in: self)
        frame = self.frame.offsetBy(dx: translation.x, dy: translation.y)
        recognizer.setTranslation(CGPoint.zero, in: self)

        borderLayer.frame = borderLayer.frame.offsetBy(dx: translation.x, dy: translation.y)
        backgroundLayer.frame = backgroundLayer.frame.offsetBy(dx: translation.x, dy: translation.y)

        CATransaction.commit()
    }
}

Objective-C头。

#import <UIKit/UIKit.h>

@interface MVMergingView : UIView

@end

Objective-C实现。

#import "MVMergingView.h"

@interface MVMergingView ()

@property (strong) CALayer *borderLayer;
@property (strong) CALayer *backgroundLayer;

@end

@implementation MVMergingView

- (void)layoutSubviews {
    [super layoutSubviews];

    [self addGestureRecognizer:[[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handlePan:)]];

    CALayer *borderLayer = [CALayer layer];
    borderLayer.borderWidth = 5.f;
    borderLayer.frame = self.frame;
    borderLayer.zPosition = 10;
    borderLayer.borderColor = UIColor.blackColor.CGColor;
    self.borderLayer = borderLayer;
    [self.superview.layer addSublayer:borderLayer];

    CALayer *backgroundLayer = [CALayer layer];
    backgroundLayer.frame = CGRectMake(self.frame.origin.x + 5.f, self.frame.origin.y + 5.f, self.frame.size.width - 10, self.frame.size.height - 10);
    backgroundLayer.zPosition = 20;
    backgroundLayer.backgroundColor = UIColor.whiteColor.CGColor;
    self.backgroundLayer = backgroundLayer;
    [self.superview.layer addSublayer:backgroundLayer];
}

- (void)handlePan:(UIPanGestureRecognizer *)recognizer {
    [CATransaction begin];
    [CATransaction setValue:(id)kCFBooleanTrue forKey:kCATransactionDisableActions];

    CGPoint translation = [recognizer translationInView:self];
    self.frame = CGRectOffset(self.frame, translation.x, translation.y);
    [recognizer setTranslation:CGPointZero inView:self];

    self.borderLayer.frame = CGRectOffset(self.borderLayer.frame, translation.x, translation.y);
    self.backgroundLayer.frame = CGRectOffset(self.backgroundLayer.frame, translation.x, translation.y);

    [CATransaction commit];
}

@end

例子回帖。https:/github.comdimitarnestorovMergingView。


3
投票

似乎你要求 "合并 "而不是重叠,只是因为有边界才存在。如果没有边界,那么就不需要任何合并,你只需要把它们重叠起来。所以问题就变成了如何处理边界的问题。

我在想也许你可以有一个特殊的UIView子类(MergingView?),它将作为2个视图的父视图:一个边框视图和一个内容视图。现在边框和内容分别在不同的视图中,"合并 "变得微不足道。

当我们放下 A 在...之上 B,我们要做的就是把A的边框视图和内容视图给B(所以它们现在是B的子视图),然后把B的边框视图都发到后面。

然后你就可以继续和B进行更多的合并,程序是一样的。

这是否适合你的用例?如果需要,很乐意发代码。

© www.soinside.com 2019 - 2024. All rights reserved.