- 视图偏移量 内边距
- 消息发送
- 代码
layout
布局
WeChat3f9f4570329de1a1cfb7b3cdea6dbb8c.png
1. 负责刷新相关的逻辑
处理
///刷新状态到达临界点
private let HWRefreshOffset:CGFloat = 60.0
/// 刷新状态
enum HWRefreshState {
case Normal //普通
case Pulling //超过临界点,没有放手
case WillRefresh //超过临界点 并且放手
}
class HWRefreshControl: UIControl {
//滚动视图的父视图 下拉刷新控件 适用于 tableView/collectionView
private weak var scrollView:UIScrollView?
private lazy var refreshView:HWRefreshView = HWRefreshView.refreshView()
init() {
super.init(frame: CGRect())
setupUI()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
//当添加到俯视图的时候 newSuperview是父视图
override func willMove(toSuperview newSuperview: UIView?) {
super.willMove(toSuperview:newSuperview)
//判断父视图的类型
guard let sv = newSuperview as? UIScrollView else {
return;
}
//记录父视图
scrollView = sv
//KVO 监听父视图的偏移
scrollView?.addObserver(self, forKeyPath:"contentOffset", options: [], context: nil)
}
//从父视图移除
override func removeFromSuperview() {
//移除KVO监听
superview?.removeObserver(self, forKeyPath: "contentOffset")
superview?.removeFromSuperview()
}
//监听方法
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
guard let sv = scrollView else {
return
}
//初始化高度是0
let height = -(sv.contentInset.top + sv.contentOffset.y)
print(sv.contentInset)
if height<0{
return
}
//可以根据高度的设置刷新控件的frame
//y:不能为0 因为self参考的父视图是scollView的content
self.frame = CGRect(x: 0, y: -height, width:sv.bounds.width , height: height)
//判断临界点 只需要判断一次 需要通过刷新状态
if sv.isDragging {
if height > HWRefreshOffset && refreshView.refreshState == .Normal {
refreshView.refreshState = .Pulling
}else if(height <= HWRefreshOffset && refreshView.refreshState == .Pulling){
refreshView.refreshState = .Normal
}
}else{
//放手 --判断是否超过临界点
if refreshView.refreshState == .Pulling {
//开始刷新
beginRefreshing()
//发送刷新数据事件
sendActions(for: .valueChanged)
}
}
}
func beginRefreshing(){
//判断父视图
guard let sv = scrollView else {
return
}
//判断是否正在刷新 如果正在刷新 直接返回
if refreshView.refreshState == .WillRefresh {
return
}
//设置刷新视图的状态
refreshView.refreshState = .WillRefresh
//调整表格间距
var inset = sv.contentInset
inset.top += HWRefreshOffset
sv.contentInset = inset
}
func endRefreshing(){
//判断父视图
guard let sv = scrollView else {
return
}
//判断状态 是否正在刷新 如果不是 直接返回
if refreshView.refreshState != .WillRefresh {
return
}
//设置刷新视图的状态
refreshView.refreshState = .Normal
//调整表格间距
var inset = sv.contentInset
inset.top -= HWRefreshOffset
sv.contentInset = inset
}
deinit {
}
}
extension HWRefreshControl{
private func setupUI(){
backgroundColor = superview?.backgroundColor
//设置超出边界不显示
// clipsToBounds = true
//添加视图
addSubview(refreshView)
//自动布局
refreshView.translatesAutoresizingMaskIntoConstraints = false
addConstraints([NSLayoutConstraint(item: refreshView, attribute: .centerX, relatedBy: .equal, toItem: self, attribute: .centerX, multiplier: 1.0, constant: 0)])
addConstraints([NSLayoutConstraint(item: refreshView, attribute: .bottom, relatedBy: .equal, toItem: self, attribute: .bottom, multiplier: 1.0, constant: 0)])
addConstraints([NSLayoutConstraint(item: refreshView, attribute: .width, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1.0, constant: refreshView.bounds.width)])
addConstraints([NSLayoutConstraint(item: refreshView, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1.0, constant: refreshView.bounds.height)])
}
}
2.刷新视图 负责刷新相关UI
显示和动画
class HWRefreshView: UIView {
///刷新状态
///动画-0.0001 为了符合动画就近原则
var refreshState:HWRefreshState = .Normal{
didSet{
switch refreshState {
case .Normal:
tipLable.text = "继续使劲拉"
//显示提示图标
tipIcon.isHidden = false
//隐藏转圈
indicator.stopAnimating()
UIView.animate(withDuration: 0.25) {
self.tipIcon.transform = CGAffineTransform.identity
}
case .Pulling:
tipLable.text = "放手就刷新"
UIView.animate(withDuration: 0.25) {
self.tipIcon.transform = CGAffineTransform(rotationAngle:CGFloat(Double.pi-0.001))
}
case .WillRefresh:
tipLable.text = "正在刷新中"
//隐藏提示图标
tipIcon.isHidden = true
//显示转圈
indicator.startAnimating()
}
}
}
///提示文字
@IBOutlet weak var tipIcon: UIImageView!
///提示图标
@IBOutlet weak var tipLable: UILabel!
///指示器
@IBOutlet weak var indicator: UIActivityIndicatorView!
class func refreshView()->HWRefreshView{
let nib = UINib(nibName: "HWRefreshView", bundle: nil)
return nib.instantiate(withOwner: nib, options: nil)[0] as! HWRefreshView
}
}
网友评论