【问题标题】:uitableview drag down outside screenuitableview 向下拖动到屏幕外
【发布时间】:2015-02-22 14:15:21
【问题描述】:

我基本上是在尝试实现这个效果:http://youtu.be/VBW2i0P11iI

tableview 是一个基本的,通过自动布局固定到它的 superview。下面的视图添加了经典的 insertSubview:belowSubview:/addChildViewController 组合。

我尝试了几种方法。我现在拥有的是:

if (scrollOffset >= -scrollView.contentInset.top) {
        self.resultsTableViewContainerTopConstraint.constant = 0;
    } else {
        self.resultsTableViewContainerTopConstraint.constant = MAX(self.resultsTableViewContainerTopConstraint.constant, self.resultsTableViewContainerTopConstraint.constant - scrollDiff);
    }
}

所以我基本上是根据 contentOffset 的增量来更改顶部约束。这样做的问题是 uitableview 反弹回来,所以它总是进入 if 的第一个分支。但即使我解决了这个问题,我也觉得我只会修补它。我确信有一种更优雅的方式可以在具有相同响应能力的视频中实现效果。

任何建议将不胜感激。 谢谢

【问题讨论】:

    标签: ios uitableview scrollview parallax contentoffset


    【解决方案1】:

    我不确定这是否是你想要的,但我做了一个快速演示:

    ViewController.h

    #import <UIKit/UIKit.h>
    
    @interface ViewController : UIViewController <UITableViewDataSource, UITableViewDelegate, UIScrollViewDelegate>
    
    @property (nonatomic, strong) UIView *headerView;
    @property (nonatomic, strong) UILabel *lblTitle;
    
    @property (nonatomic, strong) UIButton *btnReset;
    
    @property (nonatomic, strong) UIImageView *imageView;
    
    @property (nonatomic, strong) UIScrollView *scrollView;
    @property (nonatomic, strong) UITableView *tableView;
    
    @property (nonatomic, strong) NSLayoutConstraint *scrollViewTopConstraint;
    
    @end
    

    ViewController.m

    #import "ViewController.h"
    
    @interface ViewController ()
    
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        // Do any additional setup after loading the view, typically from a nib.
    
        //self.view.backgroundColor = [UIColor whiteColor];
    
        [self initViews];
        [self initConstraints];
    }
    
    - (void)didReceiveMemoryWarning {
        [super didReceiveMemoryWarning];
        // Dispose of any resources that can be recreated.
    }
    
    -(void)initViews
    {
        self.view.backgroundColor = [UIColor colorWithRed:43.0/255.0 green:39.0/255.0 blue:55.0/255.0 alpha:1.0];
    
        self.scrollView = [[UIScrollView alloc] init];
        self.scrollView.backgroundColor = [UIColor clearColor];
        self.scrollView.alwaysBounceVertical = YES;
        self.scrollView.delegate = self;
    
        self.headerView = [[UIView alloc] init];
        self.headerView.backgroundColor = [UIColor colorWithRed:43.0/255.0 green:39.0/255.0 blue:55.0/255.0 alpha:1.0];
        self.headerView.layer.shadowColor = [UIColor blackColor].CGColor;
        self.headerView.layer.shadowOffset = CGSizeMake(0,0);
        self.headerView.layer.shadowOpacity = 0.25;
        self.headerView.layer.shadowRadius = 4;
    
        self.lblTitle = [[UILabel alloc] init];
        self.lblTitle.text = @"HEADER VIEW";
        self.lblTitle.textColor = [UIColor whiteColor];
        self.lblTitle.textAlignment = NSTextAlignmentCenter;
    
        self.btnReset = [[UIButton alloc] init];
        [self.btnReset setTitle:@"Reset" forState:UIControlStateNormal];
        self.btnReset.backgroundColor = [UIColor colorWithRed:0.75 green:0.0 blue:0.0 alpha:1.0];
        self.btnReset.layer.cornerRadius = 5.0;
        [self.btnReset addTarget:self action:@selector(resetView) forControlEvents:UIControlEventTouchUpInside];
    
        self.imageView = [[UIImageView alloc] init];
        self.imageView.backgroundColor = [UIColor colorWithRed:43.0/255.0 green:39.0/255.0 blue:55.0/255.0 alpha:1.0];
    
        self.tableView = [[UITableView alloc] init];
        self.tableView.delegate = self;
        self.tableView.dataSource = self;
        self.tableView.rowHeight = 150.0;
        self.tableView.layer.shadowColor = [UIColor blackColor].CGColor;
        self.tableView.layer.shadowOffset = CGSizeMake(0,-5);
        self.tableView.layer.shadowOpacity = 0.5;
        self.tableView.layer.shadowRadius = 20;
        self.tableView.backgroundColor = [UIColor clearColor];
        self.tableView.scrollEnabled = NO;
        self.tableView.clipsToBounds = NO;
    
    
        [self.headerView addSubview:self.lblTitle];
        [self.headerView addSubview:self.btnReset];
    
        [self.scrollView addSubview:self.tableView];
    
        [self.view addSubview:self.imageView];
        [self.view addSubview:self.scrollView];
        [self.view addSubview:self.headerView];
    
    }
    
    -(void)initConstraints
    {
        self.scrollView.translatesAutoresizingMaskIntoConstraints = NO;
        self.headerView.translatesAutoresizingMaskIntoConstraints = NO;
        self.lblTitle.translatesAutoresizingMaskIntoConstraints = NO;
        self.btnReset.translatesAutoresizingMaskIntoConstraints = NO;
        self.imageView.translatesAutoresizingMaskIntoConstraints = NO;
        self.tableView.translatesAutoresizingMaskIntoConstraints = NO;
    
        id views = @{
                     @"scrollView": self.scrollView,
                     @"headerView": self.headerView,
                     @"lblTitle": self.lblTitle,
                     @"btnReset": self.btnReset,
                     @"imageView": self.imageView,
                     @"tableView": self.tableView
                     };
    
        [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[scrollView]|" options:0 metrics:nil views:views]];
        [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[scrollView]" options:0 metrics:nil views:views]];
    
        [self.view addConstraint:[NSLayoutConstraint constraintWithItem:self.scrollView attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeHeight multiplier:1.0 constant:0.0]];
    
    
    
        self.scrollViewTopConstraint = [NSLayoutConstraint constraintWithItem:self.scrollView attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeTop multiplier:1.0 constant:0.0];
    
        [self.view addConstraint:self.scrollViewTopConstraint];
    
    
    
    
        [self.view addConstraint:[NSLayoutConstraint constraintWithItem:self.scrollView attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeHeight multiplier:1.0 constant:0.0]];
    
        [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[headerView(320)]|" options:0 metrics:nil views:views]];
    
        [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[headerView(50)]" options:0 metrics:nil views:views]];
    
        [self.scrollView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[tableView(320)]|" options:0 metrics:nil views:views]];
    
        [self.scrollView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-150-[tableView(300)]|" options:0 metrics:nil views:views]];
    
        [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[imageView(320)]|" options:0 metrics:nil views:views]];
        [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[imageView(320)]" options:0 metrics:nil views:views]];
    
        [self.headerView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[lblTitle]|" options:0 metrics:nil views:views]];
        [self.headerView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[lblTitle]|" options:0 metrics:nil views:views]];
    
        [self.headerView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:[btnReset(80)]-5-|" options:0 metrics:nil views:views]];
        [self.headerView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-8-[btnReset]-8-|" options:0 metrics:nil views:views]];
    }
    
    -(BOOL)prefersStatusBarHidden
    {
        return YES;
    }
    
    #pragma mark - TableView Methods -
    
    -(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
    {
        return 2;
    }
    
    -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
    {
        static NSString *cellID = @"cell";
    
        UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellID];
    
        if(cell == nil)
        {
            cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellID];
        }
    
        cell.backgroundColor = [UIColor colorWithRed:0.5 green:0.5 blue:0.5 alpha:1.0];
    
        return cell;
    }
    
    #pragma mark - ScrollView Delegate -
    
    -(void)scrollViewDidScroll:(UIScrollView *)scrollView
    {
        //NSLog(@"scrollView offset = %lf", scrollView.contentOffset.y);
    
        if(scrollView.contentOffset.y <= -145)
        {
            //self.scrollView.scrollEnabled = NO;
    
            self.scrollViewTopConstraint.constant = self.view.bounds.size.height;
    
            [UIView animateWithDuration:0.5 delay:0.0 options:UIViewAnimationOptionCurveEaseOut animations:^{
    
                [self.scrollView layoutIfNeeded];
    
            } completion:^(BOOL finished) {
    
            }];
        }
    }
    
    -(void)resetView
    {
        self.scrollViewTopConstraint.constant = 0;
    
        [UIView animateWithDuration:0.5 delay:0.0 options:UIViewAnimationOptionCurveEaseIn animations:^{
    
            [self.scrollView layoutIfNeeded];
    
        } completion:^(BOOL finished) {
    
        }];
    }
    

    打开应用后得到的结果:

    然后你向下拖动到边缘,视图会突然打开:

    按下红色的重置按钮将其恢复:D

    【讨论】:

    • 感谢非常详细的回答 :) 我已经尝试过了,效果很好。我的问题是,一旦你点击了某个 contentOffset,表格视图就会出现在屏幕之外。我真正想要实现的是跟随我手指的表格视图(和导航栏)(它应该仅在释放并通过某个 contentOffset 时才开始动画)。您可以在视频的第一个动画中看到这一点
    • 是什么阻止您在另一个 scrollViewDidEndDragging 委托方法而不是 scrollViewDidScroll 方法中执行检查以触发表格向下滑动?我只是在 scrollViewDidScroll 方法中做的,作为一种快速破解。
    • 我想知道如何通过自定义视图控制器转换来完成。它可能更干净,一旦你编写了样板代码,它就可以在以后使用。最好的做法是什么?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-09-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-18
    • 2017-06-06
    相关资源
    最近更新 更多