首頁 > 軟體

iOS簡單抽屜效果的實現方法

2022-08-08 14:00:46

本文範例為大家分享了iOS實現簡單抽屜效果的具體程式碼,供大家參考,具體內容如下

實現思路及步驟:

1、首先準備要滑動的view

#warning 第一步
- (void)addChildView
{
    // left
    UIView *leftView = [[UIView alloc] initWithFrame:self.view.bounds];
    leftView.backgroundColor = [UIColor greenColor];
    [self.view addSubview:leftView];
    _leftView = leftView;
    
    // right
    UIView *rightView = [[UIView alloc] initWithFrame:self.view.bounds];
    rightView.backgroundColor = [UIColor blueColor];
    [self.view addSubview:rightView];
    _rightView = rightView;
    
    // mainView
    UIView *mainView = [[UIView alloc] initWithFrame:self.view.bounds];
    mainView.backgroundColor = [UIColor redColor];
    [self.view addSubview:mainView];
    _mainView = mainView;
}

2、監聽觸控事件,記錄橫軸方向的偏移量,有了偏移量就可以通過偏移量改動檢視的位置

#warning 第二布
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
    // 獲取UITouch物件
    UITouch *touch = [touches anyObject];
    
    // 獲取當前點
    CGPoint currentPoint = [touch locationInView:self.view];
    
    // 獲取上一個點
    CGPoint prePoint = [touch previousLocationInView:self.view];
    
    // x軸偏移量:當手指移動一點的時候,x偏移多少
    CGFloat offsetX = currentPoint.x - prePoint.x;
    
    // 設定當前主檢視的frame
    _mainView.frame = [self getCurrentFrameWithOffsetX:offsetX];
    
    
    _isDraging = YES;
}
  如何實時監聽一個物件的屬性(只能監聽物件,不能監聽結構體)?kvo
  // 1.監聽  2 ,實現:observeValueForKeyPath 方法
  /**
     *  給_mainView新增一個觀察者
     *
     *  KeyPath:監聽frame這個屬性
     *
     *  options:監聽新值的改變
     */
    [_mainView addObserver:self forKeyPath:@"frame" options:NSKeyValueObservingOptionNew context:nil]; //實時監聽mainview的frame
 
 
// 當_mainView的frame屬性改變的時候就會呼叫
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
    NSLog(@"%@", NSStringFromCGRect(_mainView.frame));//當前的frame
    
    if (_mainView.frame.origin.x < 0) { // 主介面的x<0,往左移動
        // 顯示右邊
        _rightView.hidden = NO;
        // 隱藏左邊
        _leftView.hidden = YES;
    }else if (_mainView.frame.origin.x > 0){ // 往右移動
        // 顯示左邊
        _rightView.hidden = YES;
        // 隱藏右邊
        _leftView.hidden = NO;
        
    }
} 

當x軸偏移的時候,如何縮放高度?
當x偏移時,y軸縮小為: x的偏移量/

#define HMMaxY 60
// 當手指偏移一點,根據X軸的偏移量算出當前主檢視的frame
- (CGRect)getCurrentFrameWithOffsetX:(CGFloat)offsetX
{
    CGFloat screenW = [UIScreen mainScreen].bounds.size.width;
    CGFloat screenH = [UIScreen mainScreen].bounds.size.height;
    
    // 獲取y軸偏移量,手指每移動一點,y軸偏移多少
    CGFloat offsetY = offsetX * HMMaxY / screenW;//HMMaxY 縮放的最大Y 
    
    CGFloat scale = (screenH - 2 * offsetY) / screenH;//比例 
    
    if (_mainView.frame.origin.x < 0) { // 往左邊滑動
        scale = (screenH + 2 * offsetY) / screenH;
    }
    
    // 獲取之前的frame
    CGRect frame = _mainView.frame;
    frame.origin.x += offsetX;
    frame.size.height = frame.size.height *scale;
    frame.size.width = frame.size.width *scale;
    frame.origin.y = (screenH - frame.size.height) * 0.5;
    
    return frame;
}

定位:

#define HMRTarget 250
#define HMLTarget -220
/*
 _mainView.frame.origin.x > screenW * 0.5 定位到右邊
  CGRectGetMaxX(_mainView.frame) < screenW * 0.5 定位到左邊 -220
 
 */
// 定位
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
    
    // 復位
    if (_isDraging == NO && _mainView.frame.origin.x != 0) {
        [UIView animateWithDuration:0.25 animations:^{
            
            _mainView.frame = self.view.bounds;
        }];
    }
    
    
    CGFloat screenW = [UIScreen mainScreen].bounds.size.width;
    
    CGFloat target = 0;
    if (_mainView.frame.origin.x > screenW * 0.5) { // 定位到右邊
        target = HMRTarget;
    }else if (CGRectGetMaxX(_mainView.frame) < screenW * 0.5) { // 定位到左邊
        target = HMLTarget;
    }
    
    [UIView animateWithDuration:0.25 animations:^{
        
        if (target) { // 在需要定位左邊或者右邊
            
            // 獲取x軸偏移量
            CGFloat offsetX = target - _mainView.frame.origin.x;
            
            // 設定當前主檢視的frame
            _mainView.frame = [self getCurrentFrameWithOffsetX:offsetX];
            
        }else{ // 還原
            _mainView.frame = self.view.bounds;
        }
    }];
    
    _isDraging = NO;
    
}

全:

@interface HMDrawViewController ()
 
 
@property (nonatomic, assign) BOOL isDraging;
@end
 
@implementation HMDrawViewController
 
 
- (void)viewDidLoad
{
    // UIViewController
    [super viewDidLoad];
    // Do any additional setup after loading the view.
   
    // 1.新增子控制元件
    [self addChildView];
#warning 第三步 觀察_mainView的frame改變
    // 2.監聽
    /**
     *  給_mainView新增一個觀察者
     *
     *  KeyPath:監聽frame這個屬性
     *
     *  options:監聽新值的改變
     */
    [_mainView addObserver:self forKeyPath:@"frame" options:NSKeyValueObservingOptionNew context:nil];
   
}
 
// 當_mainView的frame屬性改變的時候就會呼叫
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
    NSLog(@"%@", NSStringFromCGRect(_mainView.frame));
    
    if (_mainView.frame.origin.x < 0) { // 往左移動
        // 顯示右邊
        _rightView.hidden = NO;
        // 隱藏左邊
        _leftView.hidden = YES;
    }else if (_mainView.frame.origin.x > 0){ // 往右移動
        // 顯示左邊
        _rightView.hidden = YES;
        // 隱藏右邊
        _leftView.hidden = NO;
        
    }
}
 
#warning 第一步
- (void)addChildView
{
    // left
    UIView *leftView = [[UIView alloc] initWithFrame:self.view.bounds];
    leftView.backgroundColor = [UIColor greenColor];
    [self.view addSubview:leftView];
    _leftView = leftView;
    
    // right
    UIView *rightView = [[UIView alloc] initWithFrame:self.view.bounds];
    rightView.backgroundColor = [UIColor blueColor];
    [self.view addSubview:rightView];
    _rightView = rightView;
    
    // mainView
    UIView *mainView = [[UIView alloc] initWithFrame:self.view.bounds];
    mainView.backgroundColor = [UIColor redColor];
    [self.view addSubview:mainView];
    _mainView = mainView;
}
 
#warning 第二布
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
    // 獲取UITouch物件
    UITouch *touch = [touches anyObject];
    
    // 獲取當前點
    CGPoint currentPoint = [touch locationInView:self.view];
    
    // 獲取上一個點
    CGPoint prePoint = [touch previousLocationInView:self.view];
    
    // x軸偏移量:當手指移動一點的時候,x偏移多少
    CGFloat offsetX = currentPoint.x - prePoint.x;
    
    // 設定當前主檢視的frame
    _mainView.frame = [self getCurrentFrameWithOffsetX:offsetX];
    
    
    _isDraging = YES;
}
#warning 第四步
#define HMMaxY 60
// 當手指偏移一點,根據X軸的偏移量算出當前主檢視的frame
- (CGRect)getCurrentFrameWithOffsetX:(CGFloat)offsetX
{
    CGFloat screenW = [UIScreen mainScreen].bounds.size.width;
    CGFloat screenH = [UIScreen mainScreen].bounds.size.height;
    
    // 獲取y軸偏移量,手指每移動一點,y軸偏移多少
    CGFloat offsetY = offsetX * HMMaxY / screenW;
    
    CGFloat scale = (screenH - 2 * offsetY) / screenH;
    
    if (_mainView.frame.origin.x < 0) { // 往左邊滑動
        scale = (screenH + 2 * offsetY) / screenH;
    }
    
    // 獲取之前的frame
    CGRect frame = _mainView.frame;
    frame.origin.x += offsetX;
    frame.size.height = frame.size.height *scale;
    frame.size.width = frame.size.width *scale;
    frame.origin.y = (screenH - frame.size.height) * 0.5;
    
    return frame;
}
 
#define HMRTarget 250
#define HMLTarget -220
/*
 _mainView.frame.origin.x > screenW * 0.5 定位到右邊
  CGRectGetMaxX(_mainView.frame) < screenW * 0.5 定位到左邊 -220
 
 */
// 定位
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
    
    // 復位
    if (_isDraging == NO && _mainView.frame.origin.x != 0) {
        [UIView animateWithDuration:0.25 animations:^{
            
            _mainView.frame = self.view.bounds;
        }];
    }
    
    
    CGFloat screenW = [UIScreen mainScreen].bounds.size.width;
    
    CGFloat target = 0;
    if (_mainView.frame.origin.x > screenW * 0.5) { // 定位到右邊
        target = HMRTarget;
    }else if (CGRectGetMaxX(_mainView.frame) < screenW * 0.5) { // 定位到左邊
        target = HMLTarget;
    }
    
    [UIView animateWithDuration:0.25 animations:^{
        
        if (target) { // 在需要定位左邊或者右邊
            
            // 獲取x軸偏移量
            CGFloat offsetX = target - _mainView.frame.origin.x;
            
            // 設定當前主檢視的frame
            _mainView.frame = [self getCurrentFrameWithOffsetX:offsetX];
            
        }else{ // 還原
            _mainView.frame = self.view.bounds;
        }
    }];
    
    _isDraging = NO;
    
}

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支援it145.com。


IT145.com E-mail:sddin#qq.com