美文网首页iOS小项目iOS开发部落iOS实用
可拖拽的小窗口,最好用?

可拖拽的小窗口,最好用?

作者: gitKong | 来源:发表于2016-12-23 14:48 被阅读833次

    一、前言

    • 1、写了10多天的小程序代码,有兴趣的可以看我这篇小程序官方文档-小程序版【持续更新】,被坑得有点晕,突然想换换口味,写点iOS的,看群上有人提过这个拖拽view的功能,应该挺多人需要的,那就造一个分享吧。

    • 2、公司有自己的一个直播项目,看其他直播app都有小屏幕可拖拽播放的view(如下图),虽然还没有这个需求,早点准备好。

    截图来自某牙直播
    • 3、而且很久没分享了,像往常一样,封装轮子的过程都会详细介绍,分享更多的都是封装的思想。

    • 4、来看看效果图先吧:

      演示效果图,还可以吧

    二、功能分析(针对所有控件)

    • 1、可拖拽。最基本的功能,拖出父容器松手后可复位,可关闭。

    • 2、拖拽不遮盖。同级层次的控件,如果拖拽过程中出现重叠,会显示在最上层。

    • 3、可吸附边界。吸附这点参考苹果的AssistiveTouch,只能在屏幕的左边或者右边,可关闭。

    • 4、弹簧效果。如果超出屏幕,会有弹簧效果,这点参考scrollView 的 bounces 效果,可关闭。

    • 5、支持xib、storyboard 参数设置。很多控件都是在xib或storyboard 中创建,此时可通过,看下图:

    支持xib、storyboard 参数设置

    三、API 分析设计

    • 1、是否允许拖拽,默认关闭,支持xib、storyboard 参数设置
    /**
     *  @author gitKong
     *
     *  是否允许拖拽,默认关闭(可以在XIB或SB中设置)
     */
    @property (nonatomic,assign)IBInspectable BOOL fl_canDrag;
    
    • 2、是否需要边界弹簧效果,默认开启,支持xib、storyboard 参数设置
    /**
     *  @author gitKong
     *
     *  是否需要边界弹簧效果,默认开启(可以在XIB或SB中设置)
     */
    @property (nonatomic,assign)IBInspectable BOOL fl_bounces;
    
    • 3、是否需要吸附边界效果,默认开启(可以在XIB或SB中设置
    /**
     *  @author gitKong
     *
     *  是否需要吸附边界效果,默认开启(可以在XIB或SB中设置)
     */
    @property (nonatomic,assign)IBInspectable BOOL fl_isAdsorb;
    

    四、功能实现分析

    • 1、分类或继承实现。因为需要支持所有控件,我们都知道控件都是直接或者间接继承 UIView ,此时可以有两种办法实现,继承分类 ,此时我是用分类实现的,至于为什么呢?

      • (1)、如果我当前的view是已经继承了另一个自定义view,而且功能很独立,此时如果要给当前view添加拖拽功能的话,就必须融合两个功能的代码,这将变得很麻烦,而且会很乱。

      • (2)、如果我需要给一个按钮添加拖拽功能,那么继承就没办法实现了,因为你给这个按钮修改了继承,就没了自带的功能了。

    • 2、监听拖拽。拖拽事件可以通过 - (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event 方法去监听,也可以通过添加 pan 拖拽手势,至于为什么要用 手势呢?

      • (1)、需要在分类中实现 touchesMoved 方法,此时如果外界也实现了这个方法,那么就很容易起冲突。
      • (2)、虽然动态修改拖拽功能开关,但 会 多次调用 touchesMoved 方法,即使关闭了拖拽功能,相对手势实现就没那么灵活了。
    • 3、Setter 方法里添加pan事件。一开始想到的是通过 runtime 的 Swizzle 替换掉 系统的 init 方法,进而在自己的方法里面实现 拖拽手势添加,但后来考虑到,此时是给UIView 添加分类,而页面上的所有控件都是UIView 的 子类,此时 init 就会调用多次,会造成页面显示慢;于是直接在setter方法里面判断,当需要拖拽的时候,我才添加事件,不需要拖拽的时候移除手势,算是一个小优化。此时还需要记录当前控件在父容器中的 index ,这个等下就知道要用来干嘛。

    • 4、遮盖处理。我们都知道,控件通过 addSubviews 添加到父容器中,是有顺序的,后面添加的会在上层;此时如果我先添加 view1 在添加 view2,我拖拽 view1 到 view2 的时候,就会被 view2 挡住。做法如下:

      • (1)、遍历父类view 的 subViews 数组,判断是否与当前view重合,用系统自带的 CGRectIntersectsRect 方法判断。
      • (2)、在拖拽开始(UIGestureRecognizerStateBegan)的时候,用 bringSubviewToFront 将拖拽的view 移到最上层。
      • (3)、在拖拽结束(UIGestureRecognizerStateEnd)的时候,判断此时状态是否还重合,如果不重合,通过 insertSubview 将控件重置回原来的顺序(通过上面第三点记录的 index
    • 5、支持xib、storyboard 参数设置。这个只需要添加一个 关键字修饰就行 IBInspectable ,用法可以看我API 设计,这个主要作用是使view内的变量可视化,并且可以修改后马上看到

    • 6、弹簧效果和吸附效果。这个可以使用UIView 的 动画就可以实现,此时有一个注意点,判断吸附到左边还是右边,比较的应该是绝对位置,而不是相对位置,需要加上父类的x值

    if (gesR.view.fl_centerX + self.superview.fl_x > self.superview.fl_centerX) {
        [UIView animateWithDuration:0.25 animations:^{
            gesR.view.center = CGPointMake(self.superview.fl_width - self.fl_width / 2, y);
        }];
        
    }
    else{
        [UIView animateWithDuration:0.25 animations:^{
            gesR.view.center = CGPointMake(self.fl_width / 2, y);
        }];
    }
    
    计算小坑

    五、注意点:

    • 1、如果你是使用约束来布局的话,此时可能出现当你拖拽出一定范围后,能正常停留在当前位置;但当你此时拖拽后的位置在约束好的位置附近,就会被吸附回去,如下图:(此时图片是使用约束布局
    使用约束布局可能会出现这种情况
    • 2、如果手势失败,会有断言提示。

    六、总结

    • 1、为了方便大家使用,支持cocoapod,通过 pod search FLDragView 就能搜到。如果你搜不到,先清理一下吧,执行 rm ~/Library/Caches/CocoaPods/search_index.json 执行完重新 search 就行

      cocoapod
    • 2、代码不难实现,具体代码就不拷贝上来了,代码中计算相对多一点,文字分析应该比较清楚了,如果还有什么其他问题,尽管找我。

    • 3、Github地址 ,欢迎大家关注我,喜欢给个star 和 like ,你的支持是我最大的动力,会随时更新原创文章喔!

    相关文章

      网友评论

      • 后浪普拉斯:你好,问一下,将视频添加到悬浮视图上拖不动,是不是渲染导致的拖拽不动。。
        gitKong:@AlexYangle 我刚试过是可以的,应该是你代码问题,可以clone我最新demo看看效果
        后浪普拉斯:@gitKong 我直接继承你的view的计算,直接加载view是可以的,但是我将播放器放在上面,视频是在播放,出现拖拽不动的情况。
        gitKong:@AlexYangle 应该不会,是不是手势冲突了
      • zhao1zhihui:大神能不能写一个可以旋转同时改变文字大小的textview 我写了一个效果不是很好
        gitKong:@zhao1zhihui 我最近都没空帮你写,你可以看看YY的,貌似都实现了
        zhao1zhihui:@gitKong 一个输入框默认有个大小可以输入文字文字默认有个字号输入时如果文字过多输入框变大支持换行 最大有个默认值在输入字体变小。输入完成支持拖动一个按钮。 旋转放大缩小一个按钮。字体自适应如果缩小到最小字体不允许缩放 谢谢大神 我自己写了个效果太差了
        gitKong:@zhao1zhihui 字体旋转?
      • 难却却:刚好想要了解下,^_^

      本文标题:可拖拽的小窗口,最好用?

      本文链接:https://www.haomeiwen.com/subject/cfshvttx.html