《仿QQ未读消息粘性按钮》

版权声明:文章为作者良心产物,转载请注明出处. https://blog.csdn.net/u014455765/article/details/51627767

思路

  • 控件结构
  • 封装思路
  • 细节注意
  • 使用方法

1.控件结构

继承自UIButton, 对系统的按钮进行进一步的分装,主要是由一个圆形的UIView - smallCircle按钮本身一个CAShapeLayer图层构成。


2.封装思路

  1. 根据btn的frame,创建一个大小相同的圆形UIView-samillCircle, 并且将其添加到btn的父控件上。

  2. 给按钮本身添加拖动手势和点击事件,在拖动手势监听时获取btn手势的偏移量,根据偏移量改变按钮本身的center坐标,使得btn跟随手势拖动而移动。
    不规则矩形路径图

  3. 根据btn和smallCircle的center计算出两个圆的中心点的间距d, 根据间距改变smallCircle的半径(随着d越大,半径越小), 并且根据手势拖动描绘shapeLayer图层(根据手势坐标计算不规则图层的路径,这里用到UIBezierPath曲线路径), 通过对两个圆形区域的控制点A、B、C、D、O、P点描绘path路径,最后将路径赋值给图层,达到每次手势拖动不规则图层都会展示不同的矩形效果。

  4. 当间距达到最大间距kMaxDistance时,隐藏smallCircle,并且销毁不规则矩形。当手指抬起,判断间距d是否小于最大间距,若小于最大间距,则位置还原,若大于最大间距,则显示消失动画之后移除btn,调用delegate的viscousButtonDismissed方法处理事件。同时,在点击btn时也可以展示btn消失动画以及代理事件,可以通过实现代理对按钮的事件进行后续逻辑功能处理。


3.细节注意

  1. 这里不能用绘图方法drawRect去代替图层shapeLayer的实现,因为如果采用绘图,绘图内容只要超过当前控件就不会显示,但是当前形变必须显示在控件之外。

  2. 如采用代码创建该按钮的实例进行使用,由于我们是在初始化方法initWithFrame和awakeFromNib中去调用setUp方法进行内容的初始化,包括对小圆smallCircle的创建和添加。但是这样一来,代码创建就会出现获取不到superView的问题,导致self.superView addSubview: samllCircle无效,和xib创建不同的是因为程序外部是在初始化之后才添加到父控件上,而xib是由内到外一层一层的添加控件,在当前按钮创建出来之前父控件已经存在。因此我们发现苹果提供一个didMoveToSuperview方法,改方法会在父控件addSubView完成之后调用,故我们将添加小圆的步骤在该方法中执行。

/**
 *  @brief  在父控件addSubview后调用
 */
- (void)didMoveToSuperview {
    [super didMoveToSuperview];
    // 设置小圆的位置和尺寸
    self.smallCircle.center = self.center;
    self.smallCircle.bounds = CGRectMake(0, 0, self.bounds.size.height, self.bounds.size.height);
    self.smallCircle.layer.cornerRadius = self.bounds.size.height / 2;
}
  • 为防止xib中引用的self按钮会会默认使用自动布局,使用代码关闭自动布局,使得按钮和xib引用达到相同的效果。
// 取消父控件xib的自动布局 self.superview.translatesAutoresizingMaskIntoConstraints = NO;

4.使用方法

  1. xib使用
    拖动一个UIButton控件到父控件上,将MRViscousButton文件中的MRViscousButton.h和MRViscousButton.m文件复制到项目中,更改UIButton的class为MRViscousButton即可。xib使用

    1. 代码创建
    MRViscousButton *btn = [[MRViscousButton alloc] initWithFrame:CGRectMake(100, 150, 30, 30)];
    // 设置代理
    btn.delegate = self;
    [btn setTitle:@"24" forState:UIControlStateNormal];
    [btn setBackgroundColor:[UIColor redColor]];
    [self.view  addSubview:btn];
    // 设置动画图片
    NSMutableArray *arrM = [NSMutableArray array];
    for (int i = 1; i < 9; i++) {
        UIImage *image = [UIImage imageNamed:[NSString stringWithFormat:@"%d", i]];   
        [arrM addObject:image];
    }
    btn.images = arrM;

    # pragma mark - <MRViscousButtonDelegate>
    - (void)viscousButtonDismissed:(MRViscousButton *)btn {

    NSLog(@"%@ - 代理回调方法", btn);
    }

效果图
粘性按钮


Demo地址: github

展开阅读全文

没有更多推荐了,返回首页