本文要实现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>