остановка UIScrollView в определенной позиции - PullRequest
0 голосов
/ 13 декабря 2010

Я пытаюсь реализовать горизонтальную прокрутку для приложения для iPad.Представление прокрутки показывает серию изображений.После прокрутки, когда вид прокрутки останавливается, я хочу, чтобы изображения были выровнены вдоль определенных точек по горизонтали.Чтобы сделать это, я попробовал 2 подхода:

1) Отключите прокрутку для UIScrollView и вместо этого реализуйте PanGestureRecogniser, который бы определял перемещение и скорость движения «пролистывание / перетаскивание» и устанавливал смещение содержимого представления прокрутки.в соответствии с необходимыми заранее определенными точками.Но проблема здесь в том, что если пользователь медленно перетаскивает представление прокрутки, движение представления прокрутки становится очень прерывистым, потому что полученный х, скоординированный с видом прокрутки, перепрыгивает назад и вперед вокруг точки, в которой нажат палец.Например: значения х изменяются от 50 до 70, когда палец движется вдоль 60-70.Как я могу сделать движение представления прокрутки плавным?

2) Включите прокрутку для UIScrollView и проверьте конец замедления, а затем установите смещение содержимого представления прокрутки, чтобы установить его в нужное положение.Но проблема здесь в том, что представление прокрутки корректируется до своего конечного положения только после того, как оно перестает замедляться, и есть видимая задержка, и эта анимация тоже не выглядит хорошо.Есть ли способ, которым я могу определить, когда представление прокрутки собирается остановить прокрутку, а затем отрегулировать его положение, вместо того, чтобы ждать завершения прокрутки.Из того, что я читал на некоторых форумах, это будет невозможно.

3) Пейджинговая прокрутка не будет работать в этом сценарии, поскольку я не хочу, чтобы прокручивалась вся ширина изображений.

у кого-нибудь есть какие-либо идеи о том, как я могу реализовать вышеуказанную функциональность.

Ответы [ 2 ]

2 голосов
/ 19 февраля 2013

Я столкнулся с той же проблемой с 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
1 голос
/ 13 декабря 2010

На самом деле вы все еще можете использовать вид прокрутки для этого. Все, что вам нужно сделать, это установить clipsToBounds в NO (чтобы содержимое в представлении прокрутки могло отображаться вне его рамки), а затем установить frame в соответствии с желаемыми шагами выравнивания.

Например, если вы хотите выровнять представление прокрутки по кратным 200, вы можете сделать это:

scrollView.pagingEnabled = YES;
scrollView.clipsToBounds = NO;

// horizontally center scroll view with a width of 200 and the parent's height
scrollView.frame = CGRectMake(
    floor((parentView.bounds.size.width - 200) / 2),
    0,
    200,
    parentView.bounds.size.height
);

[parentView addSubview:scrollView];
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...