如何为 UIScrollView 启用方向锁定?

Posted

技术标签:

【中文标题】如何为 UIScrollView 启用方向锁定?【英文标题】:How do I enable directional lock for a UIScrollView? 【发布时间】:2010-10-26 02:35:36 【问题描述】:

我有一个UIScrollView,里面有一个UIView。我想锁定 x 轴,以便视图仅垂直滚动。如何启用定向锁定?

【问题讨论】:

【参考方案1】:

首先,将UIScrollViewcontentSize 设置为等于或小于UIScrollView 框架的宽度。

接下来,将 UIScrollView's alwaysBounceHorizontal 设置为 NO。这将防止滚动视图出现“橡皮筋”,即使您已经告诉它没有更多的水平内容要显示。

UIScrollView *scrollView;
CGSize size = scrollView.contentSize;
size.width = CGRectGetWidth(scrollView.frame);
scrollView.contentSize = size;
scrollView.alwaysBounceHorizontal = NO;

滚动视图中的实际内容并不重要。

Swift 5.0

let scrollView = UIScrollView() // Or however you want to initialize it
var size = scrollView.contentSize
size.width = scrollView.frame.width
scrollView.contentSize = size
scrollView.alwaysBounceHorizontal = false

【讨论】:

即使在 Xcode 7 中这也对我有帮助。我必须关闭情节提要中的反弹才能使方向锁定起作用(即使我已经启用了方向锁定)。【参考方案2】:
#import <UIKit/UIKit.h>


@interface DemoButtonViewController : UIViewController <UIScrollViewDelegate>

@property (nonatomic, strong) UIScrollView *filterTypeScrollView;
@property (nonatomic, strong) UIBarButtonItem *lockButton;

- (void)lockFilterScroll:(id)sender;

@end

#import "DemoButtonViewController.h"

@implementation DemoButtonViewController

@synthesize filterTypeScrollView;
@synthesize lockButton;

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil

    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];

    if (self) 
    
        // Custom initialization
    
    return self;


- (void)didReceiveMemoryWarning

    // Releases the view if it doesn't have a superview.
    [super didReceiveMemoryWarning];

    // Release any cached data, images, etc that aren't in use.


- (void)viewDidLoad

    [super viewDidLoad];

    self.view.backgroundColor = [UIColor darkGrayColor];
    self.filterTypeScrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 130, self.view.frame.size.width, 320)];
    filterTypeScrollView.contentSize = CGSizeMake(self.view.frame.size.width*4, 320);
    filterTypeScrollView.pagingEnabled = YES;
    filterTypeScrollView.delegate = self;
    [self.view addSubview:filterTypeScrollView];

    UIToolbar *lockbar = [[UIToolbar alloc] initWithFrame:CGRectMake(0, 450, self.view.frame.size.width, 30)];
    lockbar.barStyle = UIBarStyleBlackTranslucent;
    self.lockButton = [[UIBarButtonItem alloc] initWithTitle:@"Lock Filter Scroll" style:UIBarButtonItemStylePlain target:self action:@selector(lockFilterScroll:)];
    [lockbar setItems:[NSArray arrayWithObjects:[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil],lockButton,nil]]; 
    [self.view addSubview:lockbar];


- (void)viewDidUnload

    [super viewDidUnload];


- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation

    // Return YES for supported orientations  
    return (interfaceOrientation == UIInterfaceOrientationPortrait);


- (void)lockFilterScroll:(id)sender

    filterTypeScrollView.scrollEnabled = !filterTypeScrollView.scrollEnabled;

    if (filterTypeScrollView.scrollEnabled) 
    
        [lockButton setTitle:@"Lock Filter Scroll"];
     
    else 
        [lockButton setTitle:@"Unlock Filter Scroll"];
    


@end

【讨论】:

【参考方案3】:

您将继承 UIScrollView 并覆盖 touchesBegan:withEvent: 方法、touchesMoved:withEvent: 方法和 touchesEnded:withEvent: 方法。

您将使用这些方法以及触摸的起点和终点来计算发生了什么样的触摸事件:是简单的点击,还是水平或垂直滑动?

如果是水平滑动,则取消触摸事件。

查看source code here,了解如何开始。

【讨论】:

我认为最好通知滚动视图您的意图,而不是手动取消自己的触摸。使用您的方法,如果您开始水平拖动(即使是偶然的),则无法垂直拖动并使其正常工作。 我担心有人会这样说...我敢肯定,这是一种锁定轴的可靠方法,但我想我会继续寻找一种更懒惰的方法来做到这一点。不过感谢您的回复。 Nick Farina 通过建议解决了我的问题:首先,将 UIScrollView 的“contentSize”设置为等于或小于 UIScrollView 框架的宽度。接下来,将 UIScrollView 的“alwaysBounceHorizo​​ntal”设置为 NO。这将防止滚动视图出现“橡皮筋”,即使您告诉它没有更多的水平内容要显示。

以上是关于如何为 UIScrollView 启用方向锁定?的主要内容,如果未能解决你的问题,请参考以下文章

Swift:如何为 CALayer 启用捏合缩放功能?

如何为Flex Mobile中的某些视图启用方向更改?

如何为 IDWriteTextLayout 指定歧义字符的方向性?

如何在启用分页的情况下实现 UIScrollView 平铺?

约束 UIScrollView 平移?

如何在启用分页的 UIScrollView 中延迟加载 100 多个页面?