iOS氣泡提示工具BubblePopup的使用

2023-06-09 18:01:37
 
在平時的開發中,通常新手引導頁或功能提示頁會出現氣泡彈窗來做提示。如果遇到了這類功能通常需要花費一定的精力來寫這麼一個工具的,這裡寫了一個氣泡彈窗工具,希望能幫你提升一些開發效率。
 
使用方法
1.從gitHub上下載程式碼到本地,程式碼地址:https://github.com/zhfei/BubblePopup
2.呼叫BubblePopupManager檔案內的單例方法,在指定的頁面上新增氣泡提示。
普通文字氣泡彈窗使用方式如下:
BubblePopupManager.shared.addPopup(toView: self.view, tips: "冒泡彈窗", popupType: .dotLine, positionType: .bottom, popupPoint: nil, linkPoint: CGPoint(x: sender.frame.midX, y: sender.frame.minY), maxWidth: 200.0)
自定義View氣泡彈窗使用方式如下:
BubblePopupManager.shared.addPopup(toView: self.view, customContentView: MyContentView(), popupType: .triangle, positionType: .bottom, popupPoint: CGPoint(x: sender.frame.midX, y: sender.frame.minY), linkPoint: nil, maxWidth: 200.0)
 注意:自定義內容View只能使用frame佈局,不能使用約束。
 
設計模式
氣泡彈窗View的結構設計採用的設計模式為組合模式
把氣泡彈窗分為3個部分:氣泡背景,氣泡指示器,氣泡提示內容。
在建立氣泡彈窗時,根據子類的自定義實現,將這三部分分別建立並組裝到一起。實現了功能的靈活插拔和自定義擴充套件。


氣泡彈窗生成演演算法採用的設計模式為模版方法模式
在氣泡構建基礎類別中設定好氣泡的構建步驟,把必要的部分或者提供預設實現的部分在父類別中提供預設的實現,對其他需要自定義實現的部分,只在父類別中寫了一個抽象方法,具體實現交給子類自己實現。
虛線氣泡彈窗類圖

三角形氣泡彈窗類圖

 
核心實現
BubblePopupManager: 使用氣泡彈窗工具的入口,通過它建立並新增一個氣泡彈窗到指定的View上。
BubblePopupBuilder: 氣泡彈窗構建者基礎類別,使用模版方法模式定義了氣泡的構建流程,子類可以自定義各自的實現。
DotLineBubblePopupBuilder:虛線氣泡彈窗基礎類別,它是基礎類別BubblePopupBuilder的子類,內部包含了虛線氣泡彈窗生成時所需要的工具方法和必要屬性,方便建立top,bottom,left,right虛線氣泡彈窗。
TriangleBubblePopupBuilder :三角形氣泡彈窗基礎類別,它是BubblePopupBuilder的子類,內部包含了三角形氣泡彈窗生成時所需要的工具方法和必要屬性,方便建立top,bottom,left,right三角形氣泡彈窗
BubblePopup:氣泡彈窗View,它內部使用組合模式將子部件組合起來,組成了一個氣泡彈窗。
BubbleViewFactory: 氣泡彈窗子檢視建立工程,用於建立氣泡彈窗所需要的子檢視,並將各個子檢視組裝成一個最終的氣泡彈窗。

BubblePopupBuilder
BubblePopupBuilder是所有氣泡彈窗的公共基礎類別,對於裡面定義的屬性和方法的功能分別為
屬性:屬性裡儲存的是氣泡彈窗公共的,必要的資料。
方法:在基礎類別提供的方法中主要用於定義氣泡的構建流程。
核心方法如下:
func setupUI() {
    addBubbleContentView(to: bubblePopup)
    addBubbleBGView(to: bubblePopup)
    updateLayout(to: bubblePopup)
    addBubbleFlagView(to: bubblePopup)
}
其中氣泡內容展示檢視和氣泡背景檢視有預設實現,子類可以直接使用預設樣式。
而氣泡標識View和氣泡佈局方法則需要子類自己實現,因為不同型別的氣泡彈窗它們的氣泡標識設佈局方式是不一樣的。

DotLineBubblePopupBuilder
虛線氣泡基礎類別DotLineBubblePopupBuilder,它繼承自BubblePopupBuilder
屬性:增加了虛線彈窗必要的linkPoint屬性,即:虛線與氣泡彈窗的連線點。
增加了一個座標系轉換懶載入屬性,用於將使用者設定的螢幕座標點轉成氣泡內部的檢視座標系中的點。
重要方法說明:
getDrawDotLineLayerRectParams
用於虛線圖層繪製:獲取虛線繪製時所需要的繪製元素座標,如:虛線的開始,結束座標,連線點圓的直徑等。
getDotLineLayerContainerViewFrame
更新虛線容器View的位置大小資訊:獲取不同情況下的虛線容器Frame。
layoutDotLineBubblePopupView
更新虛線氣泡彈窗的frame。
updateBGBubbleViewFrame
更新氣泡背景的frame。

這裡提供的方法屬於工具方法,子類可以通過傳遞自己的型別來得到對應的結果。這裡按道理可以使用設計模式中策略模式來對演演算法進行封裝,如:在基礎類別定義一個抽象方法,將上面則4個工具方法分拆到各自的子類中,讓子類在對應的自己的類中實現這個方法。
這裡沒有這樣做原因是:這些方法在子類中的實現程式碼並不複雜,用一個方法根據條件集中返回是比較方便的,而分拆到不同類中反而很麻煩。所以選擇在基礎類別中以方法工具的形式統一放置了。

DotLineTopBubblePopupBuilder
top型虛線氣泡彈窗DotLineTopBubblePopupBuilder,它繼承自DotLineBubblePopupBuilder,屬於一直具體的彈窗型別。
它裡面只對下面兩個方法進行了重寫,根據自己的型別進行子類個性化實現。
override func updateLayout
override func addBubbleFlagView

具體實現如下:

class DotLineTopBubblePopupBuilder: DotLineBubblePopupBuilder {
    
    override func updateLayout(to bubblePopup: BubblePopup) {
        layoutDotLineBubblePopupView(bubblePopup: bubblePopup, positionType: .top)
    }
    
    override func addBubbleFlagView(to bubblePopup: BubblePopup) {
        assert(!self.targetPoint.equalTo(.zero), "氣泡提示點無效")
        
        let flagFrame = getDotLineLayerContainerViewFrame(position: .top, targetPoint: self.targetPoint)
        let params = getDrawDotLineLayerRectParams(position: .top)
        let flagBubbleView = BubbleViewFactory.generateDotLineBubbleFlagView(flagFrame: flagFrame, position: .top, params: params)
        bubblePopup.bubbleFlagView = flagBubbleView
        bubblePopup.addSubview(flagBubbleView)
    }
    
}
其他bottom, left, right型別相似。

TriangleBubblePopupBuilder
三角形氣泡基礎類別TriangleBubblePopupBuilder,它繼承自BubblePopupBuilder 
屬性:相對於基礎類別增加了popupPoint屬性,它是三角形頂點指向的座標點
增加了一個座標系轉換懶載入屬性,用於將使用者設定的螢幕座標點轉成氣泡內部的檢視座標系中的點。
重要方法說明:
getDrawTriangleLayeyRectParams
為三角形圖層繪製提供不同氣泡型別所需要的繪製元素座標,如:三角形的三個頂點。
getTriangleLayerContainerViewFrame
獲取不同情況下三角形圖層容器的Frame,用於更新三角形圖層容器View的位置大小。
layoutTriangleBubblePopupView
更新三角形氣泡彈窗的frame。
updateTriangleBGBubbleView
更新氣泡背景的frame。

三角形彈窗基礎類別TriangleBubblePopupBuilder的設計方式和虛線彈窗基礎類別是一樣的。
這裡的方法屬於工具方法,子類可以通過傳遞自己的型別來得到對應的結果,通過犧牲一點開發模式的規範化來換取開發效率的提升。
在三角形氣泡基礎類別的下面同樣有4個子類top,bottom,left ,right進行各種的自定義實現。

TriangleTopBubblePopupBuilder
top型三角形氣泡彈窗DotLineTopBubblePopupBuilder,它繼承自DotLineBubblePopupBuilder,屬於一直具體的彈窗型別。

它裡面只對下面這兩個方法做了重寫,根據自己的型別進行子類個性化實現。
override func updateLayout
override func addBubbleFlagView
具體實現如下:
class TriangleTopBubblePopupBuilder: TriangleBubblePopupBuilder {
    override func updateLayout(to bubblePopup: BubblePopup) {
        layoutTriangleBubblePopupView(bubblePopup: bubblePopup, positionType: .top)
    }
    override func addBubbleFlagView(to bubblePopup: BubblePopup) {
        assert(!self.targetPoint.equalTo(.zero), "氣泡提示點無效")
        
        let flagFrame = getTriangleLayerContainerViewFrame(position: .top, targetPoint: self.targetPoint)
        let params = getDrawTriangleLayeyRectParams(position: .top)
        let flagBubbleView = BubbleViewFactory.generateTriangleBubbleFlagView(flagFrame: flagFrame, position: .top, params: params)
        bubblePopup.bubbleFlagView = flagBubbleView
        bubblePopup.addSubview(flagBubbleView)
    }
}
其他bottom, left, right型別相似。
 
彈窗效果展示
三角形氣泡彈窗
 

虛線氣泡彈窗

自定義氣泡彈窗