摘要

在學習小程式時,看到小程式中的一個樣式屬性 hover-class,通過設定這個屬性,就可以給點選的控制元件新增一個高亮效果。所以也就萌生了在 Swift 也實現一個類似的功能的想法,開幹。

下面程式碼是給 view 控制元件新增一個高亮效果,高亮時,頁面的背景顏色會 0.8 的透明度顯示

// html 頁面
<view class="tool-bar my-class"
hover-class="hover"
hover-stay-time="50">
<image src="{{icon}}"/>
<text>{{title}}</text>
</view>
// css 頁面
.hover {
opacity: .8;
}

設定 Button

先敲定一個簡單的需求,設定一個按鈕的背景顏色,當按鈕高亮狀態時,背景顏色 0.8 透明度顯示。

看 UIButton 類中,setBackgroundImage(, for: ) 函式,可以讓按鈕在預設狀態(.normal)和高亮狀態(.highlighted)下,顯示不同的背景圖片,這裡可以通過 color 來建立純色的圖片處理。

// MARK: - 設定按鈕高亮
/// 設定按鈕背景和高亮狀態顏色
///
/// 設定的 color 是按鈕背景顏色,高亮狀態下,背景顏色會有 0.8 的 alpha
///
/// - Parameter color: 背景顏色
func setBackgroundAndHighlighted(with color: UIColor) { self.btn.setBackgroundImage(getImageFrom(color: color), for: .normal)
self.btn.setBackgroundImage(getImageFrom(color: color.withAlphaComponent(0.8)), for: .highlighted)
}

實現程式碼的時候,使用了函式 withAlphaComponent,它屬於 UIColor 類的,達到的效果是,將 color 顏色設定它的 alpha,返回一個新的 color 物件。

這個方法專門測試一下啊,比如 0.8 的 white,使用這個函式設定成 0.6 時,返回的是 0.6 的 white,而不是 0.8x0.6 的 white。

建立單色 image

下面程式碼是建立單色 image,給到按鈕,這裡使用的是 UIGraphics 框架處理圖片。

  /// 設定單色圖片
/// - Parameter color: 顏色
/// - Returns: 返回該顏色圖片
func getImageFrom(color: UIColor) -> UIImage? {
let rect = CGRect(x: 0, y: 0, width: 1, height: 1)
UIGraphicsBeginImageContext(rect.size)
guard let context = UIGraphicsGetCurrentContext() else {
print(" UIGraphicsGetCurrentContext 不存在")
UIGraphicsEndImageContext()
return nil
}
context.setFillColor(color.cgColor)
context.fill(rect)
let img = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return img
}

Highlighted(高亮)

需求是實現完了,接下來看一下 Highlighted 是什麼:

highlighted 是控制元件的高亮顯示,這裡首先明確了它屬於 UIControl 類。那麼怎麼理解高亮顯示呢?釋義這樣說,當觸控事件進入控制元件的邊界時,控制元件會高亮顯示;當觸控事件離開(比如點選按鈕時,鬆開按鈕,touch-up)或者超出控制元件的邊界時,控制元件會失去高亮顯示。並且可以通過 isHighlighted 屬性檢視控制元件是否高亮狀態,也可以設定它,讓控制元件保持高亮或者非高亮狀態。

Event(事件)

highlighted 的釋義中多次提到觸控事件,那麼順勢看看能影響到高亮的幾個觸控事件,先上總結:

  • touchDown 是手指按到控制元件的操作;
  • touchDrag 是手指在控制元件中拖動的操作;
  • touchUp 是手指從控制元件中鬆開的操作;
  • 最後一個 touchCancle 就是關閉操作。

如果理解,就簡單過一下程式碼塊

/// 點選事件
public static var touchDown: UIControl.Event { get }
/// 重複點選事件
public static var touchDownRepeat: UIControl.Event { get }
/// 被拖動到控制元件邊界內事件
public static var touchDragInside: UIControl.Event { get }
/// 被拖動到控制元件邊界外事件
public static var touchDragOutside: UIControl.Event { get }
/// 被拖動到控制元件邊界事件
public static var touchDragEnter: UIControl.Event { get }
/// 手指從控制元件內拖動到它的邊界外事件
public static var touchDragExit: UIControl.Event { get }
/// 當手指在控制元件邊界內的事件
public static var touchUpInside: UIControl.Event { get }
/// 當手指超出控制元件邊界中的事件
public static var touchUpOutside: UIControl.Event { get }
/// 取消當前觸控的系統事件
public static var touchCancel: UIControl.Event { get }

依據 heighlighted 釋義並多次測試之後,推斷當 touchDown 時候 heighlighted 高亮, 當 touchDrageOutsidetouchUpInside 或者 touchDragExit 時,heightlighted 沒有高亮效果。

之後就可以設定這幾個點選事件,去自定義是否高亮事件,以及做對應的事件處理。

Button 為什麼可以設定高亮?

看程式碼結構,UIButton 是繼承自 UIControl 的,而 UIButton 類中只是設定樣式等函式,關於 Event 事件都在 UIControl 類中。

那麼就可以大致梳理一下,UIControl 中有監聽 Event 事件的方法,通過監聽 Event 的不同 State,設定 isHighlighted,然後 isHighlighted 的屬性監聽檢測到變化時,處理 UIButton 中提前設定的程式碼。

由此可以總結,UIButton 就是一個對 UIControl 和 View 的封裝,只要是繼承 UIControl 類的子類,都可以使用它的高亮屬性,或者自定義高亮監聽相關事件。