You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Objective-C:如何禁用模态视图的上滑回弹效果

如何禁用iOS PageSheet模态视图的上滑回弹效果

问题场景

我通过以下代码以UIModalPresentationPageSheet样式展示包含CollectionView的导航控制器,并设置了占屏幕60%高度的自定义detent:

GridMenuViewController* vc = [[UIStoryboard storyboardWithName:@"Main" bundle:nil] instantiateViewControllerWithIdentifier:@"GridMenuViewControllerID"];
GridMenuNavigationController *nav = [[GridMenuNavigationController alloc] initWithRootViewController:vc];
vc.sheetPresentationController.prefersScrollingExpandsWhenScrolledToEdge = NO;
nav.modalPresentationStyle = UIModalPresentationPageSheet;
if (@available(iOS 16.0, *)) {
    if (nav.sheetPresentationController) {
        id detent = [UISheetPresentationControllerDetent customDetentWithIdentifier:UISheetPresentationControllerDetentIdentifierLarge resolver:^CGFloat(id<UISheetPresentationControllerDetentResolutionContext>  _Nonnull context) {
            return [[UIScreen mainScreen] bounds].size.height * 0.6;
        }];
        nav.sheetPresentationController.detents = @[detent];
        nav.sheetPresentationController.prefersGrabberVisible = YES;
    }
}
nav.sheetPresentationController.prefersScrollingExpandsWhenScrolledToEdge = NO;
[self presentViewController:nav animated:YES completion:nil];

我需要完全禁用该模态视图上滑时的回弹效果,但尝试以下方法均未生效:

  • 调整CollectionView的contentInsetAdjustmentBehavior:
if (@available(iOS 11.0, *)) {
    self.collectionView.contentInsetAdjustmentBehavior = 2;
} else {
    self.collectionView.automaticallyAdjustsScrollIndicatorInsets = NO;
}
  • 设置滚动指示器内边距:
self.collectionView.verticalScrollIndicatorInsets = UIEdgeInsetsMake(0, 0, self.view.safeAreaInsets.bottom, 0);
  • 在scrollViewDidScroll强制固定contentOffset:
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
    [scrollView setContentOffset: CGPointMake(scrollView.contentOffset.x, 0)];
}

解决方案

你遇到的回弹并非CollectionView的滚动回弹,而是PageSheet容器本身的拖拽回弹行为,需针对Sheet控制器进行处理:

方案1:完全禁用Sheet的拖拽交互

如果不需要用户拖拽调整Sheet高度,可直接禁用拖拽:

if (@available(iOS 16.0, *)) {
    nav.sheetPresentationController.prefersScrollingExpandsWhenScrolledToEdge = NO;
    nav.sheetPresentationController.isInteractive = NO; // 禁用Sheet的拖拽交互
}

方案2:保留拖拽但禁止回弹(灵活方案)

若需保留拖拽但禁止超出自定义detent的回弹,需通过代理和手势拦截实现:

  1. 给导航控制器设置Sheet代理:
nav.sheetPresentationController.delegate = self;
  1. 实现代理方法锁定detent位置:
#pragma mark - UISheetPresentationControllerDelegate
- (void)sheetPresentationControllerDidChangeSelectedDetentIdentifier:(UISheetPresentationController *)sheetPresentationController API_AVAILABLE(ios(16.0)) {
    if (![sheetPresentationController.selectedDetentIdentifier isEqualToString:UISheetPresentationControllerDetentIdentifierLarge]) {
        [sheetPresentationController setSelectedDetentIdentifier:UISheetPresentationControllerDetentIdentifierLarge animated:NO];
    }
}
  1. 拦截拖拽手势限制上滑范围:
- (void)viewDidAppear:(BOOL)animated {
    [super viewDidAppear:animated];
    if (@available(iOS 16.0, *)) {
        for (UIGestureRecognizer *gesture in self.navigationController.sheetPresentationController.presentingViewController.view.gestureRecognizers) {
            if ([gesture isKindOfClass:[UIPanGestureRecognizer class]]) {
                [(UIPanGestureRecognizer *)gesture addTarget:self action:@selector(handleSheetPanGesture:)];
            }
        }
    }
}

- (void)handleSheetPanGesture:(UIPanGestureRecognizer *)gesture {
    if (@available(iOS 16.0, *)) {
        UISheetPresentationController *sheetPC = self.navigationController.sheetPresentationController;
        CGPoint translation = [gesture translationInView:gesture.view];
        
        // 禁止向上拖拽超出当前detent位置
        if (translation.y < 0) {
            gesture.enabled = NO;
            gesture.enabled = YES;
            [sheetPC setSelectedDetentIdentifier:UISheetPresentationControllerDetentIdentifierLarge animated:NO];
        }
    }
}

额外处理:禁用CollectionView自身回弹

如果CollectionView本身存在滚动回弹,需补充设置:

// 完全禁用CollectionView滚动回弹
self.collectionView.bounces = NO;
// 或仅禁用顶部回弹
self.collectionView.alwaysBounceVertical = NO;

无效原因说明

你之前的代码均针对CollectionView的滚动属性调整,但问题核心是PageSheet容器的拖拽回弹,而非CollectionView自身滚动,因此这些设置无法解决问题。

内容的提问来源于stack exchange,提问作者Satoshi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 16:37:13