iOS開發(fā)--擼一發(fā)類Assistive Touch的懸浮按鈕

前段日子產(chǎn)品覺得滿大街的Tabbar,非要整一個(gè)像系統(tǒng)自帶的Assistive Touch類似的功能按鈕來代替Tabbar的作用,無力吐槽。哎,一直在在猶豫要不要告訴產(chǎn)品 蘋果BABA設(shè)計(jì)這個(gè)Assistive Touch真正的含義是什么啊QAQ!!

無語的是UI悶頭一頓設(shè)計(jì),圖都整出來了。沒辦法,做唄。

趁現(xiàn)在項(xiàng)目不忙幫這個(gè)東西整理出來分享給大家。

懸浮按鈕11.gif

我這邊具體寫一下,實(shí)現(xiàn)的過程。以及在實(shí)現(xiàn)這個(gè)東西遇到的一些坑。發(fā)現(xiàn)問題的童鞋要及時(shí)幫我指出哦。不要讓我出糗哇!

大概

1。主要的控件組成 一個(gè)主按鈕root 和 4個(gè)子按鈕detail組成。
2。布局方面:考慮到這個(gè)懸浮按鈕需要在左右兩邊子按鈕針對(duì)主按鈕有2套布局??赡芪疫@種寫法比較簡(jiǎn)單,帶考究。我令視圖的大小和主按鈕的大小相同,這時(shí)候子按鈕的的布局只要相對(duì)主按鈕布局就可以了(不過這樣會(huì)有一些響應(yīng)事件的問題,下面會(huì)給出解決辦法)。--簡(jiǎn)單的來說這個(gè)控件的大小是縮小之后的視圖大小而非展開后后的視圖大小。

主要代碼實(shí)現(xiàn)

1.讓懸浮控件始終保持在屏幕兩邊

if touchPoint.x > kScreenWidth/2 {
            UIView.animateWithDuration(0.2, animations: {
                self.frame.origin = CGPoint(x: kScreenWidth - CGFloat(kSuspendViewWidth), y: self.touchPoint.y)

            })
        }else {
            UIView.animateWithDuration(0.2, animations: {
                self.frame.origin = CGPoint(x:0, y: self.touchPoint.y)

            })
        }

這個(gè)比較好實(shí)現(xiàn)了 就是判斷 endTouch的坐標(biāo)和屏幕的寬度對(duì)比

2.子按鈕的伸縮動(dòng)畫

UIView.animateWithDuration(0.3, animations: {
                    self.buttonRoot.transform = CGAffineTransformRotate(self.buttonRoot.transform, CGFloat(M_PI_4))

                    self.buttonDetail1.snp_updateConstraints { (make) in

                        make.center.equalTo( CGPoint(x: -kRadius , y: 0))

                    }
                    self.buttonDetail2.snp_updateConstraints { (make) in
                        make.center.equalTo( CGPoint(x: -kRadius * cos(M_PI/6) , y:  -kRadius*cos(M_PI/3)))



                    }
                    self.buttonDetail3.snp_updateConstraints { (make) in
                        make.center.equalTo( CGPoint(x: -kRadius*cos(M_PI/3) , y:  -kRadius*cos(M_PI/6)))


                    }
                    self.buttonDetail4.snp_updateConstraints { (make) in

                        make.center.equalTo( CGPoint(x:0 , y:  -kRadius))
                    }
                    self.layoutIfNeeded()
                })

            }

這邊只列出在左邊出現(xiàn)的情況,以及相關(guān)動(dòng)畫。我用的snapKit約束,只要在annimaton中設(shè)置對(duì)應(yīng)的中心點(diǎn)。中心點(diǎn)的計(jì)算就是一些簡(jiǎn)單的勾股定理 sin cos相信童鞋通一眼就看出來啦。
這邊要提出來的是,更新約束動(dòng)畫要調(diào)用self.layoutIfNeeded()不然沒有動(dòng)畫效果哦。。
3 要記錄懸浮空間的是否處于移動(dòng)狀態(tài)

    override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
         isMoiving = false


    }

    override func touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent?) {
        isMoiving = true

去處理移動(dòng)和點(diǎn)擊的touch 時(shí)間。以及懸浮控件移動(dòng)范圍在touchend中判斷

4.區(qū)分點(diǎn)擊事件和移動(dòng)事件
我在上面的root主按鈕用的button,這就會(huì)導(dǎo)致時(shí)間被button。從而導(dǎo)致移動(dòng)時(shí)間無法處理。
這邊有2個(gè)辦法
--1不用button 換成view 區(qū)分點(diǎn)擊時(shí)間和移動(dòng)時(shí)間(繁瑣)
--2將button接受的時(shí)間繼續(xù)往下傳遞
我們來看下第二種的實(shí)現(xiàn),我創(chuàng)建了一個(gè)button的子類來處理這種有沖突的事件

class IGOSuspendButton: UIButton {

    override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
        self.nextResponder()?.touchesBegan(touches, withEvent: event)
        super.touchesBegan(touches, withEvent: event)

    }
    override func touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent?) {
        self.nextResponder()?.touchesMoved(touches, withEvent: event)
        super.touchesMoved(touches, withEvent: event)

    }
    override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?) {
        self.nextResponder()?.touchesEnded(touches, withEvent: event)
        super.touchesEnded(touches, withEvent: event)

    }

}

重寫 父類touch的3個(gè)方法,將事件傳遞下去。

5.子按鈕事件的響應(yīng)
在開始的時(shí)候我為了布局簡(jiǎn)單,5個(gè)按鈕父視圖的大小我設(shè)置成了主按鈕的大小。這時(shí)候展開的時(shí)候4個(gè)自按鈕的就不在父視圖上了。就會(huì)無法響應(yīng)事件,這時(shí)候我們就需要手動(dòng)指定需要響應(yīng)的事件的視圖

 // MARK: 處理detail btn 超出父視圖 不響應(yīng)事件
    override func hitTest(point: CGPoint, withEvent event: UIEvent?) -> UIView? {
        var view = super.hitTest(point, withEvent: event)
        if view == nil {
            if !self.hidden  {
            if CGRectContainsPoint(buttonDetail1.frame,point) {
                view = buttonDetail1
            }else if CGRectContainsPoint(buttonDetail2.frame,point) {
                view = buttonDetail2
            }else if CGRectContainsPoint(buttonDetail3.frame,point) {
                view = buttonDetail3
            }else if CGRectContainsPoint(buttonDetail4.frame,point) {
                view = buttonDetail4
            }
            }


        }
        return view

    }

使用

創(chuàng)建懸浮按鈕 實(shí)現(xiàn)代理方法CycleTabbarViewDelegate

var suspendButton: CycleTabbarView? = nil
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        suspendButton = CycleTabbarView(frame: CGRect(x: 0, y: 130, width: 60, height: 60) )
        suspendButton?.delegate = self
        self.view.addSubview(suspendButton!)
    }
    func suspendButtonsAction(type: CycleTabbarViewType) {
        switch type {
        case .Type1:
            let alertVC = UIAlertController(title: "11", message: "22", preferredStyle: .Alert)
            alertVC.addAction(UIAlertAction(title: "sure", style: .Cancel, handler: nil))
            self.presentViewController(alertVC, animated: true, completion: nil)
        case .Type2:
            print("")
        case .Type3:
            print("")
        case .Type4:
            print("")

        }
    }

總體寫下來,感覺寫的還是有問題的。畢竟第一次用swift寫項(xiàng)目。有點(diǎn)慌,等項(xiàng)目完成,我在優(yōu)化一下吧。
github地址:https://github.com/dongqihouse/DQWorkDemo/tree/master/SuspendButtonDemo

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 內(nèi)容抽屜菜單ListViewWebViewSwitchButton按鈕點(diǎn)贊按鈕進(jìn)度條TabLayout圖標(biāo)下拉刷新...
    皇小弟閱讀 47,158評(píng)論 22 665
  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 179,034評(píng)論 25 709
  • 咖啡冥想 目標(biāo):可以和家人一起去增城家里住,工作地點(diǎn)也靠近家附近,申請(qǐng)調(diào)職可以成功 時(shí)間要求:2017年7月30日...
    波羅豆閱讀 237評(píng)論 0 0
  • 很早就知道要開源節(jié)流,但是沒有系統(tǒng)的學(xué)習(xí),也沒有什么文字性總結(jié)和輸出。 從最初的銀行零存整取強(qiáng)制性到到現(xiàn)在的股票基...
    一只暴躁的小仙女閱讀 214評(píng)論 0 1
  • 公司:寧波大發(fā)化纖有限公司 姓名:陸小燕 期數(shù):六項(xiàng)精進(jìn)234期學(xué)員 組號(hào):利他三組 [日精進(jìn)打卡第21天] [知...
    牛媽牛媽閱讀 174評(píng)論 0 0

友情鏈接更多精彩內(nèi)容