Подтвердить что ты не робот

UIScrollview с UIButtons - как воссоздать трамплин?

Я пытаюсь создать в моем приложении подобный трамплину интерфейс. Я пытаюсь использовать UIButtons, добавленные в UIScrollView. Проблема, с которой я столкнулся, - это кнопки, не передающие какие-либо штрихи в UIScrollView - если я попытаюсь щелкнуть/сдвинуть и нажимать на кнопку, которую он не регистрирует для UIScrollView, но если я прокручу пробел между кнопок он будет работать. Кнопки нажимают/работают, если я прикасаюсь к ним.

Есть ли свойство или параметр, который заставляет кнопку отправлять события касания до своего родителя (супервизор)? Нужно ли добавлять кнопки к чему-то еще до добавления UIScrollView?

Вот мой код:

//init scrolling area
UIScrollView *scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, 480, 480)];
scrollView.contentSize = CGSizeMake(480, 1000);
scrollView.bounces = NO;
scrollView.delaysContentTouches = NO;

//create background image
UIImageView *rowsBackground = [[UIImageView alloc] initWithImage:[self scaleAndRotateImage:[UIImage imageNamed:@"mylongbackground.png"]]];
rowsBackground.userInteractionEnabled = YES;

//create button
UIButton *btn = [[UIButton buttonWithType:UIButtonTypeCustom] retain];
btn.frame = CGRectMake(100, 850, 150, 150);
btn.bounds = CGRectMake(0, 0, 150.0, 150.0);
[btn setImage:[self scaleAndRotateImage:[UIImage imageNamed:@"basicbutton.png"]] forState:UIControlStateNormal];
[btn addTarget:self action:@selector(buttonClick) forControlEvents:UIControlEventTouchUpInside];

//add "stuff" to scrolling area
[scrollView addSubview:rowsBackground];
[scrollView addSubview:btn];

//add scrolling area to cocos2d
//this is just a UIWindow
[[[Director sharedDirector] openGLView] addSubview:scrollView];

//mem-mgmt
[rowsBackground release];
[btn release];
[scrollView release];
4b9b3361

Ответ 1

Чтобы UIScrollView определить разницу между кликом, который проходит до его содержимого (ов) и прикосновением, которое превращается в салфетки или пинч, необходимо задержать прикосновение и посмотреть, перемещен ли ваш палец во время этой задержки. Установив delaysContentTouches в NO в приведенном выше примере, вы предотвращаете это. Таким образом, просмотр прокрутки всегда передает касание к кнопке, вместо того, чтобы отменить ее, когда выясняется, что пользователь выполняет жестовый салфет. Попробуйте установить delaysContentTouches на YES.

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

Ответ 2

Решение, которое работало для меня, включало:

  • Настройка canCancelContentTouches в UIScrollView на YES.
  • Расширение UIScrollView для переопределения touchesShouldCancelInContentView:(UIView *)view для возврата YES, когда view является UIButton.

В соответствии с документацией touchesShouldCancelInContentView возвращает "YES, чтобы отменить дальнейшие сенсорные сообщения для просмотра, NO, чтобы иметь возможность продолжить просмотр этих сообщений. Возвращаемое по умолчанию значение YES, если представление не является UIControl объект, в противном случае он возвращает NO."

Так как UIButton является UIControl, расширение необходимо, чтобы получить эффект canCancelContentTouches, который позволяет прокручивать.

Ответ 3

У меня есть аналогичный случай, когда несколько кнопок на UIScrollView, и я хочу прокрутить эти кнопки. Сначала я подклассифицировал UIScrollView и UIButton. Тем не менее, я заметил, что мой подклассифицированный UIScrollView не получил событие touchesEnded, поэтому я перешел на подклассу UIButton.


@interface MyPhotoButton : UIButton {
}

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event;
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event;
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event;
@end

@implementation MyPhotoButton

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
    [super touchesMoved:touches withEvent:event];
    [self setEnabled:NO];
    [self setSelected:NO];
}

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
    [super touchesEnded:touches withEvent:event];
    [self setEnabled:YES];
}

- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event {
    [super touchesCancelled:touches withEvent:event];
    [self setEnabled:YES];
}

@end

Ответ 4

UIScrollView обрабатывает множество событий. Вам нужно обработать touchhesDidEnd и нажать тест для кнопок внутри UIScrollView вручную.

Ответ 5

ОК, вот ваш ответ:

Подкласс UIButton. (ПРИМЕЧАНИЕ: вызовите [super....] в начале каждого переопределения.

  • Добавьте свойство. Один из типов BOOL (называемый enableToRestore)
  • Добавьте свойство. Один из типов CGPoint (называется startTouchPosition)
  • в awakeFromNib и initWithFrame, установите enableToRestore к isEnabled недвижимость)
  • Переопределить "touchhesBegan: withEvent:" сохранить начало прикосновения положение.
  • Переопределить "touchesMoved: withEvent:" to проверьте, есть ли горизонтальный движение.
  • Если ДА, установите значение НЕТ и выбрано значение НЕТ.

Пример кода:

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event 
{
    UITouch *touch = [touches anyObject];

    [super touchesBegan:touches withEvent:event];
    [self setStartTouchPosition:[touch locationInView:self]];
}


//
// Helper Function
//
- (BOOL)isTouchMovingHorizontally:(UITouch *)touch 
{
    CGPoint currentTouchPosition = [touch locationInView:self];
    BOOL      rValue = NO;

    if (fabsf([self startTouchPosition].x - currentTouchPosition.x) >= 2.0) 
    {
        rValue = YES;
    }

    return (rValue);
}

//
// This is called when the finger is moved.  If the result is a left or right
// movement, the button will disable resulting in the UIScrollView being the
// next responder.  The parrent ScrollView will then re-enable the button
// when the finger event is ended of cancelled.
//
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event 
{
    [super touchesMoved:touches withEvent:event];
    if ([self isTouchMovingHorizontally:[touches anyObject]]) 
    {
        [self setEnabled:NO];
        [self setSelected:NO];
    } 
}

Это активирует UIScrollView.

Подкласс UIScrollView. (ПРИМЕЧАНИЕ: вызовите [super....] в начале каждого переопределения.

  • Переопределите оба параметра "touchesEnded: withEvent:" и "touchesCancelled: withEvent:"
  • В переопределении reset включен флаг всех подзонов (и их дочерних объектов).
  • ПРИМЕЧАНИЕ. Используйте категорию и добавьте метод в UIView:

.

- (void) restoreAllEnables
{
    NSArray   *views = [self subviews];

    for (UIView *aView in views)
    {
        if ([aView respondsToSelector:@selector(restoreEnable)])
        {
            [aView restoreEnable];
        }
    }
}

- (void) touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
    [super touchesEnded:touches withEvent:event];
    [self restoreAllEnables];
}

- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
{
    [super touchesEnded:touches withEvent:event];
    [self restoreAllEnables];
}
  • В категории:

.

-(void) restoreEnable
{
    NSArray   *views = [self subviews];

    if ([self respondsToSelector:@selector(enableToRestore)])
    {
        [self setEnabled:[self enableToRestore]];
    }

    for (UIView *aView in views)
    {
        if ([aView respondsToSelector:@selector(restoreEnable)])
        {
            [aView restoreEnable];
        }
    }
}

ИЗМЕНИТЬ Примечание. У меня никогда не было ответа 3 на работу. Аналогично: setDelaysContentTouches: NO (установленный в контроллере представления или где-нибудь) должен быть установлен для получения наилучших результатов в ответе 4. Это обеспечивает очень быструю реакцию на кнопки. Настройка setDelaysContentTouches: YES оказывает серьезное воздействие (150 мс) на время отклика на кнопки и делает свет, быстро касаясь, невозможно.

Ответ 6

Другой способ:
1. Замените кнопку простым пользовательским UIView
2. Поместите флаг "userInterationEnable = yes;" по методу init
3. В представлении переопределите метод UIResponder" touchesEnded" здесь, вы можете вызвать действие, которое вам нужно, как кнопку.

Ответ 7

В моем опыте первый ответ, т.е. просто установка delaysContentTouches в YES, ничего не меняет в отношении проблемы. Кнопки все равно не передадут результаты отслеживания в режим прокрутки. Третий ответ прост и очень полезен. Спасибо sieroaoj!

Однако для третьего ответа на работу вам также нужно delaysContentTouches установить YES. В противном случае метод touchesEnded также будет вызываться для отслеживания в представлении. Поэтому я мог бы решить проблему:

  • Замените кнопку простым пользовательским UIView
  • Поместите флаг "userInterationEnable = yes;" по методу init
  • В представлении переопределите метод UIResponder "touchesEnded" здесь вы можете вызвать действие, которое вы

В-четвертых. установите delaysContentTouches в YES