Я столкнулся с той же проблемой с vertical
scrollview
и использовал подход 2. Даже если этот вопрос старый, я не нашел решения здесь и чувствовал, что было бы здорово ответить. *
Краткий ответ: scrollViewWillEndDragging:withVelocity:targetContentOffset:
метод в UIScrollViewDelegate
protocol
.
Это дает вам targetContentOffset
, когда пользователь заканчивает прокрутку и анимация начинает замедляться. Вы можете изменить targetContentOffset
в этом методе, чтобы animation
заканчивался именно там, где вы можете. Ваша задача - только рассчитать целевую позицию.
Вот подкласс UIView
, который я создал. Я хотел создать класс UIPickerView
, но хотел, чтобы он останавливался на определенных позициях (например, при выборе даты).
Я создал подкласс UIView
, соответствующий UIScrollViewDelegate
. В этом 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