Files
keyboard/Pods/LSTPopView/LSTPopView/Classes/Code/LSTPopView.m
2025-11-06 13:18:27 +08:00

1776 lines
65 KiB
Objective-C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//
// LSTPopView.m
// LoSenTrad
//
// Created by LoSenTrad on 2020/2/22.
//
#import "LSTPopView.h"
#import <objc/runtime.h>
#import "LSTTimer.h"
static NSString *const LSTPopViewLogTitle = @"LSTPopView日志 ---> :";
static LSTPopViewLogStyle _logStyle;
@interface LSTPopViewManager : NSObject
/** 单例 */
LSTPopViewManager *LSTPopViewM(void);
@end
@interface LSTPopViewManager ()
/** 储存已经展示popView */
@property (nonatomic,strong) NSMutableArray *popViewMarr;
/** 按顺序弹窗顺序存储已显示的 popview */
@property (nonatomic,strong) NSPointerArray *showList;
/** 储存待移除的popView */
@property (nonatomic,strong) NSHashTable <LSTPopView *> *removeList;
/** 内存信息View */
@property (nonatomic,strong) UILabel *infoView;
@end
@implementation LSTPopViewManager
static LSTPopViewManager *_instance;
LSTPopViewManager *LSTPopViewM() {
return [LSTPopViewManager sharedInstance];
}
+ (instancetype)sharedInstance {
if (!_instance) {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_instance = [[self alloc] init];
});
}
return _instance;
}
+ (id)allocWithZone:(struct _NSZone *)zone {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_instance = [super allocWithZone:zone];
});
return _instance;
}
+ (NSArray *)getAllPopView {
return LSTPopViewM().popViewMarr;
}
/** 获取当前页面所有popView */
+ (NSArray *)getAllPopViewForParentView:(UIView *)parentView {
NSMutableArray *mArr = LSTPopViewM().popViewMarr;
NSMutableArray *resMarr = [NSMutableArray array];
for (id obj in mArr) {
LSTPopView *popView = (LSTPopView *)obj;
if ([popView.parentView isEqual:parentView]) {
[resMarr addObject:obj];
}
}
return [NSArray arrayWithArray:resMarr];
}
/** 获取当前页面指定编队的所有popView */
+ (NSArray *)getAllPopViewForPopView:(LSTPopView *)popView {
NSArray *mArr = [self getAllPopViewForParentView:popView.parentView];
NSMutableArray *resMarr = [NSMutableArray array];
for (id obj in mArr) {
LSTPopView *tPopView = (LSTPopView *)obj;
if (popView.groupId == nil && tPopView.groupId == nil) {
[resMarr addObject:obj];
continue;
}
if ([tPopView.groupId isEqual:popView.groupId]) {
[resMarr addObject:obj];
continue;
}
}
return [NSArray arrayWithArray:resMarr];
}
/** 读取popView */
+ (LSTPopView *)getPopViewForKey:(NSString *)key {
if (key.length<=0) { return nil; }
NSMutableArray *mArr = LSTPopViewM().popViewMarr;
for (id obj in mArr) {
LSTPopView *popView = (LSTPopView *)obj;
if ([popView.identifier isEqualToString:key]) {
return popView;
}
}
return nil;
}
+ (void)savePopView:(LSTPopView *)popView {
[LSTPopViewM().popViewMarr addObject:popView];
//优先级排序
[self sortingArr];
if (_logStyle & LSTPopViewLogStyleWindow) {
[self setInfoData];
}
if (_logStyle & LSTPopViewLogStyleConsole) {
[self setConsoleLog];
}
}
/** 移除popView */
+ (void)removePopView:(LSTPopView *)popView {
if (!popView) { return; }
NSArray *arr = LSTPopViewM().popViewMarr;
for (id obj in arr) {
LSTPopView *tPopView = (LSTPopView *)obj;
if ([tPopView isEqual:popView]) {
// [LSTPopViewM().popViewMarr removeObject:obj];
[tPopView dismissWithStyle:LSTDismissStyleNO];
break;
}
}
if (_logStyle & LSTPopViewLogStyleWindow) {
[self setInfoData];
}
if (_logStyle & LSTPopViewLogStyleConsole) {
[self setConsoleLog];
}
}
/** 移除popView */
+ (void)removePopViewForKey:(NSString *)key {
if (key.length<=0) { return; }
NSArray *arr = LSTPopViewM().popViewMarr;
for (id obj in arr) {
LSTPopView *tPopView = (LSTPopView *)obj;
if ([tPopView.identifier isEqualToString:key]) {
// [LSTPopViewM().popViewMarr removeObject:obj];
[tPopView dismissWithStyle:LSTDismissStyleNO];
break;
}
}
if (_logStyle & LSTPopViewLogStyleWindow) {
[self setInfoData];
}
if (_logStyle & LSTPopViewLogStyleConsole) {
[self setConsoleLog];
}
}
/** 移除所有popView */
+ (void)removeAllPopView {
NSMutableArray *arr = LSTPopViewM().popViewMarr;
if (arr.count<=0) { return; }
NSArray *popViewMarr = [NSArray arrayWithArray:LSTPopViewM().popViewMarr];
[popViewMarr enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
LSTPopView *tPopView = (LSTPopView *)obj;
[tPopView dismissWithStyle:LSTDismissStyleNO];
}];
if (_logStyle & LSTPopViewLogStyleWindow) {
[self setInfoData];
}
if (_logStyle & LSTPopViewLogStyleConsole) {
[self setConsoleLog];
}
}
+ (void)removeLastPopView {
NSPointerArray *showList = LSTPopViewM().showList;
for (NSInteger i = showList.count - 1; i >= 0; i --) {
LSTPopView *popView = [showList pointerAtIndex:i];
if (popView) {
[self removePopView:popView];
[showList addPointer:NULL];
[showList compact];
break;
}
}
}
#pragma mark - ***** Other 其他 *****
+ (void)setInfoData {
LSTPopViewM().infoView.text = [NSString stringWithFormat:@"S:%zd R:%zd",LSTPopViewM().popViewMarr.count,LSTPopViewM().removeList.allObjects.count];
}
+ (void)setConsoleLog {
LSTPVLog(@"%@ S:%zd个 R:%zd个",LSTPopViewLogTitle,LSTPopViewM().popViewMarr.count,LSTPopViewM().removeList.allObjects.count);
}
//冒泡排序
+ (void)sortingArr {
NSMutableArray *arr = LSTPopViewM().popViewMarr;
for (int i = 0; i < arr.count; i++) {
for (int j = i+1; j < arr.count; j++) {
LSTPopView *iPopView = (LSTPopView *)arr[i];
LSTPopView *jPopView = (LSTPopView *)arr[j];
if (iPopView.priority > jPopView.priority) {
[arr exchangeObjectAtIndex:i withObjectAtIndex:j];
}
}
}
}
/** 转移popView到待移除队列 */
+ (void)transferredToRemoveQueueWithPopView:(LSTPopView *)popView {
NSArray *popViewMarr = LSTPopViewM().popViewMarr;
[popViewMarr enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
LSTPopView *tPopView = (LSTPopView *)obj;
if ([popView isEqual:tPopView]) {
[LSTPopViewM().removeList addObject:obj];
[LSTPopViewM().popViewMarr removeObject:obj];
}
}];
}
+ (void)destroyInRemoveQueue:(LSTPopView *)popView {
if (LSTPopViewM().removeList.allObjects.count <= 0) {
[self transferredToRemoveQueueWithPopView:popView];
}
if (_logStyle&LSTPopViewLogStyleWindow) {
[self setInfoData];
}
if (_logStyle&LSTPopViewLogStyleConsole) {
[self setConsoleLog];
}
}
#pragma mark - ***** 懒加载 *****
- (UILabel *)infoView {
if(_infoView) return _infoView;
_infoView = [[UILabel alloc] init];
_infoView.backgroundColor = UIColor.orangeColor;
_infoView.textAlignment = NSTextAlignmentCenter;
_infoView.font = [UIFont systemFontOfSize:11];
_infoView.frame = CGRectMake(pv_ScreenWidth()-70, pv_IsIphoneX_ALL()? 40:20, 60, 10);
_infoView.layer.cornerRadius = 1;
_infoView.layer.masksToBounds = YES;
UIView *superView = [UIApplication sharedApplication].keyWindow;
[superView addSubview:_infoView];
return _infoView;
}
- (NSMutableArray *)popViewMarr {
if(_popViewMarr) return _popViewMarr;
_popViewMarr = [NSMutableArray array];
return _popViewMarr;
}
- (NSHashTable<LSTPopView *> *)removeList {
if (_removeList) return _removeList;
_removeList = [NSHashTable hashTableWithOptions:NSPointerFunctionsWeakMemory];
return _removeList;
}
- (NSPointerArray *)showList {
if (_showList) return _showList;
_showList = [NSPointerArray pointerArrayWithOptions:(NSPointerFunctionsWeakMemory)];
return _showList;
}
@end
static const NSTimeInterval LSTPopViewDefaultDuration = -1.0f;
// 角度转弧度
#define LST_DEGREES_TO_RADIANS(angle) ((angle) / 180.0 * M_PI)
@interface LSTPopViewBgView : UIView
/** 是否隐藏背景 默认NO */
@property (nonatomic, assign) BOOL isHideBg;
@end
@implementation LSTPopViewBgView
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event{
UIView *hitView = [super hitTest:point withEvent:event];
if(hitView == self && self.isHideBg){
return nil;
}
return hitView;
}
@end
@interface LSTPopView () <UIGestureRecognizerDelegate>
/** 弹窗容器 默认是app UIWindow 可指定view作为容器 */
@property (nonatomic, weak) UIView *container;
/** 背景层 */
@property (nonatomic, strong) LSTPopViewBgView *backgroundView;
/** 自定义视图 */
@property (nonatomic,strong) UIView *customView;
/** 规避键盘偏移量 */
@property (nonatomic, assign) CGFloat avoidKeyboardOffset;
/** 代理池 */
@property (nonatomic, strong) NSHashTable <id<LSTPopViewProtocol>> *delegates;
/** 背景点击手势 */
@property (nonatomic, strong) UITapGestureRecognizer *tapGesture;
/** 自定义View滑动手势 */
@property (nonatomic, strong) UIPanGestureRecognizer *panGesture;
//当前正在拖拽的是否是tableView
@property (nonatomic, assign) BOOL isDragScrollView;
/** 标记popView中是否有UIScrollView, UITableView, UICollectionView */
@property (nonatomic, weak) UIScrollView *scrollerView;
/** 记录自定义view原始Frame */
@property (nonatomic, assign) CGRect originFrame;
/** 标记dragDismissStyle是否被复制 */
@property (nonatomic, assign) BOOL isDragDismissStyle;
/** 是否弹出键盘 */
@property (nonatomic,assign,readonly) BOOL isShowKeyboard;
/** 弹出键盘的高度 */
@property (nonatomic, assign) CGFloat keyboardY;
@end
@implementation LSTPopView
#pragma mark - ***** 初始化 *****
- (instancetype)initWithFrame:(CGRect)frame {
if (self = [super initWithFrame:frame]) {
[self initSubViews];
}
return self;
}
- (void)initSubViews {
//初始化配置
_isClickBgDismiss = NO;
_isObserverScreenRotation = YES;
_bgAlpha = 0.25;
_popStyle = LSTPopStyleFade;
_dismissStyle = LSTDismissStyleFade;
_popDuration = LSTPopViewDefaultDuration;
_dismissDuration = LSTPopViewDefaultDuration;
_hemStyle = LSTHemStyleCenter;
_adjustX = 0;
_adjustY = 0;
_isClickFeedback = NO;
_isAvoidKeyboard = YES;
_avoidKeyboardSpace = 10;
_bgColor = [UIColor blackColor];
_identifier = @"";
_isShowKeyboard = NO;
_showTime = 0.0;
_priority = 0;
_isHideBg = NO;
_isShowKeyboard = NO;
_isImpactFeedback = NO;
_rectCorners = UIRectCornerAllCorners;
_isSingle = NO;
//拖拽相关属性初始化
_dragStyle = LSTDragStyleNO;
_dragDismissStyle = LSTDismissStyleNO;
_dragDistance = 0.0f;
_dragReboundTime = 0.25;
_dragDismissDuration = LSTPopViewDefaultDuration;
_swipeVelocity = 1000.0f;
_isDragDismissStyle = NO;
}
+ (nullable instancetype)initWithCustomView:(UIView *_Nonnull)customView {
return [self initWithCustomView:customView popStyle:LSTPopStyleNO dismissStyle:LSTDismissStyleNO];
}
+ (nullable instancetype)initWithCustomView:(UIView *_Nonnull)customView
popStyle:(LSTPopStyle)popStyle
dismissStyle:(LSTDismissStyle)dismissStyle {
return [self initWithCustomView:customView
parentView:nil
popStyle:popStyle
dismissStyle:dismissStyle];
}
+ (nullable instancetype)initWithCustomView:(UIView *_Nonnull)customView
parentView:(UIView *)parentView
popStyle:(LSTPopStyle)popStyle
dismissStyle:(LSTDismissStyle)dismissStyle {
// 检测自定义视图是否存在(check customView is exist)
if (!customView) { return nil; }
if (![parentView isKindOfClass:[UIView class]] && parentView != nil) {
LSTPVLog(@"parentView is error !!!");
return nil;
}
CGRect popViewFrame = CGRectZero;
if (parentView) {
popViewFrame = parentView.bounds;
} else {
popViewFrame = CGRectMake(0, 0, pv_ScreenWidth(), pv_ScreenHeight());
}
LSTPopView *popView = [[LSTPopView alloc] initWithFrame:popViewFrame];
popView.backgroundColor = [UIColor clearColor];
popView.container = parentView? parentView : [UIApplication sharedApplication].keyWindow;
popView.customView = customView;
popView.backgroundView = [[LSTPopViewBgView alloc] initWithFrame:popView.bounds];
popView.backgroundView.backgroundColor = [UIColor clearColor];
popView.popStyle = popStyle;
popView.dismissStyle = dismissStyle;
[popView addSubview:popView.backgroundView];
[popView.backgroundView addSubview:customView];
//背景添加手势
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:popView action:@selector(popViewBgViewTap:)];
tap.delegate = popView;
popView.tapGesture = tap;
[popView.backgroundView addGestureRecognizer:tap];
//添加拖拽手势
popView.panGesture = [[UIPanGestureRecognizer alloc] initWithTarget:popView action:@selector(pan:)];
popView.panGesture.delegate = popView;
[popView.customView addGestureRecognizer:popView.panGesture];
// [popView.backgroundView addTarget:popView action:@selector(popViewBgViewTap:) forControlEvents:UIControlEventTouchUpInside];;
// UILongPressGestureRecognizer *customViewLP = [[UILongPressGestureRecognizer alloc] initWithTarget:popView action:@selector(bgLongPressEvent:)];
// [popView.backgroundView addGestureRecognizer:customViewLP];
// UITapGestureRecognizer *customViewTap = [[UITapGestureRecognizer alloc] initWithTarget:popView action:@selector(customViewClickEvent:)];
// [popView.customView addGestureRecognizer:customViewTap];
//键盘将要显示
[[NSNotificationCenter defaultCenter] addObserver:popView
selector:@selector(keyboardWillShow:)
name:UIKeyboardWillShowNotification
object:nil];
//键盘显示完毕
[[NSNotificationCenter defaultCenter] addObserver:popView
selector:@selector(keyboardDidShow:)
name:UIKeyboardDidShowNotification
object:nil];
//键盘frame将要改变
[[NSNotificationCenter defaultCenter] addObserver:popView
selector:@selector(keyboardWillChangeFrame:)
name:UIKeyboardWillChangeFrameNotification
object:nil];
//键盘frame改变完毕
[[NSNotificationCenter defaultCenter] addObserver:popView
selector:@selector(keyboardDidChangeFrame:)
name:UIKeyboardDidChangeFrameNotification
object:nil];
//键盘将要收起
[[NSNotificationCenter defaultCenter] addObserver:popView
selector:@selector(keyboardWillHide:)
name:UIKeyboardWillHideNotification
object:nil];
//键盘收起完毕
[[NSNotificationCenter defaultCenter] addObserver:popView
selector:@selector(keyboardDidHide:)
name:UIKeyboardDidHideNotification
object:nil];
//屏幕旋转
[[NSNotificationCenter defaultCenter] addObserver:popView
selector:@selector(statusBarOrientationChange:)
name:UIApplicationDidChangeStatusBarOrientationNotification
object:nil];
//监听customView frame
[popView.customView addObserver:popView
forKeyPath:@"frame"
options:NSKeyValueObservingOptionOld
context:NULL];
return popView;
}
- (void)dealloc {
[self.customView removeObserver:self forKeyPath:@"frame"];
[[NSNotificationCenter defaultCenter] removeObserver:self];
//从待移除队列中销毁
[LSTPopViewManager destroyInRemoveQueue:self];
[self lst_PopViewDidDismissForPopView:self];
self.popViewDidDismissBlock? self.popViewDidDismissBlock():nil;
}
- (void)removeFromSuperview {
[super removeFromSuperview];
[LSTPopViewManager transferredToRemoveQueueWithPopView:self];
}
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
UIView *hitView = [super hitTest:point withEvent:event];
if (hitView != self.customView) {
if(hitView == self && self.isHideBg){ return nil; }
}
return hitView;
}
#pragma mark - ***** 代理方法 *****
- (void)lst_PopViewBgClickForPopView:(LSTPopView *)popView {
for (id<LSTPopViewProtocol> delegate in _delegates.copy) {
if ([delegate respondsToSelector:_cmd]) {
[delegate lst_PopViewBgClickForPopView:popView];
}
}
}
- (void)lst_PopViewBgLongPressForPopView:(LSTPopView *)popView {
for (id<LSTPopViewProtocol> delegate in _delegates.copy) {
if ([delegate respondsToSelector:_cmd]) {
[delegate lst_PopViewBgLongPressForPopView:popView];
}
}
}
- (void)lst_PopViewWillPopForPopView:(LSTPopView *)popView {
for (id<LSTPopViewProtocol> delegate in _delegates.copy) {
if ([delegate respondsToSelector:_cmd]) {
[delegate lst_PopViewWillPopForPopView:popView];
}
}
}
- (void)lst_PopViewDidPopForPopView:(LSTPopView *)popView {
for (id<LSTPopViewProtocol> delegate in _delegates.copy) {
if ([delegate respondsToSelector:_cmd]) {
[delegate lst_PopViewDidPopForPopView:popView];
}
}
}
- (void)lst_PopViewCountDownForPopView:(LSTPopView *)popView forCountDown:(NSTimeInterval)timeInterval {
for (id<LSTPopViewProtocol> delegate in _delegates.copy) {
if ([delegate respondsToSelector:_cmd]) {
[delegate lst_PopViewCountDownForPopView:popView forCountDown:timeInterval];
}
}
}
- (void)lst_PopViewCountDownFinishForPopView:(LSTPopView *)popView {
for (id<LSTPopViewProtocol> delegate in _delegates.copy) {
if ([delegate respondsToSelector:_cmd]) {
[delegate lst_PopViewCountDownFinishForPopView:popView];
}
}
}
- (void)lst_PopViewWillDismissForPopView:(LSTPopView *)popView {
for (id<LSTPopViewProtocol> delegate in _delegates.copy) {
if ([delegate respondsToSelector:_cmd]) {
[delegate lst_PopViewWillDismissForPopView:popView];
}
}
}
- (void)lst_PopViewDidDismissForPopView:(LSTPopView *)popView {
for (id<LSTPopViewProtocol> delegate in _delegates.copy) {
if ([delegate respondsToSelector:_cmd]) {
[delegate lst_PopViewDidDismissForPopView:popView];
}
}
}
#pragma mark - ***** 界面布局 *****
- (void)setCustomViewFrameWithHeight:(CGFloat)height {
CGFloat changeY = 0;
switch (self.hemStyle) {
case LSTHemStyleTop ://贴顶
{
self.customView.pv_X = _backgroundView.pv_CenterX - _customView.pv_Size.width*0.5 + _adjustX;
self.customView.pv_Y = _adjustY;
changeY = _adjustY;
}
break;
case LSTHemStyleLeft ://贴左
{
self.customView.pv_X = _adjustX;
self.customView.pv_Y = _backgroundView.pv_CenterY - _customView.pv_Size.height*0.5 + _adjustY;
changeY = height*0.5;
}
break;
case LSTHemStyleBottom ://贴底
{
self.customView.pv_X = _backgroundView.pv_CenterX - _customView.pv_Size.width*0.5 + _adjustX;
[self.customView layoutIfNeeded];
self.customView.pv_Y = _backgroundView.pv_Height - _customView.pv_Height + _adjustY;
changeY = height;
}
break;
case LSTHemStyleRight ://贴右
{
self.customView.pv_X = _backgroundView.pv_Width - _customView.pv_Width + _adjustX;
self.customView.pv_Y = _backgroundView.pv_CenterY - _customView.pv_Size.height*0.5 + _adjustY;
changeY = height*0.5;
}
break;
case LSTHemStyleTopLeft :///贴顶和左
{
self.customView.pv_X = _adjustX;
self.customView.pv_Y = _adjustY;
changeY = _adjustY;
}
break;
case LSTHemStyleBottomLeft ://贴底和左
{
self.customView.pv_X = _adjustX;
[self.customView layoutIfNeeded];
self.customView.pv_Y = _backgroundView.pv_Height - _customView.pv_Height + _adjustY;
changeY = height;
}
break;
case LSTHemStyleBottomRight ://贴底和右
{
self.customView.pv_X = _backgroundView.pv_Width - _customView.pv_Width + _adjustX;
[self.customView layoutIfNeeded];
self.customView.pv_Y = _backgroundView.pv_Height - _customView.pv_Height + _adjustY;
changeY = height;
}
break;
case LSTHemStyleTopRight ://贴顶和右
{
self.customView.pv_X = _backgroundView.pv_Width - _customView.pv_Width + _adjustX;
self.customView.pv_Y = _adjustY;
changeY = _adjustY;
}
break;
default://居中
{
self.customView.pv_X = _backgroundView.pv_CenterX - _customView.pv_Size.width*0.5 + _adjustX;
self.customView.pv_Y = _backgroundView.pv_CenterY - _customView.pv_Size.height*0.5 + _adjustY;
changeY = height*0.5;
}
break;
}
CGFloat originBottom = _originFrame.origin.y + _originFrame.size.height + _avoidKeyboardSpace;
if (_isShowKeyboard && (originBottom > _keyboardY)) {//键盘已经显示
CGFloat Y = _keyboardY - _customView.pv_Height - _avoidKeyboardSpace;
_customView.pv_Y = Y;
CGRect newFrame = _originFrame;
newFrame.origin.y = newFrame.origin.y - changeY;
newFrame.size = CGSizeMake(_originFrame.size.width, _customView.pv_Height);
self.originFrame = newFrame;
}else {//没有键盘显示
self.originFrame = _customView.frame;
}
[self setCustomViewCorners];
}
- (void)setCustomViewCorners {
BOOL isSetCorner = NO;
if (self.rectCorners & UIRectCornerTopLeft) {
isSetCorner = YES;
}
if (self.rectCorners & UIRectCornerTopRight) {
isSetCorner = YES;
}
if (self.rectCorners & UIRectCornerBottomLeft) {
isSetCorner = YES;
}
if (self.rectCorners & UIRectCornerBottomRight) {
isSetCorner = YES;
}
if (self.rectCorners & UIRectCornerAllCorners) {
isSetCorner = YES;
}
if (isSetCorner && self.cornerRadius>0) {
UIBezierPath * path = [UIBezierPath bezierPathWithRoundedRect:self.customView.bounds byRoundingCorners:self.rectCorners cornerRadii:CGSizeMake(self.cornerRadius, self.cornerRadius)];
CAShapeLayer * layer = [[CAShapeLayer alloc]init];
layer.frame = self.customView.bounds;
layer.path = path.CGPath;
self.customView.layer.mask = layer;
}
}
#pragma mark - ***** setter 设置器/数据处理 *****
- (void)setPopDuration:(NSTimeInterval)popDuration {
if (popDuration <= 0.0) { return; }
_popDuration = popDuration;
}
- (void)setDismissDuration:(NSTimeInterval)dismissDuration {
if (dismissDuration <= 0.0) { return; }
_dismissDuration = dismissDuration;
}
- (void)setDragDismissDuration:(NSTimeInterval)dragDismissDuration {
if (dragDismissDuration <= 0.0) { return; }
_dragDismissDuration = dragDismissDuration;
}
- (void)setHemStyle:(LSTHemStyle)hemStyle {
_hemStyle = hemStyle;
}
- (void)setAdjustX:(CGFloat)adjustX {
_adjustX = adjustX;
// self.customView.x = _customView.x + adjustX;
// self.originFrame = _customView.frame;
[self setCustomViewFrameWithHeight:0];
}
- (void)setAdjustY:(CGFloat)adjustY {
_adjustY = adjustY;
// self.customView.y = _customView.y + adjustY;
// self.originFrame = _customView.frame;
[self setCustomViewFrameWithHeight:0];
}
- (void)setIsObserverScreenRotation:(BOOL)isObserverScreenRotation {
_isObserverScreenRotation = isObserverScreenRotation;
}
- (void)setBgAlpha:(CGFloat)bgAlpha {
_bgAlpha = (bgAlpha <= 0.0f) ? 0.0f : ((bgAlpha > 1.0) ? 1.0 : bgAlpha);
}
- (void)setIsClickFeedback:(BOOL)isClickFeedback {
_isClickFeedback = isClickFeedback;
}
- (void)setIsHideBg:(BOOL)isHideBg {
_isHideBg = isHideBg;
self.backgroundView.isHideBg = isHideBg;
self.backgroundView.backgroundColor = [self getNewColorWith:self.bgColor alpha:0.0];
}
- (void)setShowTime:(NSTimeInterval)showTime {
_showTime = showTime;
}
- (void)setDelegate:(id<LSTPopViewProtocol>)delegate {
if ([self.delegates containsObject:delegate]) return;
[self.delegates addObject:delegate];
}
- (void)setDragDismissStyle:(LSTDismissStyle)dragDismissStyle {
_dragDismissStyle = dragDismissStyle;
self.isDragDismissStyle = YES;
}
#pragma mark - ***** pop 弹出 *****
- (void)pop {
[self popWithStyle:self.popStyle duration:self.popDuration];
}
- (void)popWithStyle:(LSTPopStyle)popStyle {
[self popWithStyle:popStyle duration:self.popDuration];
}
- (void)popWithDuration:(NSTimeInterval)duration {
[self popWithStyle:self.popStyle duration:duration];
}
- (void)popWithStyle:(LSTPopStyle)popStyle duration:(NSTimeInterval)duration {
[self popWithPopStyle:popStyle duration:duration isOutStack:NO];
}
- (void)popWithPopStyle:(LSTPopStyle)popStyle duration:(NSTimeInterval)duration isOutStack:(BOOL)isOutStack {
NSTimeInterval resDuration = [self getPopDuration:duration];
[self setCustomViewFrameWithHeight:0];
self.originFrame = self.customView.frame;
BOOL startTimer = NO;
if (self.isSingle) {//单显
NSArray *popViewArr = [LSTPopViewManager getAllPopViewForPopView:self];
for (id obj in popViewArr) {//移除所有popView和移除定a时器
LSTPopView *lastPopView = (LSTPopView *)obj;
[lastPopView dismissWithDismissStyle:LSTDismissStyleNO duration:0.2 isRemove:YES];
}
startTimer = YES;
}else {//多显
if (!isOutStack) {//处理隐藏倒数第二个popView
NSArray *popViewArr = [LSTPopViewManager getAllPopViewForPopView:self];
if (popViewArr.count >= 1) {
id obj = popViewArr[popViewArr.count - 1];
LSTPopView *lastPopView = (LSTPopView *)obj;
if (self.isStack) {//堆叠显示
startTimer = YES;
}else {
if (self.priority >= lastPopView.priority) {//置顶显示
if (lastPopView.isShowKeyboard) {
[lastPopView endEditing:YES];
}
[lastPopView dismissWithDismissStyle:LSTDismissStyleFade duration:0.2 isRemove:NO];
startTimer = YES;
} else {//隐藏显示
if (!self.parentView) {
self.container = [UIApplication sharedApplication].keyWindow;
}
[LSTPopViewManager savePopView:self];
return;
}
}
} else {
startTimer = YES;
}
}
}
// if (!isOutStack){
// [self.parentView addSubview:self];
// }
if (!self.superview) {
[self.container addSubview:self];
[LSTPopViewM().showList addPointer:(__bridge void * _Nullable)self];
}
if (!isOutStack){
[self lst_PopViewWillPopForPopView:self];
self.popViewWillPopBlock? self.popViewWillPopBlock():nil;
}
//动画处理
[self popAnimationWithPopStyle:popStyle duration:resDuration];
//震动反馈
[self beginImpactFeedback];
LSTPopViewWK(self);;
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(resDuration * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
if (!isOutStack){
[self lst_PopViewDidPopForPopView:self];
wk_self.popViewDidPopBlock? wk_self.popViewDidPopBlock():nil;
}
if (startTimer){ [self startTimer]; }
});
//保存popView
if (!isOutStack) { [LSTPopViewManager savePopView:self]; }
}
- (void)popAnimationWithPopStyle:(LSTPopStyle)popStyle duration:(NSTimeInterval)duration {
LSTPopViewWK(self);
if (popStyle == LSTPopStyleFade) {//渐变出现
self.backgroundView.backgroundColor = [self getNewColorWith:self.bgColor alpha:0.0];
self.customView.alpha = 0.0f;
[UIView animateWithDuration:0.2 animations:^{
self.backgroundView.backgroundColor =[self getNewColorWith:self.bgColor alpha:self.bgAlpha];
self.customView.alpha = 1.0f;
}];
} else if (popStyle == LSTPopStyleNO){//无动画
self.backgroundView.backgroundColor = [self getNewColorWith:self.bgColor alpha:0.0];
[UIView animateWithDuration:0.1 animations:^{
self.backgroundView.backgroundColor =[self getNewColorWith:self.bgColor alpha:self.bgAlpha];
}];
self.customView.alpha = 1.0f;
} else {//有动画
self.backgroundView.backgroundColor = [self getNewColorWith:self.bgColor alpha:0.0];
[UIView animateWithDuration:duration animations:^{
wk_self.backgroundView.backgroundColor = [self getNewColorWith:self.bgColor alpha:self.bgAlpha];
}];
//自定义view过渡动画
[self hanlePopAnimationWithDuration:duration popStyle:popStyle];
}
}
- (void)hanlePopAnimationWithDuration:(NSTimeInterval)duration
popStyle:(LSTPopStyle)popStyle {
self.alpha = 0;
[UIView animateWithDuration:duration*0.2 animations:^{
self.alpha = 1;
}];
LSTPopViewWK(self);
switch (popStyle) {
case LSTPopStyleScale:// < 缩放动画,先放大,后恢复至原大小
{
[self animationWithLayer:_customView.layer duration:((0.3*duration)/0.7) values:@[@0.0, @1.2, @1.0]]; // 另外一组动画值(the other animation values) @[@0.0, @1.2, @0.9, @1.0]
}
break;
case LSTPopStyleSmoothFromTop:
case LSTPopStyleSmoothFromBottom:
case LSTPopStyleSmoothFromLeft:
case LSTPopStyleSmoothFromRight:
case LSTPopStyleSpringFromTop:
case LSTPopStyleSpringFromLeft:
case LSTPopStyleSpringFromBottom:
case LSTPopStyleSpringFromRight:
{
CGPoint startPosition = self.customView.layer.position;
if (popStyle == LSTPopStyleSmoothFromTop || popStyle == LSTPopStyleSpringFromTop) {
self.customView.layer.position = CGPointMake(startPosition.x, -_customView.pv_Height*0.5);
} else if (popStyle == LSTPopStyleSmoothFromLeft || popStyle == LSTPopStyleSpringFromLeft) {
self.customView.layer.position = CGPointMake(-_customView.pv_Width*0.5, startPosition.y);
} else if (popStyle == LSTPopStyleSmoothFromBottom || popStyle == LSTPopStyleSpringFromBottom) {
self.customView.layer.position = CGPointMake(startPosition.x, CGRectGetMaxY(self.frame) + _customView.pv_Height*0.5);
} else {
self.customView.layer.position = CGPointMake(CGRectGetMaxX(self.frame) + _customView.pv_Width*0.5 , startPosition.y);
}
CGFloat damping = 1.0;
if (popStyle == LSTPopStyleSpringFromTop||
popStyle == LSTPopStyleSpringFromLeft||
popStyle == LSTPopStyleSpringFromBottom||
popStyle == LSTPopStyleSpringFromRight) {
damping = 0.65;
}
[UIView animateWithDuration:duration
delay:0
usingSpringWithDamping:damping
initialSpringVelocity:1.0
options:UIViewAnimationOptionCurveEaseOut
animations:^{
wk_self.customView.layer.position = startPosition;
} completion:nil];
}
break;
case LSTPopStyleCardDropFromLeft:
case LSTPopStyleCardDropFromRight:
{
CGPoint startPosition = self.customView.layer.position;
if (popStyle == LSTPopStyleCardDropFromLeft) {
self.customView.layer.position = CGPointMake(startPosition.x * 1.0, -_customView.pv_Height*0.5);
self.customView.transform = CGAffineTransformMakeRotation(LST_DEGREES_TO_RADIANS(15.0));
} else {
self.customView.layer.position = CGPointMake(startPosition.x * 1.0, -_customView.pv_Height*0.5);
self.customView.transform = CGAffineTransformMakeRotation(LST_DEGREES_TO_RADIANS(-15.0));
}
[UIView animateWithDuration:duration delay:0 usingSpringWithDamping:0.75 initialSpringVelocity:1.0 options:UIViewAnimationOptionCurveEaseIn animations:^{
wk_self.customView.layer.position = startPosition;
} completion:nil];
[UIView animateWithDuration:duration*0.6 animations:^{
wk_self.customView.layer.transform = CATransform3DMakeRotation(LST_DEGREES_TO_RADIANS((popStyle == LSTPopStyleCardDropFromRight) ? 5.5 : -5.5), 0, 0, 0);
} completion:^(BOOL finished) {
[UIView animateWithDuration:duration*0.2 animations:^{
wk_self.customView.transform = CGAffineTransformMakeRotation(LST_DEGREES_TO_RADIANS((popStyle == LSTPopStyleCardDropFromRight) ? -1.0 : 1.0));
} completion:^(BOOL finished) {
[UIView animateWithDuration:duration*0.2 animations:^{
wk_self.customView.transform = CGAffineTransformMakeRotation(0.0);
} completion:nil];
}];
}];
}
break;
default:
break;
}
}
#pragma mark - ***** dismiss 移除 *****
- (void)dismiss {
[self dismissWithStyle:self.dismissStyle duration:self.dismissDuration];
}
- (void)dismissWithStyle:(LSTDismissStyle)dismissStyle {
[self dismissWithStyle:dismissStyle duration:self.dismissDuration];
}
- (void)dismissWithDuration:(NSTimeInterval)duration {
[self dismissWithStyle:self.dismissStyle duration:duration];
}
- (void)dismissWithStyle:(LSTDismissStyle)dismissStyle duration:(NSTimeInterval)duration {
[self dismissWithDismissStyle:dismissStyle duration:duration isRemove:YES];
}
- (void)dismissWithDismissStyle:(LSTDismissStyle)dismissStyle
duration:(NSTimeInterval)duration
isRemove:(BOOL)isRemove {
NSTimeInterval resDuration = [self getDismissDuration:duration];
if (isRemove) {
//把当前popView转移到待移除队列 避免线程安全问题
[LSTPopViewManager transferredToRemoveQueueWithPopView:self];
}
[self lst_PopViewWillDismissForPopView:self];
self.popViewWillDismissBlock? self.popViewWillDismissBlock():nil;
LSTPopViewWK(self)
[self dismissAnimationWithDismissStyle:dismissStyle duration:resDuration];
if (!self.isSingle && (isRemove && [LSTPopViewManager getAllPopViewForPopView:self].count >= 1)){//多显
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(resDuration * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
//popView出栈
if (!self.isStack && [LSTPopViewManager getAllPopViewForPopView:self].count >= 1) {
NSArray *popViewArr = [LSTPopViewManager getAllPopViewForPopView:self];
id obj = popViewArr[popViewArr.count-1];
LSTPopView *tPopView = (LSTPopView *)obj;
if (!tPopView.superview) {
[tPopView.container addSubview:tPopView];
[LSTPopViewM().showList addPointer:(__bridge void * _Nullable)tPopView];
}
[tPopView popWithPopStyle:LSTPopStyleFade duration:0.25 isOutStack:YES];
}
});
}
if (isRemove) {
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(resDuration * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[wk_self removeFromSuperview];
});
}
}
- (void)dismissAnimationWithDismissStyle:(LSTDismissStyle)dismissStyle duration:(NSTimeInterval)duration {
LSTPopViewWK(self);
if (dismissStyle == LSTPopStyleFade) {
[UIView animateWithDuration:0.2 animations:^{
wk_self.backgroundView.backgroundColor = [self getNewColorWith:self.bgColor alpha:0.0];
wk_self.customView.alpha = 0.0f;
}];
}else if (dismissStyle == LSTPopStyleNO){
wk_self.backgroundView.backgroundColor = [self getNewColorWith:self.bgColor alpha:0.0];
wk_self.customView.alpha = 0.0f;
}else {//有动画
[UIView animateWithDuration:duration*0.8 animations:^{
wk_self.backgroundView.backgroundColor = [self getNewColorWith:self.bgColor alpha:0.0];
}];
[self hanleDismissAnimationWithDuration:duration withDismissStyle:dismissStyle];
}
}
- (void)hanleDismissAnimationWithDuration:(NSTimeInterval)duration
withDismissStyle:(LSTDismissStyle)dismissStyle {
[UIView animateWithDuration:duration*0.8 animations:^{
self.alpha = 0;
}];
LSTPopViewWK(self);;
switch (dismissStyle) {
case LSTDismissStyleScale:
{
[self animationWithLayer:self.customView.layer duration:((0.2*duration)/0.8) values:@[@1.0, @0.66, @0.33, @0.01]];
}
break;
case LSTDismissStyleSmoothToTop:
case LSTDismissStyleSmoothToBottom:
case LSTDismissStyleSmoothToLeft:
case LSTDismissStyleSmoothToRight:
{
CGPoint startPosition = self.customView.layer.position;
CGPoint endPosition = self.customView.layer.position;
if (dismissStyle == LSTDismissStyleSmoothToTop) {
endPosition = CGPointMake(startPosition.x, -(_customView.pv_Height*0.5));
} else if (dismissStyle == LSTDismissStyleSmoothToBottom) {
endPosition = CGPointMake(startPosition.x, CGRectGetMaxY(self.frame) + _customView.pv_Height*0.5);
} else if (dismissStyle == LSTDismissStyleSmoothToLeft) {
endPosition = CGPointMake(-_customView.pv_Width*0.5, startPosition.y);
} else {
endPosition = CGPointMake(CGRectGetMaxX(self.frame) + _customView.pv_Width*0.5, startPosition.y);
}
[UIView animateWithDuration:duration delay:0 usingSpringWithDamping:1.0 initialSpringVelocity:1.0 options:UIViewAnimationOptionCurveEaseOut animations:^{
wk_self.customView.layer.position = endPosition;
} completion:nil];
}
break;
case LSTDismissStyleCardDropToLeft:
case LSTDismissStyleCardDropToRight:
{
CGPoint startPosition = self.customView.layer.position;
BOOL isLandscape = UIInterfaceOrientationIsLandscape([UIApplication sharedApplication].statusBarOrientation);
__block CGFloat rotateEndY = 0.0f;
[UIView animateWithDuration:duration delay:0 usingSpringWithDamping:0.5 initialSpringVelocity:1.0 options:UIViewAnimationOptionCurveEaseIn animations:^{
if (dismissStyle == LSTDismissStyleCardDropToLeft) {
wk_self.customView.transform = CGAffineTransformMakeRotation(M_1_PI * 0.75);
if (isLandscape) rotateEndY = fabs(wk_self.customView.frame.origin.y);
wk_self.customView.layer.position = CGPointMake(startPosition.x, CGRectGetMaxY(wk_self.frame) + startPosition.y + rotateEndY);
} else {
wk_self.customView.transform = CGAffineTransformMakeRotation(-M_1_PI * 0.75);
if (isLandscape) rotateEndY = fabs(wk_self.customView.frame.origin.y);
wk_self.customView.layer.position = CGPointMake(startPosition.x * 1.25, CGRectGetMaxY(wk_self.frame) + startPosition.y + rotateEndY);
}
} completion:nil];
}
break;
case LSTDismissStyleCardDropToTop:
{
CGPoint startPosition = self.customView.layer.position;
CGPoint endPosition = CGPointMake(startPosition.x, -startPosition.y);
[UIView animateWithDuration:duration*0.2 animations:^{
wk_self.customView.layer.position = CGPointMake(startPosition.x, startPosition.y + 50.0f);
} completion:^(BOOL finished) {
[UIView animateWithDuration:duration*0.8 animations:^{
wk_self.customView.layer.position = endPosition;
} completion:nil];
}];
}
break;
default:
break;
}
}
#pragma mark - ***** other 其他 *****
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
if([keyPath isEqualToString:@"frame"]) {
CGRect newFrame = CGRectNull;
CGRect oldFrame = CGRectNull;
if([object valueForKeyPath:keyPath] != [NSNull null]) {
//此处为获取新的frame
newFrame = [[object valueForKeyPath:keyPath] CGRectValue];
oldFrame = [[change valueForKeyPath:@"old"] CGRectValue];
if (!CGSizeEqualToSize(newFrame.size, oldFrame.size)) {
[self setCustomViewFrameWithHeight:newFrame.size.height-oldFrame.size.height];
}
}
}else {
[super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
}
}
//按钮的压下事件 按钮缩小
- (void)bgLongPressEvent:(UIGestureRecognizer *)ges {
// [self.delegateMarr enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
//
// if ([obj respondsToSelector:@selector(lst_PopViewBgLongPressForPopView:)]) {
// [obj lst_PopViewBgLongPressForPopView:self];
// }
//
// }];
self.bgLongPressBlock? self.bgLongPressBlock():nil;
// switch (ges.state) {
// case UIGestureRecognizerStateBegan:
// {
// CGFloat scale = 0.95;
// [UIView animateWithDuration:0.35 animations:^{
// ges.view.transform = CGAffineTransformMakeScale(scale, scale);
// }];
// }
// break;
// case UIGestureRecognizerStateEnded:
// case UIGestureRecognizerStateCancelled:
// {
// [UIView animateWithDuration:0.35 animations:^{
// ges.view.transform = CGAffineTransformMakeScale(1.0, 1.0);
// } completion:^(BOOL finished) {
// }];
// }
// break;
//
// default:
// break;
// }
}
- (void)customViewClickEvent:(UIGestureRecognizer *)ges {
if (self.isClickFeedback) {
CGFloat scale = 0.95;
[UIView animateWithDuration:0.25 animations:^{
ges.view.transform = CGAffineTransformMakeScale(scale, scale);
} completion:^(BOOL finished) {
[UIView animateWithDuration:0.25 animations:^{
ges.view.transform = CGAffineTransformMakeScale(1.0, 1.0);
} completion:^(BOOL finished) {
}];
}];
}
}
- (void)popViewBgViewTap:(UIButton *)tap {
// [self.delegateMarr enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
//
// if ([obj respondsToSelector:@selector(lst_PopViewBgClickForPopView:)]) {
// [obj lst_PopViewBgClickForPopView:self];
// }
//
// }];
if (self.bgClickBlock) {
if (self.isShowKeyboard) {
[self endEditing:YES];
}
self.bgClickBlock();
}
if (_isClickBgDismiss) {
[self dismiss];
}
}
- (NSTimeInterval)getPopDuration:(NSTimeInterval)currDuration {
if (_popStyle == LSTPopStyleNO) { return 0.0f; }
if (_popStyle == LSTPopStyleFade) { return 0.2f; }
if (currDuration<=0) { self.popDuration = LSTPopViewDefaultDuration; }
if (self.popDuration == LSTPopViewDefaultDuration) {
NSTimeInterval defaultDuration = 0.0f;
if (_popStyle == LSTPopStyleScale) {
defaultDuration = 0.3f;
}
if (_popStyle == LSTPopStyleSmoothFromTop ||
_popStyle == LSTPopStyleSmoothFromLeft ||
_popStyle == LSTPopStyleSmoothFromBottom ||
_popStyle == LSTPopStyleSmoothFromRight ||
_popStyle == LSTPopStyleSpringFromTop ||
_popStyle == LSTPopStyleSpringFromLeft ||
_popStyle == LSTPopStyleSpringFromBottom ||
_popStyle == LSTPopStyleSpringFromRight ||
_popStyle == LSTPopStyleCardDropFromLeft ||
_popStyle == LSTPopStyleCardDropFromRight) {
defaultDuration = 0.6f;
}
return defaultDuration;
} else {
return currDuration;
}
}
- (NSTimeInterval)getDismissDuration:(NSTimeInterval)currDuration {
if (_dismissStyle == LSTDismissStyleNO) { return 0.0f; }
if (_dismissStyle == LSTDismissStyleFade) { return 0.2f; }
if (self.dismissDuration == LSTPopViewDefaultDuration) {
NSTimeInterval defaultDuration = 0.0f;
if (_dismissStyle == LSTDismissStyleNO) {
defaultDuration = 0.0f;
}
if (_dismissStyle == LSTDismissStyleScale) {
defaultDuration = 0.3f;
}
if (_dismissStyle == LSTDismissStyleSmoothToTop ||
_dismissStyle == LSTDismissStyleSmoothToBottom ||
_dismissStyle == LSTDismissStyleSmoothToLeft ||
_dismissStyle == LSTDismissStyleSmoothToRight ||
_dismissStyle == LSTDismissStyleCardDropToLeft ||
_dismissStyle == LSTDismissStyleCardDropToRight ||
_dismissStyle == LSTDismissStyleCardDropToTop) {
defaultDuration = 0.5f;
}
return defaultDuration;
} else {
return currDuration;
}
}
- (NSTimeInterval)getDragDismissDuration {
if (self.dragDismissDuration == LSTPopViewDefaultDuration) {
return [self getDismissDuration:self.dismissDuration];
} else {
return self.dragDismissDuration;
}
}
- (void)animationWithLayer:(CALayer *)layer duration:(CGFloat)duration values:(NSArray *)values {
CAKeyframeAnimation *KFAnimation = [CAKeyframeAnimation animationWithKeyPath:@"transform"];
KFAnimation.duration = duration;
KFAnimation.removedOnCompletion = NO;
KFAnimation.fillMode = kCAFillModeForwards;
// KFAnimation.delegate = self;//造成强应用 popView释放不了
NSMutableArray *valueArr = [NSMutableArray arrayWithCapacity:values.count];
for (NSUInteger i = 0; i<values.count; i++) {
CGFloat scaleValue = [values[i] floatValue];
[valueArr addObject:[NSValue valueWithCATransform3D:CATransform3DMakeScale(scaleValue, scaleValue, scaleValue)]];
}
KFAnimation.values = valueArr;
KFAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn];
[layer addAnimation:KFAnimation forKey:nil];
}
- (UIColor *)lst_BlackWithAlpha:(CGFloat)alpha {
return [UIColor colorWithRed:0 green:0 blue:0 alpha:alpha];
}
// 改变UIColor的Alpha
- (UIColor *)getNewColorWith:(UIColor *)color alpha:(CGFloat)alpha {
if (self.isHideBg) {
return UIColor.clearColor;
}
if (self.bgColor == UIColor.clearColor) {
return UIColor.clearColor;
}
CGFloat red = 0.0;
CGFloat green = 0.0;
CGFloat blue = 0.0;
CGFloat resAlpha = 0.0;
[color getRed:&red green:&green blue:&blue alpha:&resAlpha];
UIColor *newColor = [UIColor colorWithRed:red green:green blue:blue alpha:alpha];
return newColor;
}
- (void)startTimer {
if (self.showTime > 0) {
LSTPopViewWK(self);;
NSString *idStr = [NSString stringWithFormat:@"LSTPopView_%p",self];
[LSTTimer addMinuteTimerForTime:self.showTime identifier:idStr handle:^(NSString * _Nonnull day, NSString * _Nonnull hour, NSString * _Nonnull minute, NSString * _Nonnull second, NSString * _Nonnull ms) {
if (wk_self.popViewCountDownBlock) {
wk_self.popViewCountDownBlock(wk_self, [second doubleValue]);
}
[wk_self lst_PopViewCountDownForPopView:wk_self forCountDown:[second doubleValue]];
} finish:^(NSString * _Nonnull identifier) {
[wk_self lst_PopViewCountDownFinishForPopView:wk_self];
[self dismiss];
} pause:^(NSString * _Nonnull identifier) {}];
}
}
/** 删除指定代理 */
- (void)removeForDelegate:(id<LSTPopViewProtocol>)delegate {
if (delegate) {
if ([self.delegates containsObject:delegate]) {
[self.delegates removeObject:delegate];
}
}
}
/** 删除代理池 删除所有代理 */
- (void)removeAllDelegate {
if (self.delegates.count > 0) {
[self.delegates removeAllObjects];
}
}
- (void)beginImpactFeedback {
if (self.isImpactFeedback) {
if (@available(iOS 10.0, *)) {
UIImpactFeedbackGenerator *feedBackGenertor = [[UIImpactFeedbackGenerator alloc] initWithStyle:UIImpactFeedbackStyleMedium];
[feedBackGenertor impactOccurred];
}
}
}
#pragma mark - ***** 横竖屏改变 *****
- (void)statusBarOrientationChange:(NSNotification *)notification {
if (self.isObserverScreenRotation) {
CGRect originRect = self.customView.frame;
self.frame = CGRectMake(0, 0, pv_ScreenWidth(), pv_ScreenHeight());
self.backgroundView.frame = self.bounds;
self.customView.frame = originRect;
[self setCustomViewFrameWithHeight:0];
}
}
#pragma mark - ***** 键盘弹出/收回 *****
- (void)keyboardWillShow:(NSNotification *)notification{
// LSTPVLog(@"keyboardWillShow");
_isShowKeyboard = YES;
self.keyboardWillShowBlock? self.keyboardWillShowBlock():nil;
if (!self.isAvoidKeyboard) { return; }
CGFloat customViewMaxY = self.customView.pv_Bottom + self.avoidKeyboardSpace;
CGFloat duration = [notification.userInfo[UIKeyboardAnimationDurationUserInfoKey] floatValue];
CGRect keyboardEedFrame = [notification.userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue];
CGFloat keyboardMaxY = keyboardEedFrame.origin.y;
self.isAvoidKeyboard = YES;
self.avoidKeyboardOffset = customViewMaxY - keyboardMaxY;
self.keyboardY = keyboardEedFrame.origin.y;
//键盘遮挡到弹窗
if ((keyboardMaxY<customViewMaxY) || ((_originFrame.origin.y + _customView.pv_Height) > keyboardMaxY)) {
//执行动画
[UIView animateWithDuration:duration animations:^{
self.customView.pv_Y = self.customView.pv_Y - self.avoidKeyboardOffset;
}];
}
}
- (void)keyboardDidShow:(NSNotification *)notification{
_isShowKeyboard = YES;
self.keyboardDidShowBlock? self.keyboardDidShowBlock():nil;
}
- (void)keyboardWillHide:(NSNotification *)notification{
_isShowKeyboard = NO;
self.keyboardWillHideBlock? self.keyboardWillHideBlock():nil;
if (!self.isAvoidKeyboard) {
return;
}
CGFloat duration = [notification.userInfo[UIKeyboardAnimationDurationUserInfoKey] floatValue];
[UIView animateWithDuration:duration animations:^{
self.customView.pv_Y = self.originFrame.origin.y;
}];
}
- (void)keyboardDidHide:(NSNotification *)notification{
_isShowKeyboard = NO;
self.keyboardDidHideBlock? self.keyboardDidHideBlock():nil;
}
- (void)keyboardWillChangeFrame:(NSNotification *)notification{
// LSTPVLog(@"键盘frame将要改变");
if (self.keyboardFrameWillChangeBlock) {
CGRect keyboardBeginFrame = [notification.userInfo[UIKeyboardFrameBeginUserInfoKey] CGRectValue];
CGRect keyboardEedFrame = [notification.userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue];
CGFloat duration = [notification.userInfo[UIKeyboardAnimationDurationUserInfoKey] floatValue];
self.keyboardFrameWillChangeBlock(keyboardBeginFrame,keyboardEedFrame,duration);
}
}
- (void)keyboardDidChangeFrame:(NSNotification *)notification{
// LSTPVLog(@"键盘frame已经改变");
if (self.keyboardFrameDidChangeBlock) {
CGRect keyboardBeginFrame = [notification.userInfo[UIKeyboardFrameBeginUserInfoKey] CGRectValue];
CGRect keyboardEedFrame = [notification.userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue];
CGFloat duration = [notification.userInfo[UIKeyboardAnimationDurationUserInfoKey] floatValue];
self.keyboardFrameDidChangeBlock(keyboardBeginFrame,keyboardEedFrame,duration);
}
}
#pragma mark - ***** UIGestureRecognizerDelegate *****
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
if(gestureRecognizer == self.panGesture) {
UIView *touchView = touch.view;
while (touchView != nil) {
if([touchView isKindOfClass:[UIScrollView class]]) {
self.isDragScrollView = YES;
self.scrollerView = (UIScrollView *)touchView;
break;
} else if(touchView == self.customView) {
self.isDragScrollView = NO;
break;
}
touchView = (id)[touchView nextResponder];
}
}
return YES;
}
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer {
if(gestureRecognizer == self.tapGesture) {
//如果是点击手势
CGPoint point = [gestureRecognizer locationInView:self.customView];
BOOL iscontain = [self.customView.layer containsPoint:point];
if(iscontain) {
return NO;
}
} else if(gestureRecognizer == self.panGesture){
//如果是自己加的拖拽手势
// LSTPVLog(@"gestureRecognizerShouldBegin");
}
return YES;
}
//3. 是否与其他手势共存,一般使用默认值(默认返回NO不与任何手势共存)
- (BOOL)gestureRecognizer:(UIPanGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
if(gestureRecognizer == self.panGesture) {
if ([otherGestureRecognizer isKindOfClass:NSClassFromString(@"UIScrollViewPanGestureRecognizer")] || [otherGestureRecognizer isKindOfClass:NSClassFromString(@"UIPanGestureRecognizer")] ) {
if([otherGestureRecognizer.view isKindOfClass:[UIScrollView class]] ) {
return YES;
}
}
}
return NO;
}
//拖拽手势
- (void)pan:(UIPanGestureRecognizer *)panGestureRecognizer {
self.panOffsetBlock?self.panOffsetBlock(CGPointMake(_customView.pv_X-_originFrame.origin.x, _customView.pv_Y-_originFrame.origin.y)):nil;
if (self.dragStyle == LSTDragStyleNO) {return;}
// 获取手指的偏移量
CGPoint transP = [panGestureRecognizer translationInView:self.customView];
CGPoint velocity = [panGestureRecognizer velocityInView:[UIApplication sharedApplication].keyWindow];
if(self.isDragScrollView) {//含有tableView,collectionView,scrollView
//如果当前拖拽的是tableView
if(self.scrollerView.contentOffset.y <= 0) {
//如果tableView置于顶端
if(transP.y > 0) {
//如果向下拖拽
self.scrollerView.contentOffset = CGPointMake(0, 0);
self.scrollerView.panGestureRecognizer.enabled = NO;
self.isDragScrollView = NO;
//向下拖
self.customView.frame = CGRectMake(_customView.pv_X, _customView.pv_Y + transP.y, _customView.pv_Width, _customView.pv_Height);
} else {
//如果向上拖拽
}
}
} else {//不含有tableView,collectionView,scrollView
CGFloat customViewX = self.customView.pv_X;
CGFloat customViewY = self.customView.pv_Y;
//X正方向移动
if ((self.dragStyle & LSTDragStyleX_Positive) && (customViewX >= _originFrame.origin.x)) {
if (transP.x > 0) {
customViewX = customViewX + transP.x;
} else if(transP.x < 0 && customViewX > _originFrame.origin.x ){
customViewX = (customViewX + transP.x) > _originFrame.origin.x? (customViewX + transP.x):(_originFrame.origin.x);
}
}
//X负方向移动
if ((self.dragStyle & LSTDragStyleX_Negative) && (customViewX <= self.originFrame.origin.x)) {
if (transP.x < 0) {
customViewX = customViewX + transP.x;
} else if(transP.x > 0 && customViewX < _originFrame.origin.x ){
customViewX = (customViewX + transP.x) < _originFrame.origin.x? (customViewX + transP.x):(_originFrame.origin.x);
}
}
//Y正方向移动
if (self.dragStyle & LSTDragStyleY_Positive && (customViewY >= _originFrame.origin.y)) {
if (transP.y > 0) {
customViewY = customViewY + transP.y;
} else if(transP.y < 0 && customViewY > _originFrame.origin.y ){
customViewY = (customViewY + transP.y) > _originFrame.origin.y ?(customViewY + transP.y):(_originFrame.origin.y);
}
}
//Y负方向移动
if (self.dragStyle & LSTDragStyleY_Negative&&(customViewY <= _originFrame.origin.y)) {
if (transP.y < 0) {
customViewY = customViewY + transP.y;
} else if(transP.y > 0 && customViewY < _originFrame.origin.y){
customViewY = (customViewY + transP.y) < _originFrame.origin.y?(customViewY + transP.y):(_originFrame.origin.y);
}
}
self.customView.frame = CGRectMake(customViewX, customViewY, _customView.pv_Width, _customView.pv_Height);
}
[panGestureRecognizer setTranslation:CGPointZero inView:self.customView];
if(panGestureRecognizer.state == UIGestureRecognizerStateEnded) {
if (self.scrollerView) {
self.scrollerView.panGestureRecognizer.enabled = YES;
}
LSTPopViewWK(self)
//拖拽松开回位Block
void (^dragReboundBlock)(void) = ^ {
[UIView animateWithDuration:wk_self.dragReboundTime
delay:0.1f
options:UIViewAnimationOptionCurveEaseOut
animations:^{
CGRect frame = wk_self.customView.frame;
frame.origin.y = wk_self.frame.size.height - wk_self.customView.frame.size.height;
wk_self.customView.frame = wk_self.originFrame;
} completion:^(BOOL finished) {}];
};
//横扫移除Block
void (^sweepBlock)(BOOL,BOOL,BOOL,BOOL) = ^(BOOL isX_P, BOOL isX_N, BOOL isY_P, BOOL isY_N) {
if (isX_P==NO && isX_N==NO && isY_P==NO && isY_N==NO) {
dragReboundBlock();
return;
}
if (isY_P==NO && isY_N==NO && self.sweepDismissStyle == LSTSweepDismissStyleSmooth) {//X轴可轻扫
if (velocity.x>0) {//正向
[self dismissWithStyle:LSTDismissStyleSmoothToRight duration:self.dismissDuration];
} else {//负向
[self dismissWithStyle:LSTDismissStyleSmoothToLeft duration:self.dismissDuration];
}
return;
}
if (isX_P==NO && isX_N==NO && self.sweepDismissStyle == LSTSweepDismissStyleSmooth) {//Y轴可轻扫
if (velocity.y>0) {//正向
[self dismissWithStyle:LSTDismissStyleSmoothToBottom duration:self.dismissDuration];
} else {//负向
[self dismissWithStyle:LSTDismissStyleSmoothToTop duration:self.dismissDuration];
}
return;
}
// 移除,以手势速度飞出
[UIView animateWithDuration:0.5 animations:^{
wk_self.backgroundView.backgroundColor = [self getNewColorWith:self.bgColor alpha:0.0];
self.customView.center = CGPointMake(isX_P || isX_N?velocity.x:self.customView.pv_CenterX, isY_P||isY_N?velocity.y:self.customView.pv_CenterY);
} completion:^(BOOL finished) {
[wk_self dismissWithStyle:LSTDismissStyleFade duration:0.1];
}];
};
double velocityX = sqrt(pow(velocity.x, 2));
double velocityY = sqrt(pow(velocity.y, 2));
if((velocityX >= self.swipeVelocity)||(velocityY >= self.swipeVelocity)) {//轻扫
if (self.scrollerView.contentOffset.y>0) {
return;
}
//可轻扫移除的方向
BOOL isX_P = NO;
BOOL isX_N = NO;
BOOL isY_P = NO;
BOOL isY_N = NO;
if ((self.dragStyle & LSTDragStyleX_Positive) && velocity.x>0 && velocityX >= self.swipeVelocity) {
isX_P = self.sweepStyle & LSTSweepStyleX_Positive? YES:NO;
}
if ((self.dragStyle & LSTDragStyleX_Negative) && velocity.x<0 && velocityX >= self.swipeVelocity) {
isX_N = self.sweepStyle & LSTSweepStyleX_Negative? YES:NO;
}
if ((self.dragStyle & LSTDragStyleY_Positive) && velocity.y>0 && velocityY >= self.swipeVelocity) {
isY_P = self.sweepStyle & LSTSweepStyleY_Positive? YES:NO;
}
if ((self.dragStyle & LSTDragStyleY_Negative) && velocity.y <0 && velocityY >= self.swipeVelocity) {
isY_N = self.sweepStyle & LSTSweepStyleY_Negative? YES:NO;
}
sweepBlock(isX_P,isX_N,isY_P,isY_N);
// LSTPVLog(@"isX=%@,isY=%@,velocityX=%lf,velocityY=%lf",isX?@"YES":@"NO",isY?@"YES":@"NO",velocityX,velocityY);
}else {//普通拖拽
BOOL isCanDismiss = NO;
if (self.dragStyle & LSTDragStyleAll) {
if (fabs(self.customView.frame.origin.x - self.originFrame.origin.x)>=self.dragDistance && self.dragDistance!=0) {
isCanDismiss = YES;
}
if (fabs(self.customView.frame.origin.y - self.originFrame.origin.y)>=self.dragDistance && self.dragDistance!=0) {
isCanDismiss = YES;
}
if (isCanDismiss) {
[self dismissWithStyle:_isDragDismissStyle? self.dragDismissStyle:self.dismissStyle
duration:self.getDragDismissDuration];
}else {
dragReboundBlock();
}
} else {
dragReboundBlock();
}
}
}
}
#pragma mark - ***** 懒加载 *****
- (NSHashTable<id<LSTPopViewProtocol>> *)delegates {
if (_delegates) return _delegates;
_delegates = [NSHashTable hashTableWithOptions:NSPointerFunctionsWeakMemory];
return _delegates;
}
- (UIView *)parentView {
return self.container;
}
- (UIView *)currCustomView {
return self.customView;
}
#pragma mark - ***** 以下是 窗口管理api *****
/** 保存popView */
+ (void)savePopView:(LSTPopView *)popView {
[LSTPopViewManager savePopView:popView];
}
/** 获取全局(整个app内)所有popView */
+ (NSArray *)getAllPopView {
return [LSTPopViewManager getAllPopView];
}
/** 获取当前页面所有popView */
+ (NSArray *)getAllPopViewForParentView:(UIView *)parentView {
return [LSTPopViewManager getAllPopViewForParentView:parentView];
}
/** 获取当前页面指定编队的所有popView */
+ (NSArray *)getAllPopViewForPopView:(LSTPopView *)popView {
return [LSTPopViewManager getAllPopViewForPopView:popView];
}
/**
读取popView (有可能会跨编队读取弹窗)
建议使用getPopViewForGroupId:forkey: 方法进行精确读取
*/
+ (LSTPopView *)getPopViewForKey:(NSString *)key {
return [LSTPopViewManager getPopViewForKey:key];
}
/** 移除popView */
+ (void)removePopView:(LSTPopView *)popView {
[LSTPopViewManager removePopView:popView];
}
/**
移除popView 通过唯一key (有可能会跨编队误删弹窗)
建议使用removePopViewForGroupId:forkey: 方法进行精确删除
*/
+ (void)removePopViewForKey:(NSString *)key {
[LSTPopViewManager removePopViewForKey:key];
}
/** 移除所有popView */
+ (void)removeAllPopView {
[LSTPopViewManager removeAllPopView];
}
/** 移除 最后一个弹出的 popView */
+ (void)removeLastPopView {
return [LSTPopViewManager removeLastPopView];
}
/** 开启调试view 建议设置成 线上隐藏 测试打开 */
+ (void)setLogStyle:(LSTPopViewLogStyle)logStyle {
_logStyle = logStyle;
if (logStyle == LSTPopViewLogStyleNO) {
[LSTPopViewM().infoView removeFromSuperview];
LSTPopViewM().infoView = nil;
}
}
@end