我在verticalscrollview 上遇到了同样的问题,并使用了方法 2。即使这个问题很老,我也没有在这里找到解决方案,觉得回答会很好。
简短的回答是scrollViewWillEndDragging:withVelocity:targetContentOffset:
UIScrollViewDelegateprotocol中的方法。
当用户完成滚动并且动画开始减速时,它会为您提供targetContentOffset。您可以在此方法中更改targetContentOffset,因此animation 将在您可以的位置结束。你的工作只是计算目标位置。
这是我创建的UIView 子类。我想创建一个类似UIPickerView 的类,但我希望它停止在特定位置(例如日期选择器)。
我创建了一个符合UIScrollViewDelegate 的UIView 子类。在这个UIView 中,我确实添加了一个scrollView。这个scrollView 将包含UILabel 实例。小心,我使用ARC,所以我没有发布任何东西。
#import <UIKit/UIKit.h>
@protocol MyPickerViewDataSource <NSObject>
-(NSUInteger)numberOfRowsForSender:(id)sender;
-(NSString *)titleForRowAtIndex:(NSUInteger)rowIndex sender:(id)sender;
@end
@interface MyPickerView : UIView <UIScrollViewDelegate>
@property (weak, nonatomic) id<MyPickerViewDataSource> dataSource;
@end
实施:
#import "MyPickerView.h"
#define CONTENT_ROW_HEIGHT 30
typedef enum {
ScrollDirectionUp,
ScrollDirectionDown
} ScrollDirection;
@interface MyPickerView() {
int topOffset;
int bottomOffset;
int lastContentOffset;
int targetLabelIndex;
ScrollDirection scrollDirection;
}
@implementation PickerView
- (void)initSetup {
self.scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(self.frame.origin.x,self.frame.origin.y, self.frame.size.width, self.frame.size.height)];
self.scrollView.delegate = self;
self.scrollView.showsHorizontalScrollIndicator = NO;
self.scrollView.showsVerticalScrollIndicator = NO;
self.scrollView.userInteractionEnabled = YES;
[self addSubview:self.scrollView];
targetLabelIndex = 0;
topOffset = (self.scrollView.frame.size.height/2)-CONTENT_ROW_HEIGHT/2;
bottomOffset = topOffset;
}
- (id)initWithCoder:(NSCoder *)aDecoder {
self = [super initWithCoder:aDecoder];
if(self) {
[self initSetup];
}
return self;
}
- (id)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if(self) {
[self initSetup];
}
return self;
}
- (void)layoutSubviews {
[super layoutSubviews];
NSUInteger numberOfRows = [self.dataSource numberOfRowsForSender:self];
self.scrollView.contentSize = CGSizeMake(self.scrollView.frame.size.width, topOffset+numberOfRows*CONTENT_ROW_HEIGHT+bottomOffset);
for (int index = 0; index < numberOfRows; index++)
{
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(self.scrollView.frame.origin.x,
topOffset+index*CONTENT_ROW_HEIGHT,
self.scrollView.frame.size.width,
CONTENT_ROW_HEIGHT)];
label.backgroundColor = [UIColor clearColor];
label.textColor = [UIColor colorWithRed:1.0 green:1.0 blue:1.0 alpha:1.0];
label.text = [self.dataSource titleForRowAtIndex:index sender:self];
[self.scrollView addSubview:label];
}
[(UILabel *)[self.scrollView.subviews objectAtIndex:targetLabelIndex] setTextColor:[UIColor blueColor]];
}
- (void)reloadData {
NSUInteger numberOfRows = [self.dataSource numberOfRowsForSender:self];
self.scrollView.contentSize = CGSizeMake(self.scrollView.frame.size.width, numberOfRows*CONTENT_ROW_HEIGHT);
[self.scrollView setContentOffset:CGPointMake(0.0, 0.0) animated:NO];
[self layoutSubviews];
}
#pragma mark - UIScrollViewDelegate
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
if(lastContentOffset>self.scrollView.contentOffset.y) {
scrollDirection = ScrollDirectionUp;
}
else {
scrollDirection = ScrollDirectionDown;
}
lastContentOffset = self.scrollView.contentOffset.y;
}
- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset {
targetLabelIndex = (targetContentOffset->y/CONTENT_ROW_HEIGHT)+1;
if(scrollDirection==ScrollDirectionUp && targetLabelIndex>0) {
targetLabelIndex--;
}
targetContentOffset->y = targetLabelIndex*CONTENT_ROW_HEIGHT;
[(UILabel *)[self.scrollView.subviews objectAtIndex:targetLabelIndex] setTextColor:[UIColor blueColor]];
}
@end