本文要實現Android的toast效果, 同時實現loading框, 包括模態和非模態(即是否攔截控件的焦點)。
1、 因為toast文字有長有短, 所有要動態判斷toast文字的寬度。
<pre>
extension UILabel {
//根據最大寬度計算高
func getLableSize(text: String, maxWidth: CGFloat) -> CGRect {
let maxSize = CGSize(width: maxWidth, height: 0) //注意高度是0
// size = text.boundingRectWithSize(size2, options: NSStringDrawingOptions.UsesLineFragmentOrigin, attributes: attributes , context: nil);
let size = text.boundingRect(with: maxSize, options: .usesLineFragmentOrigin,
attributes: [NSFontAttributeName:self.font], context: nil)
return size
}
}</pre>
2、 按鈕的點擊事件:
<pre>
@IBAction func clickButton2(_ sender: Any) {
let toast = ToastView()
toast.showLoadingDlg()
}
@IBAction func clickButton3(_ sender: Any) {
let toast = ToastView()
toast.showToast(text: "網絡連接異常,請稍候再試", pos: .Bottom)
}
@IBAction func showToastTop(_ sender: Any) {
let toast = ToastView()
toast.showToast(text: "您的申請已受理,請耐心等待", pos: .Top)
}
@IBAction func showNoModal(_ sender: Any) {
let toast = ToastView()
toast.showToastExt(text: "非模態toast", pos: .Bottom)
}</pre>
3、以顯示loading為例講解語法, 注意模態和非模態是根據window大小決定的。 如果window的大小跟應用根窗口大小一樣, 那么就是模態, 反之是非模態。
<pre>
func showLoadingDlg() {
let rootRect = UIApplication.shared.windows.first?.frame //應用屏幕大小
let container = UIView() //全屏且透明,蓋在最上面, 可以自定義點擊事件, 從而實現模態和非模態框效果。
container.backgroundColor = UIColor.clear
container.frame = rootRect!
//添加中間矩形黑色區域, 80*80
let bgLength = 90
let bgView = UIView() //黑色半透明方形區域
bgView.frame = CGRect(x: Int((rootRect?.width)!/2) - bgLength/2,
y: Int((rootRect?.height)!/2) - bgLength/2,
width: bgLength,
height: bgLength)
bgView.layer.cornerRadius = 10 //黑色矩形區域的角弧度
bgView.backgroundColor = UIColor(hue: 0, saturation: 0, brightness: 0, alpha: 0.8)
container.addSubview(bgView) //全屏透明背景在中心位置添加矩形黑色區域
//添加圈圈
let indicatorLength: CGFloat = 50 //黑色矩形區域里的旋轉
let indicatorView = UIActivityIndicatorView(activityIndicatorStyle: .white)
indicatorView.frame = CGRect(x: (rootRect?.width)!/2 - indicatorLength/2,
y: (rootRect?.height)!/2 - indicatorLength/2 - 10,
width: indicatorLength,
height: indicatorLength)
indicatorView.startAnimating() //動畫
container.addSubview(indicatorView) //添加旋轉動畫view
//添加文字
let lableX = (rootRect?.width)!/2 - CGFloat(bgLength/2) + 5
let lableY = (rootRect?.height)!/2 + indicatorLength/2 - 10
let lableView = UILabel(frame: CGRect(x: Int(lableX),
y: Int(lableY),
width: bgLength-10,
height: bgLength/2-Int(indicatorLength)/2-5))
lableView.font = UIFont.systemFont(ofSize: 15) //設置系統字體和字號
lableView.textColor = UIColor.white
lableView.text = "加載中"
lableView.textAlignment = .center
container.addSubview(lableView)
//-------------測試代碼-------------
//let size = lableView.getLableSize(text: "網絡異常,請稍候再試", maxWidth: 100)
//-------------測試代碼-------------
let window = UIWindow()
window.backgroundColor = UIColor.clear
window.frame = rootRect! //全屏大小
window.center = CGPoint(x: (rootRect?.width)!/2, y: (rootRect?.height)!/2)
window.windowLevel = UIWindowLevelAlert
window.isHidden = false
window.addSubview(container)
//添加點擊事件
container.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(tapGesture(sender:))))
bufWindows.append(window)
perform(#selector(showFinished(sender:)), with: window, afterDelay: delay)
}
</pre>
4、toast和loading框都是window, 可以動態關閉, 就像gif圖里演示的那樣點擊window所在區域就可以關閉。
<pre>
//添加點擊事件
func tapGesture(sender: UITapGestureRecognizer) {
print("點擊uiview")
//移除最后一個
if bufWindows.count > 0 {
bufWindows.removeLast()
}
NSObject.cancelPreviousPerformRequests(withTarget: self) //可以關閉window, 如果注釋該語句則相當于蓋住了一層透明界面
}
</pre>