php实现飘窗,飘窗的实现原理

#import

typedef void (^PopViewSelectedHandle) (NSInteger selectedIndex);

@interface SGPopSelectView :

UIView

@property (nonatomic,

strong) NSArray *selections;

@property (nonatomic, copy) PopViewSelectedHandle selectedHandle;

@property (nonatomic,

readonly) BOOL visible;

- (instancetype)init;

-

(void)showFromView:(UIView*)view

atPoint:(CGPoint)point

animated:(BOOL)animated;

-

(void)hide:(BOOL)animated;

@end

#import "SGPopSelectView.h"

#define SGPOP_DEFAULT_FONT_SIZE  13

#define SGPOP_DEFAULT_ROW_HEIHGT 30

#define SGPOP_DEFAULT_MAX_HEIGHT 200

@interface SGPopSelectView ()

<UITableViewDelegate,

UITableViewDataSource>

@property (nonatomic,

strong) UITableView *tableView;

// data

@property (nonatomic,

assign) NSInteger selectedIndex;

@end

@implementation

SGPopSelectView

- (instancetype)init

{

self

= [super initWithFrame:CGRectZero];

if (self) {

_selectedIndex

= NSNotFound;

self.backgroundColor = [UIColor colorWithWhite:1.0

alpha:0.95];

self.layer.cornerRadius = 8;

self.layer.masksToBounds = NO;

self.translatesAutoresizingMaskIntoConstraints

= NO;

_tableView =

[[UITableView

alloc]

initWithFrame:CGRectZero style:UITableViewStylePlain];

_tableView.backgroundColor = [UIColor clearColor];

_tableView.backgroundView = nil;

_tableView.separatorStyle =

UITableViewCellSeparatorStyleNone;

_tableView.dataSource = self;

_tableView.delegate = self;

_tableView.translatesAutoresizingMaskIntoConstraints

= NO;

[self

addSubview:_tableView];

NSMutableArray *constraints = [NSMutableArray array];

[constraints addObjectsFromArray:

[NSLayoutConstraint

constraintsWithVisualFormat:@"V:|[_tableView]|"

options:0

metrics:nil

views:NSDictionaryOfVariableBindings(_tableView)]];

[constraints addObjectsFromArray:

[NSLayoutConstraint

constraintsWithVisualFormat:@"H:|[_tableView]|"

options:0

metrics:nil

views:NSDictionaryOfVariableBindings(_tableView)]];

[self

addConstraints:constraints];

}

return self;

}

-

(void)layoutSubviews

{

[super

layoutSubviews];

self.layer.shadowColor =

[UIColor blackColor].CGColor;

self.layer.shadowOffset = CGSizeMake(0,

0);

self.layer.shadowRadius = 4;

self.layer.shadowOpacity = 0.2;

self.layer.shadowPath =

[UIBezierPath bezierPathWithRect:self.bounds].CGPath;

}

-

(void)setSelectedHandle:(PopViewSelectedHandle)handle

{

_selectedHandle = handle;

}

-

(void)showFromView:(UIView

*)view atPoint:(CGPoint)point

animated:(BOOL)animated

{

if (self.visible) {

[self removeFromSuperview];

}

[view addSubview:self];

[self

_setupConstraintsWithSuperView:view atPoint:point];

[self _showFromView:view animated:animated];

}

-

(void)hide:(BOOL)animated

{

[self _hideWithAnimated:animated];

}

-

(BOOL)visible

{

if (self.superview) {

return

YES;

}

return NO;

}

-

(void)setSelections:(NSArray *)selections

{

_selections = selections;

_selectedIndex = NSNotFound;

[_tableView reloadData];

}

#pragma mark - Private Methods

static CAAnimation* _showAnimation()

{

CAKeyframeAnimation *transform = [CAKeyframeAnimation

animationWithKeyPath:@"transform"];

NSMutableArray *values = [NSMutableArray array];

[values addObject:[NSValue valueWithCATransform3D:CATransform3DMakeScale(0.95,

0.95, 1.0)]];

[values addObject:[NSValue valueWithCATransform3D:CATransform3DMakeScale(1.05,

1.05, 1.0)]];

[values addObject:[NSValue valueWithCATransform3D:CATransform3DMakeScale(1.0,

1.0, 1.0)]];

transform.values = values;

CABasicAnimation *opacity = [CABasicAnimation animationWithKeyPath:@"opacity"];

[opacity setFromValue:@0.0];

[opacity setToValue:@1.0];

CAAnimationGroup *group = [CAAnimationGroup animation];

group.duration = 0.2;

group.timingFunction =

[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];

[group setAnimations:@[transform, opacity]];

return group;

}

static CAAnimation* _hideAnimation()

{

CAKeyframeAnimation *transform = [CAKeyframeAnimation

animationWithKeyPath:@"transform"];

NSMutableArray *values = [NSMutableArray array];

[values addObject:[NSValue valueWithCATransform3D:CATransform3DMakeScale(1.05,

1.05, 1.0)]];

[values addObject:[NSValue valueWithCATransform3D:CATransform3DMakeScale(1.0,

1.0, 1.0)]];

[values addObject:[NSValue valueWithCATransform3D:CATransform3DMakeScale(0.95,

0.95, 1.0)]];

transform.values = values;

CABasicAnimation *opacity = [CABasicAnimation animationWithKeyPath:@"opacity"];

[opacity setFromValue:@1.0];

[opacity setToValue:@0.0];

CAAnimationGroup *group = [CAAnimationGroup animation];

group.duration = 0.2;

group.timingFunction =

[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];

[group setAnimations:@[transform, opacity]];

return group;

}

-

(void)_showFromView:(UIView *)view animated:(BOOL)animated

{

if (animated) {

[CATransaction

begin];

[CATransaction

setCompletionBlock:^{

[self.tableView flashScrollIndicators];

}];

[self.layer addAnimation:_showAnimation() forKey:nil];

[CATransaction

commit];

}

}

-

(void)_hideWithAnimated:(BOOL)animated

{

if (animated) {

[CATransaction

begin];

[CATransaction

setCompletionBlock:^{

[self.layer

removeAnimationForKey:@"transform"];

[self.layer

removeAnimationForKey:@"opacity"];

[self

removeFromSuperview];

}];

[self.layer addAnimation:_hideAnimation() forKey:nil];

[CATransaction

commit];

}else {

[self removeFromSuperview];

}

}

-

(void)_setupConstraintsWithSuperView:(UIView

*)view atPoint:(CGPoint)point

{

CGFloat totalHeight = _selections.count * SGPOP_DEFAULT_ROW_HEIHGT;

CGFloat height

= totalHeight > SGPOP_DEFAULT_MAX_HEIGHT ? SGPOP_DEFAULT_MAX_HEIGHT : totalHeight;

CGFloat width = [self _preferedWidth];

width = width >

view.bounds.size.width * 0.9 ? view.bounds.size.width * 0.9 : width;

CGFloat left = (point.x + width) > view.bounds.size.width ? (view.bounds.size.width - width - 10) : point.x;

NSMutableArray *constraints = [NSMutableArray array];

[constraints addObjectsFromArray:

[NSLayoutConstraint

constraintsWithVisualFormat:@"H:|-left-[self(==width)]"

options:0

metrics:@{@"left": @(left), @"width": @(width)}

views:NSDictionaryOfVariableBindings(self)]];

[constraints addObjectsFromArray:

[NSLayoutConstraint

constraintsWithVisualFormat:@"V:|->=20-[self]->=10-|"

options:0

metrics:nil

views:NSDictionaryOfVariableBindings(self)]];

[constraints setValue:@(UILayoutPriorityRequired) forKeyPath:@"priority"];

NSLayoutConstraint *hConstraint = [NSLayoutConstraint

constraintWithItem:self

attribute:NSLayoutAttributeHeight

relatedBy:NSLayoutRelationEqual

toItem:nil

attribute:NSLayoutAttributeNotAnAttribute

multiplier:1.0

constant:height];

hConstraint.priority =

UILayoutPriorityDefaultHigh;

[constraints addObject:hConstraint];

NSLayoutConstraint *yConstraint = [NSLayoutConstraint

constraintWithItem:self

attribute:NSLayoutAttributeCenterY

relatedBy:NSLayoutRelationEqual

toItem:view

attribute:NSLayoutAttributeTop

multiplier:1.0

constant:point.y];

yConstraint.priority =

UILayoutPriorityDefaultHigh;

[constraints addObject:yConstraint];

[view addConstraints:constraints];

}

-

(CGFloat)_preferedWidth

{

NSPredicate *maxLength = [NSPredicate predicateWithFormat:@"SELF.length ==

%@.@max.length", _selections];

NSString *maxString = [_selections filteredArrayUsingPredicate:maxLength][0];

CGFloat strWidth;

if

([UIDevice currentDevice].systemVersion.floatValue >= 7.0)

{

strWidth = [maxString sizeWithAttributes:@{NSFontAttributeName: [UIFont systemFontOfSize:SGPOP_DEFAULT_FONT_SIZE]}].width;

}else {

strWidth = [maxString sizeWithFont:[UIFont systemFontOfSize:SGPOP_DEFAULT_FONT_SIZE]].width;

}

return strWidth + 15 * 2

+ 30;

}

#pragma mark - UITableview DataSource

-

(NSInteger)tableView:(UITableView *)tableView

numberOfRowsInSection:(NSInteger)section

{

return _selections.count;

}

-

(UITableViewCell

*)tableView:(UITableView

*)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath

{

static NSString *cellId = @"SelectionCell";

UITableViewCell *cell = [tableView

dequeueReusableCellWithIdentifier:cellId];

if (cell == nil) {

cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault

reuseIdentifier:cellId];

cell.selectionStyle =

UITableViewCellSelectionStyleNone;

cell.backgroundView = nil;

cell.backgroundColor

= [UIColor clearColor];

cell.textLabel.font

= [UIFont systemFontOfSize:SGPOP_DEFAULT_FONT_SIZE];

cell.textLabel.textColor

= [UIColor darkTextColor];

}

if (_selectedIndex == indexPath.row) {

cell.accessoryView

= [[UIImageView alloc]

initWithImage:[UIImage imageNamed:@"oval_selected"]];

}else {

cell.accessoryView

= [[UIImageView alloc]

initWithImage:[UIImage imageNamed:@"oval_unselected"]];

}

cell.textLabel.text = _selections[indexPath.row];

return cell;

}

#pragma mark - UITableview Delegate

-

(CGFloat)tableView:(UITableView

*)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath

{

return SGPOP_DEFAULT_ROW_HEIHGT;

}

-

(void)tableView:(UITableView *)tableView

didSelectRowAtIndexPath:(NSIndexPath *)indexPath

{

_selectedIndex = indexPath.row;

[tableView reloadData];

if

(_selectedHandle) {

_selectedHandle(indexPath.row);

}

}

@end

#import "ViewController.h"

#import "SGPopSelectView.h"

@interface ViewController ()

<UIGestureRecognizerDelegate>

@property (nonatomic,

strong) NSArray *selections;

@property (nonatomic,

strong) SGPopSelectView *popView;

@end

@implementation

ViewController

-

(void)viewDidLoad {

[super

viewDidLoad];

self.selections = @[@"Shake It Off",@"All About that Bass",@"Animals",@"Take Me To Church",@"Out Of The Woods",@"Centuries",@"I'm Not the Only One",@"Burnin' It Down",@"Shake It Off",@"All About that Bass",@"Animals",@"Take Me To Church",@"Out Of The Woods",@"Centuries",@"I'm Not the Only One",@"Burnin' It Down"];

self.popView =

[[SGPopSelectView alloc]

init];

self.popView.selections = self.selections;

__weak typeof(self) weakSelf = self;

self.popView.selectedHandle = ^(NSInteger selectedIndex){

NSLog(@"selected index %ld, content is %@",

selectedIndex, weakSelf.selections[selectedIndex]);

};

}

-

(void)didReceiveMemoryWarning

{

[super

didReceiveMemoryWarning];

// Dispose of any resources that can be

recreated.

}

-

(IBAction)showAction:(id)sender {

// CGPoint p = [(UIButton

*)sender center];

CGPoint p = CGPointMake(100, 240);

[self.popView showFromView:self.view

atPoint:p animated:YES];

}

-

(IBAction)tapAction:(UIGestureRecognizer *)sender {

[self.popView hide:YES];

}

-

(BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer

*)gestureRecognizer

{

CGPoint p = [gestureRecognizer locationInView:self.view];

if (self.popView.visible && CGRectContainsPoint(self.popView.frame, p)) {

return

NO;

}

return YES;

}

@end

a4c26d1e5885305701be709a3d33442f.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值