QQ消息提示移除粘性效果

几何原理

创建一个继承UIButton的自定义Button

#import "StickyButton.h"

@interface StickyButton()

@property (strong, nonatomic)UIView *smallCircle;
@property (strong, nonatomic)CAShapeLayer *shapeLayer;

@end

@implementation StickyButton

- (void)awakeFromNib
{
    [super awakeFromNib];

    [self config];
}

- (void)config
{
    //设置背景颜色,设置layer的cornerRadius属性,添加手势,重写setHighlighted方法,屏蔽按钮的高亮状态
    [self.layer setMasksToBounds:YES];
    [self.layer setCornerRadius:self.bounds.size.width * 0.5];
    self.titleLabel.font = [UIFont systemFontOfSize:12];
    [self setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
    self.backgroundColor = [UIColor redColor];

    [self.superview addSubview:self.smallCircle];
    [self.superview insertSubview:self.smallCircle belowSubview:self];

    UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc]initWithTarget:self action:@selector(pan:)];

    [self addGestureRecognizer:pan];
}

//创建一个小圆于大圆之下,初始和大圆一样大
- (UIView *)smallCircle
{
    if(_smallCircle == nil)
    {
        _smallCircle = [[UIView alloc]initWithFrame:self.frame];
        _smallCircle.layer.cornerRadius = self.layer.cornerRadius;
        _smallCircle.backgroundColor = [UIColor redColor];
    }
    return _smallCircle;
}

//创建一个形状图层,用于绘制两个圆之间的形状
- (CAShapeLayer *)shapeLayer
{
    if(_shapeLayer == nil)
    {
        _shapeLayer= [CAShapeLayer layer];
        _shapeLayer.fillColor = [UIColor redColor].CGColor;
        [self.superview.layer insertSublayer:_shapeLayer atIndex:0];
    }
    return _shapeLayer;
}

//添加拖动手势,
- (void)pan:(UIPanGestureRecognizer*)gesture
{
    //实现自定义控件的移动
    //注意修改控件的形变,其ceter的值并不会改变
    CGPoint transPoint = [gesture translationInView:self];
    CGPoint center = self.center;
    center.x += transPoint.x;
    center.y += transPoint.y;
    self.center = center;

    //注意利用CGAffineTransformTranslate修改形变,center的值不会改变
    //self.transform = CGAffineTransformTranslate(self.transform, trans.x, trans.y);

    [gesture setTranslation:CGPointZero inView:self];

    CGFloat distance = [self distanceWithSmallCircle:self.smallCircle BigCircle:self];

    NSLog(@"%f",distance);

    CGFloat smallRadius = self.bounds.size.width * 0.5;
    smallRadius -= distance / 10.0;
    if(smallRadius <= 0)smallRadius = 0;
    self.smallCircle.bounds = CGRectMake(0, 0, smallRadius * 2, smallRadius * 2);
    self.smallCircle.layer.cornerRadius = smallRadius;

    if(self.smallCircle.hidden == NO)
    {
        self.shapeLayer.path = [self pathWithSmallCircle:self.smallCircle BigCircle:self].CGPath;
    }

    if(distance > 100)
    {
        self.smallCircle.hidden = YES;

        [self.shapeLayer removeFromSuperlayer];
        self.shapeLayer = nil;
    }

    //当手指离开时,判断当前两圆心的距离
    //若两圆心距离大于规定的距离,则加载gif动画,移除当前控件
    //若两圆心距离小于规定的距离,则返回最开始的位置,即小圆的位置,隐藏小圆,移除不规则矩形
    if(gesture.state == UIGestureRecognizerStateEnded)
    {

        if(distance < 100)
        {
            self.center = self.smallCircle.center;

            self.smallCircle.hidden = NO;

            [self.shapeLayer removeFromSuperlayer];
            self.shapeLayer = nil;
        }
        else
        {
            [UIView animateWithDuration:0.5 animations:^{
                self.alpha = 0;
            } completion:^(BOOL finished) {
                self.center = self.smallCircle.center;

                self.smallCircle.hidden = NO;

                [self.shapeLayer removeFromSuperlayer];
                self.shapeLayer = nil;

                self.alpha = 1;
            }];
        }
    }
}

//若两圆心距离大于规定的距离,则隐藏小圆,移除不规则矩形
- (CGFloat)distanceWithSmallCircle:(UIView*)smallCircle BigCircle:(UIView*)bigCircle
{
    CGFloat offsetX = bigCircle.center.x - smallCircle.center.x;
    CGFloat offsetY = bigCircle.center.y - smallCircle.center.y;
    return sqrt(offsetX * offsetX + offsetY * offsetY);
}

//该矩形路径的计算公式如下(原理如顶部图片所示)
- (UIBezierPath*) pathWithSmallCircle:(UIView*)smallCircle BigCircle:(UIView*)bigCircle
{
    CGFloat x1 = smallCircle.center.x;
    CGFloat y1 = smallCircle.center.y;

    CGFloat x2 = bigCircle.center.x;
    CGFloat y2 = bigCircle.center.y;

    CGFloat d = [self distanceWithSmallCircle:self.smallCircle BigCircle:self];

    if(d <= 0)
    {
        return nil;
    }

    CGFloat cosθ = (y2 - y1) / d;
    CGFloat sinθ = (x2 - x1) / d;

    CGFloat r1 = smallCircle.bounds.size.width * 0.5;
    CGFloat r2 = bigCircle.bounds.size.width * 0.5;

    CGPoint pointA = CGPointMake(x1 - r1 * cosθ, y1 + r1 * sinθ);
    CGPoint pointB = CGPointMake(x1 + r1 * cosθ, y1 - r1 * sinθ);
    CGPoint pointC = CGPointMake(x2 + r2 * cosθ, y2 - r2 * sinθ);
    CGPoint pointD = CGPointMake(x2 - r2 * cosθ, y2 + r2 * sinθ);
    CGPoint pointO = CGPointMake(pointA.x + d * 0.5 * sinθ, pointA.y + d * 0.5 * cosθ);
    CGPoint pointP = CGPointMake(pointB.x + d * 0.5 * sinθ, pointB.y + d * 0.5 * cosθ);

    UIBezierPath *path = [UIBezierPath bezierPath];
    [path moveToPoint:pointA];
    [path addLineToPoint:pointB];
    [path addQuadCurveToPoint:pointC controlPoint:pointP];
    [path addLineToPoint:pointD];
    [path addQuadCurveToPoint:pointA controlPoint:pointO];

    return path;
}

- (void)layoutSubviews
{
    [super layoutSubviews];

    [self config];
}

- (void)drawRect:(CGRect)rect {
    // Drawing code

}

//屏蔽高亮状态
- (void)setHighlighted:(BOOL)highlighted
{

}

@end

results matching ""

    No results matching ""