UI控件 - 简单的抽屉效果

本文介绍如何在iOS应用中实现简单的抽屉效果。通过在主控制器添加子控件,利用KVO监听frame变化来判断滑动方向,并处理滑动手势,根据滑动距离调整界面位置。最终在手指松开时完成抽屉的定位效果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

抽屉效果图

右移                                                                                             左移
   

抽屉效果实现步骤

<span style="font-size:14px;background-color: rgb(255, 255, 255);">@interface YZHViewController ()
@property (nonatomic, strong) UIView *leftView;
@property (nonatomic, strong) UIView *rightView;
@property (nonatomic, strong) UIView *mainView;
@property (nonatomic, assign) BOOL isDraging;

@end</span>

1. 在主控制器中添加子控件   分别为主界面 左滑界面 右滑界面

- (void)viewDidLoad
{
    [super viewDidLoad];
	// Do any additional setup after loading the view, typically from a nib.
    //  在view上添加三个view 分别为主界面 左滑界面 右滑界面
    [self addView];
    //  KVO 监听当前类的属性的改变
    [_mainView addObserver:self forKeyPath:@"frame" options:NSKeyValueObservingOptionNew context:nil];
    
}


- (void)addView
{
    //
    UIView *leftView = [[UIView alloc] initWithFrame:self.view.bounds];
    leftView.backgroundColor = [UIColor redColor];
    _leftView =leftView;
    [self.view addSubview:leftView];
    
    //
    UIView *rightView = [[UIView alloc] initWithFrame:self.view.bounds];
    rightView.backgroundColor = [UIColor greenColor];
    _rightView = rightView;
    [self.view addSubview:rightView];
    
    //
    UIView *mainView = [[UIView alloc] initWithFrame:self.view.bounds];
    mainView.backgroundColor = [UIColor blueColor];
    _mainView = mainView;
    [self.view addSubview:mainView];
}


2. KVO 监听当前类的frame属性的改变,判断滑动方向

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
    // keyPath
    if (_mainView.frame.origin.x < 0) {
        _leftView.hidden = NO;
        _rightView.hidden = YES;
    }else if(_mainView.frame.origin.x > 0){
        _leftView.hidden = YES;
        _rightView.hidden = NO;
    }
}


3. 处理手指滑动事件

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
    UITouch *touch = [touches anyObject];
    CGPoint curP = [touch locationInView:self.view];
    CGPoint preP = [touch previousLocationInView:self.view];
    CGFloat offSetX = curP.x - preP.x;
    
    _mainView.frame = [self frameWithOffSetX:offSetX];
    
    _isDraging = YES;
    
}


4. 根据滑动改变量offSetX设置滑动的效果

<p style="margin-top: 0px; margin-bottom: 0px; font-size: 13px; font-family: Menlo; color: rgb(120, 73, 42);">#define screenW [UIScreen mainScreen].bounds.size.width</p><p style="margin-top: 0px; margin-bottom: 0px; font-size: 13px; font-family: Menlo; color: rgb(120, 73, 42);">#define screenH [UIScreen mainScreen].bounds.size.height</p><p style="margin-top: 0px; margin-bottom: 0px; font-size: 13px; font-family: Menlo; color: rgb(120, 73, 42);">#define WWMaxY <span style="color: #272ad8">60</span></p>
- (CGRect )frameWithOffSetX:(CGFloat ) offsetX
{
    CGFloat offsetY = WWMaxY / screenH * offsetX;
    CGFloat scale = (screenH - 2 * offsetY) / screenH;
    
    if (_mainView.frame.origin.x < 0) { //offsetY 是负数
        scale = (screenH + 2 * offsetY) / screenH;
    }
    CGRect frame = _mainView.frame;
    CGFloat w = frame.size.width * scale;
    CGFloat h = frame.size.height * scale;
    CGFloat x = frame.origin.x + offsetX;
    CGFloat y = (screenH - h) * 0.5;
    frame = CGRectMake(x, y, w, h);
    return frame;
}


5. 松手实现定位

#define WWTargetRightX 250
#define WWTargetLeftX -220
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
    if (!_isDraging && _mainView.frame.origin.x != 0) { // 没有拖拽
        
        [UIView animateWithDuration:0.25 animations:^{
            
            _mainView.frame = self.view.bounds;
        }];
        return ;
        
    }
    
    CGFloat targetX = 0;
    if (_mainView.frame.origin.x > screenW * 0.5) {
        targetX = WWTargetRightX;
    }else if (CGRectGetMaxX(_mainView.frame) < screenW * 0.5){
        targetX = WWTargetLeftX;
    }
    [UIView animateWithDuration:0.25 animations:^{
        
        if (targetX) {
            
            CGFloat offsetX = targetX - _mainView.frame.origin.x;
            
            _mainView.frame = [self frameWithOffSetX:offsetX];
        }else{
            _mainView.frame = self.view.bounds;
        }
    }];
    
    _isDraging = NO;
    
}








评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值