当前位置: 首页 > news >正文

[一句秒懂]高仿QQ底部小红点弹簧效果

为什么80%的码农都做不了架构师?>>>   hot3.png

101521_VSR3_2684046.gif101725_JjPy_2684046.gif

 

1:

// 前提之前:增加几张jpg格式的图片,暂时写死为9张,命名格式为:(1.jpg-9.jpg),你也可以在代码中去修改一下、谢谢!

 

 

//
//  QQRedButton.m
//  仿照QQ小红点
//
//  Created by 李胜兵 on 15/4/18.
//  Copyright © 2015年 李胜兵. All rights reserved.
//

#import "QQRedButton.h"
#define kMaxDisance 200
#define kHeight [UIScreen mainScreen].bounds.size.height
#define kWidth [UIScreen mainScreen].bounds.size.width

@interface QQRedButton ()


@property (nonatomic, strong)UIView *smallCircleView;

@property (nonatomic, assign)CGFloat smallOriginRadius;


@property (nonatomic, strong)CAShapeLayer *shapeLayer;

@end

@implementation QQRedButton

- (instancetype)initWithFrame:(CGRect)frame {
    if (self = [super initWithFrame:frame]) {
        [self setUp];
    }
    return self;
}

#pragma mark - 设置按钮内容

- (void)setUp {
    CGFloat w = self.bounds.size.width;
    self.layer.cornerRadius = w /2;
    self.smallOriginRadius = w /2;
    
    
    [self setTitle:@"10" forState:UIControlStateNormal];
     self.titleLabel.font = [UIFont systemFontOfSize:12];
    [self setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
    [self setBackgroundColor:[UIColor redColor]];
    
  
    // 添加pan手势
    UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc]initWithTarget:self action:@selector(pan:)];
    [self addGestureRecognizer:pan];
    
    
    // 添加小圆到大圆的后面:设置小圆的位置和尺寸
    self.smallCircleView.center = self.center;
    self.smallCircleView.bounds = self.bounds;
    self.smallCircleView.layer.cornerRadius = w/2;
    
}

#pragma mark - 方法

- (void)pan:(UIPanGestureRecognizer *)pan {
    [self.superview insertSubview:self.smallCircleView belowSubview:self];
    CGPoint transPoint = [pan translationInView:self];
    CGPoint center = self.center;
    center.x += transPoint.x;
    center.y += transPoint.y;
    self.center = center;
    [pan setTranslation:CGPointZero inView:self];

    CGFloat d = [self circleCenterDistanceWithBigCircleViewCenter:self.center smallCircleViewCenter:self.smallCircleView.center];
    CGFloat smallRadius = (self.smallOriginRadius - d / 10)>0?(self.smallOriginRadius - d / 10):0;
    self.smallCircleView.bounds = CGRectMake(0, 0, smallRadius*2, smallRadius*2);
    self.smallCircleView.layer.cornerRadius = smallRadius;
    if (d>kMaxDisance) {
        self.smallCircleView.hidden = YES;
        
        [self.shapeLayer removeFromSuperlayer];
        self.shapeLayer = nil;
    }else if (d>0 && self.smallCircleView.hidden == NO) { // 有圆心距离而且小圆也显示的时候才绘制不
        [self.superview.layer insertSublayer:_shapeLayer below:self.layer];
        self.shapeLayer.path = [[self pathWithBigCircleView:self smallCircleView:self.smallCircleView] CGPath];
    }


    
    if (pan.state == UIGestureRecognizerStateEnded) {
        if (d>kMaxDisance) {
            NSMutableArray *arrM = [NSMutableArray array];
            UIImageView *imgV = [[UIImageView alloc]initWithFrame:self.bounds];
            
            for (int i = 1; i<10; i++) {
                UIImage *image = [UIImage imageNamed:[NSString stringWithFormat:@"%d.gif",i]];
                [arrM addObject:image];
            }
            
            imgV.animationDuration = 2.2;
            imgV.animationRepeatCount = 1;
            imgV.animationImages = arrM;
            [imgV startAnimating];
            [self addSubview:imgV];
            
            dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
                [self removeFromSuperview];
            });
            
        }else {
            [self.shapeLayer removeFromSuperlayer];
            self.shapeLayer = nil;
            self.smallCircleView.hidden = NO;
            [UIView animateWithDuration:.5 delay:0 usingSpringWithDamping:.2 initialSpringVelocity:0 options:(UIViewAnimationOptionCurveLinear) animations:^{
                self.center = self.smallCircleView.center;
            } completion:^(BOOL finished) {
                
            }];
        }
    }
}


- (CGFloat)circleCenterDistanceWithBigCircleViewCenter:(CGPoint)bigCircleViewCenter smallCircleViewCenter:(CGPoint)smallCircleViewCenter {
    CGFloat offsetX = bigCircleViewCenter.x - smallCircleViewCenter.x;
    CGFloat offsetY = bigCircleViewCenter.y - smallCircleViewCenter.y;
    return  sqrt(offsetX * offsetX + offsetY * offsetY);
    
}


- (UIBezierPath *)pathWithBigCircleView:(UIView *)bigCircleView smallCircleView:(UIView *)smallCircleView {
    
    
    CGPoint bigCenter = bigCircleView.center;
    CGFloat x2 = bigCenter.x;
    CGFloat y2 = bigCenter.y;
    CGFloat r2 = bigCircleView.bounds.size.width /2;
    
    CGPoint smallCenter = smallCircleView.center;
    CGFloat x1 = smallCenter.x;
    CGFloat y1 = smallCenter.y;
    CGFloat r1 = smallCircleView.bounds.size.width /2;
    
    CGFloat d = [self circleCenterDistanceWithBigCircleViewCenter:bigCenter smallCircleViewCenter:smallCenter];
    
    CGFloat sinθ = (x2 - x1) /d;
    CGFloat cosθ = (y2 - y1) /d;
    
    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/2 *sinθ, pointA.y + d/2 * cosθ);
    CGPoint pointP = CGPointMake(pointB.x + d/2 * sinθ, pointB.y + d/2 * 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;
}



#pragma mark - get

- (UIView *)smallCircleView {
    if (!_smallCircleView) {
        _smallCircleView = [[UIView alloc] init];
        _smallCircleView.layer.cornerRadius = self.layer.cornerRadius;
        _smallCircleView.backgroundColor = self.backgroundColor;
    }
    return _smallCircleView;
}

#pragma mark - get

- (CAShapeLayer *)shapeLayer {
    if (!_shapeLayer) {
        _shapeLayer = [CAShapeLayer layer];
        _shapeLayer.fillColor = self.backgroundColor.CGColor;
    }
    return _shapeLayer;
}



@end
//
//  QQRedButton.h
//  仿照QQ小红点
//
//  Created by 李胜兵 on 15/4/18.
//  Copyright © 2015年 李胜兵. All rights reserved.
//

#import <UIKit/UIKit.h>

@interface QQRedButton : UIButton

@end

 


 

 

 

 

 

 

 

 

转载于:https://my.oschina.net/shengbingli/blog/662434

相关文章:

  • 安全关闭多Activity的Application
  • Android自定义控件之日历控件
  • path去除多余“/”和添加“/”正则
  • JS魔法堂:doctype我们应该了解的基础知识
  • CSS3魔法堂:禁止用户改变textarea大小
  • 音效
  • 在Servlet使用getServletContext()获取ServletContext对象出现java.lang.NullPointerException(空指针)异常的解决办法...
  • ssl证书的对称密钥与非对称密钥
  • Linux LVM硬盘管理及LVM扩容
  • synchronized 补遗
  • 软考信息系统监理师,2016年4月22日作业
  • 使用VMware虚拟机,分别部署2台centos7主机实现,httpd(php模块)+mysql,
  • .NET(C#) Internals: as a developer, .net framework in my eyes
  • 获取当前时间的 年月日时分秒
  • 开发QQ互联ios版Ane扩展 辛酸史
  • LeetCode算法系列_0891_子序列宽度之和
  • linux学习笔记
  • mysql innodb 索引使用指南
  • react-core-image-upload 一款轻量级图片上传裁剪插件
  • Redis提升并发能力 | 从0开始构建SpringCloud微服务(2)
  • spring cloud gateway 源码解析(4)跨域问题处理
  • 搭建gitbook 和 访问权限认证
  • 构建工具 - 收藏集 - 掘金
  • 关于Java中分层中遇到的一些问题
  • 前端自动化解决方案
  • 使用 5W1H 写出高可读的 Git Commit Message
  • 提升用户体验的利器——使用Vue-Occupy实现占位效果
  • 跳前端坑前,先看看这个!!
  • 微信小程序开发问题汇总
  • [Shell 脚本] 备份网站文件至OSS服务(纯shell脚本无sdk) ...
  • ​html.parser --- 简单的 HTML 和 XHTML 解析器​
  • ​Linux·i2c驱动架构​
  • #ifdef 的技巧用法
  • #LLM入门|Prompt#1.8_聊天机器人_Chatbot
  • (007)XHTML文档之标题——h1~h6
  • (06)Hive——正则表达式
  • (4)通过调用hadoop的java api实现本地文件上传到hadoop文件系统上
  • (C++)栈的链式存储结构(出栈、入栈、判空、遍历、销毁)(数据结构与算法)
  • (day 12)JavaScript学习笔记(数组3)
  • (Java数据结构)ArrayList
  • (动态规划)5. 最长回文子串 java解决
  • (过滤器)Filter和(监听器)listener
  • (九十四)函数和二维数组
  • (免费领源码)Java#Springboot#mysql农产品销售管理系统47627-计算机毕业设计项目选题推荐
  • (转)Android中使用ormlite实现持久化(一)--HelloOrmLite
  • (转)C#开发微信门户及应用(1)--开始使用微信接口
  • (转载)hibernate缓存
  • .Net CF下精确的计时器
  • .NET I/O 学习笔记:对文件和目录进行解压缩操作
  • .NET/MSBuild 中的发布路径在哪里呢?如何在扩展编译的时候修改发布路径中的文件呢?
  • .NET设计模式(7):创建型模式专题总结(Creational Pattern)
  • .net实现头像缩放截取功能 -----转载自accp教程网
  • /bin/bash^M: bad interpreter: No such file ordirectory
  • @reference注解_Dubbo配置参考手册之dubbo:reference
  • [ C++ ] STL---stack与queue