最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

ios實(shí)現(xiàn)底部PopupWindow的示例代碼(底部彈出菜單)

 更新時(shí)間:2018年01月02日 11:10:35   作者:林天涯  
這篇文章主要介紹了ios實(shí)現(xiàn)底部PopupWindow的示例代碼(底部彈出菜單),小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧

前言

在Android中要實(shí)現(xiàn)底部彈出菜單很容易,有專門的PopupWindow類,我們只需要用xml訂制好其內(nèi)容View以及設(shè)置其彈出位置即可,非常容易。但是,在ios中就不能這么直接了,沒(méi)有現(xiàn)成的東西,需要自己想辦法來(lái)實(shí)現(xiàn)。

思路分析

  1. 反正最終一定要實(shí)現(xiàn)效果,那么內(nèi)容View一定要解決掉,那么是在Interface Builder編輯實(shí)現(xiàn)還是直接用代碼實(shí)現(xiàn)呢?答案是都可以,但為了方便和訂制相對(duì)比較規(guī)范,建議用interface Builder編輯。
  2. 內(nèi)容ok了,那么內(nèi)容放在哪里?這是個(gè)核心問(wèn)題,也就是確定PopupWindow的容器。我們知道ios視圖的層級(jí)結(jié)構(gòu)是Window->RootView->各種組件。顯然PopupWindow要么放在Window中要么放在RootView中,但是如果放在RootView勢(shì)必會(huì)影響RootView中原來(lái)的組件,而且與PopupWindow這個(gè)名字也不相符。所以,理想的容器就是Window。
  3. 如何彈出的問(wèn)題,其實(shí)這個(gè)比較好解決,彈出時(shí)就把PopupWindow加入到容器,消失時(shí)就把它從容器中移除。要實(shí)現(xiàn)從底部彈出,從底部消失的效果,只需要借助UIView動(dòng)畫,變換起始坐標(biāo)就可以了,比較容易。

具體實(shí)現(xiàn)

UI

用Interface Builder實(shí)現(xiàn),ViewController直接選用UIViewController,內(nèi)部選的是UICollectionView方便動(dòng)態(tài)更新,當(dāng)然這個(gè)根據(jù)需要隨意。布局用AutoLayout就不用多說(shuō)了,比較簡(jiǎn)單。直接上圖:

 

注意此ViewController的RootView就是我們需要添加到Window的view,為了效果,將其背景色置為clearcolor。將其中交互的組件右鍵拖拽到PopupWindow類形成映射。

彈出

將RootView添加到Window中,并顯示在最前面。直接上代碼:

func create()-> PopupWindow {
    let window = UIApplication.shared.keyWindow
    window?.addSubview(self.view)
    window?.bringSubview(toFront: self.view)
    self.view.frame = CGRect(x: 0, y: UIScreen.main.bounds.height, width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height)
    UIView.animate(withDuration: 0.3) {
      animation in
      self.view.frame = CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height)
    }
    return self
  }

這里關(guān)鍵就是addSubView方法添加到Window,bringSubView顯示到前臺(tái)。UIView動(dòng)畫將view的y坐標(biāo)由屏幕高度改變?yōu)?,從而實(shí)現(xiàn)由底部彈出效果。

這里返回自身對(duì)象是為了方便鏈?zhǔn)皆O(shè)置組件屬性和其他屬性。

添加交互功能

雖然現(xiàn)在已經(jīng)可以彈出PopupWindow了,但并不具有交互功能。并且我們?yōu)榱吮阌趶?fù)用,不會(huì)把交互的功能直接寫在PopupWindow中,而是根據(jù)需要寫在調(diào)用它的地方。這里有兩種方式:

  1. 以協(xié)議的方式,把方法寫在協(xié)議中,調(diào)用部分實(shí)現(xiàn)這個(gè)協(xié)議并重寫回調(diào)函數(shù),這和Android的接口基本一致。
  2. 以函數(shù)作為參數(shù)類型的方式,調(diào)用部分通過(guò)傳遞函數(shù)類型參數(shù)至PopupWindow,而在調(diào)用部分以閉包或者尾隨閉包的形式添加交互功能。

兩種方式一般都可以隨性,但第一種適合交互函數(shù)比較多的時(shí)候。第二種適合于同一調(diào)用類中出現(xiàn)多個(gè)地方不同調(diào)用,一些設(shè)置屬性也不相同。

我們這里選擇第一種,以協(xié)議的方式:

protocol PopupWindowDelegate {
  func attach()
  func detach()
  func rename()
  func delete()
  func control()
}

這里具體函數(shù)完全不用管它,是從項(xiàng)目中截取的。

當(dāng)然我們需要在PopupWindow中定義一個(gè)該協(xié)議類型的變量:

public var delegate: PopupWindowDelegate?

通過(guò)協(xié)議對(duì)象來(lái)調(diào)用交互函數(shù):

func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
    let row = indexPath.row
    switch itemsString[row] {
      case "attach":
      delegate?.attach()
      cancel()
      case "detach":
      delegate?.detach()
      cancel()
      case "rename":
      delegate?.rename()
      cancel()
      case "delete":
      delegate?.delete()
      cancel()
      case "control":
      delegate?.control()
      cancel()
    default:
      break
    }
  }

這是UICollectionView item的選擇函數(shù),這里不多說(shuō)。注意協(xié)議對(duì)象對(duì)其函數(shù)的調(diào)用,這里只相當(dāng)于一種綁定。真正的調(diào)用在調(diào)用地方對(duì)協(xié)議對(duì)象的賦值。

除了這些還有一個(gè)最重要的東西,就是聲明對(duì)于PopupWindow對(duì)象的一個(gè)強(qiáng)引用,如果這個(gè)不存在,交互功能依然不可用。原因是為了防止當(dāng)前對(duì)象被回收掉,有了強(qiáng)引用,只有強(qiáng)引用置空時(shí),對(duì)象才能被回收掉。

var strongSelf: PopupWindow?

引用賦值即可以放在彈出函數(shù)create()中,也可以放在viewDidLoad()中,執(zhí)行順序是彈出函數(shù)create()在前。這里放在viewDidLoad()中的:

override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view.
    self.view.backgroundColor = UIColor.init(white: 0, alpha: 0)
    let gesture = UITapGestureRecognizer(target: self, action: #selector(cancel))
    gesture.delegate = self
    self.dismissView.addGestureRecognizer(gesture)
    self.collectionView.delegate = self
    self.collectionView.dataSource = self
    strongSelf = self
  }

里面對(duì)于UICollectionView的操作可以忽略,dismissView是取消PopupView的按鈕,當(dāng)然并沒(méi)有用UIButton,用的是UIView,所以要手動(dòng)添加點(diǎn)擊事件。

取消

取消PopupWindow比較簡(jiǎn)單,將view從其容器中移除,并將其強(qiáng)引用置空。為了實(shí)現(xiàn)從底部消失的效果,仍然用UIView動(dòng)畫變換y坐標(biāo)實(shí)現(xiàn)。

func cancel() {
    UIView.animate(withDuration: 0.3) {
      animation in
      self.view.frame = CGRect(x: 0, y: UIScreen.main.bounds.height, width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height)
    }
    DispatchQueue.main.asyncAfter(deadline: .now()+0.3) {
      self.view.removeFromSuperview()
    }
    strongSelf = nil
  }

調(diào)用

在調(diào)用類中實(shí)現(xiàn)PopupWindowDelegate協(xié)議,重寫交互函數(shù)。創(chuàng)建PopupWindow對(duì)象,并設(shè)置委托屬性和其他屬性。

let popupWindow = UIStoryboard(name: "DefiniteUI", bundle: nil).instantiateViewController(withIdentifier: "popup") as! PopupWindow
popupWindow.delegate = self
popupWindow.create().setItems(value: items)

效果

彈出PopWindow:

 

取消PopWindow:

 

后記

舉一反三,除了PopupWindow,類似的各種自定義的Dialog都可以這樣去實(shí)現(xiàn),讀者可以去試試。以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • iOS實(shí)現(xiàn)短信驗(yàn)證碼倒計(jì)時(shí)

    iOS實(shí)現(xiàn)短信驗(yàn)證碼倒計(jì)時(shí)

    這篇文章主要介紹了iOS實(shí)現(xiàn)短信驗(yàn)證碼倒計(jì)時(shí)功能,一種方法是利用NSTimer計(jì)時(shí)器,另一種方法是利用GCD實(shí)現(xiàn)短信驗(yàn)證碼倒計(jì)時(shí),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-12-12
  • Mac OS自帶了apache基本用法總結(jié)

    Mac OS自帶了apache基本用法總結(jié)

    這篇文章主要介紹了Mac OS自帶了apache基本用法總結(jié),小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-05-05
  • iOS開(kāi)發(fā)中多線程的安全隱患總結(jié)

    iOS開(kāi)發(fā)中多線程的安全隱患總結(jié)

    在本篇文章中小編給大家整理了關(guān)于iOS開(kāi)發(fā)中多線程的安全隱患的知識(shí)點(diǎn),需要的朋友們學(xué)習(xí)參考下。
    2019-07-07
  • iOS中最全的各種定時(shí)器使用教程

    iOS中最全的各種定時(shí)器使用教程

    這篇文章主要給大家介紹了關(guān)于iOS中最全的各種定時(shí)器的使用教程,文中通過(guò)示例代碼介紹的非常詳細(xì),通過(guò)文中介紹的最全的定時(shí)器相信會(huì)對(duì)各位iOS開(kāi)發(fā)者們帶來(lái)一定的幫助,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧。
    2017-09-09
  • iOS項(xiàng)目開(kāi)發(fā)鍵盤彈出遮擋輸入框問(wèn)題解決方案

    iOS項(xiàng)目開(kāi)發(fā)鍵盤彈出遮擋輸入框問(wèn)題解決方案

    大家在用IOS開(kāi)發(fā)項(xiàng)目的時(shí)候,經(jīng)常出現(xiàn)鍵盤彈出遮擋輸入框問(wèn)題,小編給大家整理的這個(gè)問(wèn)題的處理方法,一起學(xué)習(xí)下。
    2018-01-01
  • IOS開(kāi)發(fā)之路--C語(yǔ)言存儲(chǔ)方式和作用域

    IOS開(kāi)發(fā)之路--C語(yǔ)言存儲(chǔ)方式和作用域

    只有你完全了解每個(gè)變量或函數(shù)存儲(chǔ)方式、作用范圍和銷毀時(shí)間才可能正確的使用這門語(yǔ)言。今天將著重介紹C語(yǔ)言中變量作用范圍、存儲(chǔ)方式、生命周期、作用域和可訪問(wèn)性。
    2014-08-08
  • iOS基礎(chǔ)動(dòng)畫教程分享

    iOS基礎(chǔ)動(dòng)畫教程分享

    這篇文章主要為大家詳細(xì)介紹了iOS幾種基礎(chǔ)動(dòng)畫教程,包括位置動(dòng)畫、透明度動(dòng)畫、大小動(dòng)畫等,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2016-11-11
  • iOS中 UIActionSheet字體的修改

    iOS中 UIActionSheet字體的修改

    這篇文章主要介紹了iOS中 UIActionSheet字體的修改,需要的朋友可以參考下
    2017-06-06
  • iOS 實(shí)現(xiàn)跑馬燈效果的方法示例

    iOS 實(shí)現(xiàn)跑馬燈效果的方法示例

    可能說(shuō)起跑馬燈,大家第一個(gè)會(huì)想到的就是山寨機(jī)。但接下來(lái)這篇文章介紹的跑馬燈和那個(gè)跑馬燈是不一樣滴。在iOS中,跑馬燈是指label上的字自動(dòng)滾動(dòng),形成類似跑馬燈似的條幅。下面通過(guò)這篇文章我們來(lái)一起看看iOS 實(shí)現(xiàn)跑馬燈效果的方法,有需要的朋友們可以參考借鑒。
    2017-01-01
  • iOS開(kāi)發(fā)--仿新聞首頁(yè)效果WMPageController的使用詳解

    iOS開(kāi)發(fā)--仿新聞首頁(yè)效果WMPageController的使用詳解

    這篇文章主要介紹了iOS開(kāi)發(fā)--仿新聞首頁(yè)效果WMPageController的使用詳解,詳解的介紹了iOS開(kāi)發(fā)中第三方庫(kù)WMPageController控件的使用方法,有需要的可以了解下。
    2016-11-11

最新評(píng)論

临安市| 濉溪县| 东台市| 曲周县| 西林县| 新营市| 营口市| 齐齐哈尔市| 兰西县| 定安县| 富蕴县| 竹北市| 织金县| 沙坪坝区| 金昌市| 定州市| 翁源县| 南雄市| 六安市| 嘉定区| 二连浩特市| 剑川县| 原阳县| 富锦市| 邓州市| 扶沟县| 时尚| 璧山县| 鄂托克前旗| 子长县| 寿阳县| 隆回县| 宜君县| 金坛市| 扶绥县| 巩留县| 滦南县| 无锡市| 淮阳县| 砚山县| 辽源市|