문제

내 앱 내에서 스프링보드와 유사한 인터페이스를 만들려고 합니다.UIScrollView에 추가된 UIButton을 사용하려고 합니다.내가 겪고 있는 문제는 버튼이 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];
도움이 되었습니까?

해결책

위해서는 UIScrollView 컨텐츠보기로 전달되는 클릭의 차이와 스 와이프 또는 꼬집음으로 변하는 터치의 차이를 확인하려면 터치를 지연시키고 지연 중에 손가락이 움직이는 지 확인해야합니다. 설정하여 delaysContentTouches 에게 NO 위의 예에서는 이것이 일어나지 못하게합니다. 따라서 스크롤보기는 사용자가 스 와이프 제스처를 수행하고 있음이 밝혀 질 때 취소하는 대신 버튼에 항상 터치를 전달합니다. 설정해보십시오 delaysContentTouches 에게 YES.

스크롤 뷰에서 호스팅 할 모든 뷰를 공통 컨텐츠보기에 추가하고 해당 뷰를 스크롤보기의 하위 뷰로 만 사용하는 것이 구조적으로 좋은 아이디어 일 수 있습니다.

다른 팁

저를 위해 일한 솔루션은 다음과 같습니다.

  1. 환경 canCancelContentTouches 안에 UIScrollView 에게 YES.
  2. 확장 UIScrollView 무시합니다 touchesShouldCancelInContentView:(UIView *)view 돌려 주다 YES 언제 view a UIButton.

문서에 따르면 touchesShouldCancelInContentView 반환 "YES 보기에 대한 추가 터치 메시지를 취소하려면 NO 견해를 유지하려면 그 메시지를 계속받습니다. 기본 반환 값은입니다 YES 보기가 아닌 경우 UIControl 물체; 그렇지 않으면 반환됩니다 NO."

부터 UIButton a UIControl 확장이 필요합니다 canCancelContentTouches 스크롤링을 가능하게하는 적용.

UiscrollView의 여러 버튼과 비슷한 경우가 있으며이 버튼을 스크롤하고 싶습니다. 처음에는 Uiscrollview와 Uibutton을 모두 서브 클래스했습니다. 그러나 서브 클래스 Uiscrollview가 터치 엔드 이벤트를받지 못했기 때문에 Uibitton 하위 클래스로만 변경했습니다.


@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

uiscrollview는 많은 이벤트 자체를 처리합니다. UiscrollView 내부의 버튼에 대한 TouchesDidend를 처리하고 적중 테스트를 처리해야합니다.

좋아, 여기에 당신의 대답이 있습니다 :

서브 클래스 Uibutton. (참고 : 각각의 시작시 [Super ....]에게 전화하십시오.

  • 속성을 추가하십시오. 유형 BOOL 중 하나 (ENABLETORESTORE라고 함)
  • 속성을 추가하십시오. CGPoint 유형 중 하나 (startTouchPosition이라고 함)
  • awakefromnib 및 initwithframe에서 enabletorestore를 isenabled 속성으로 설정하십시오)
  • "Touchesbegan : Withevent :"터치 위치의 시작을 저장합니다.
  • "TouchesMoved : WithEvent :"수평 이동이 있는지 확인하려면 재정의하십시오.
  • 그렇다면 활성화를 no로 설정하고 no로 선택하십시오.

샘플 코드 :

- (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 ....]에게 전화하십시오.

  • "터치 엔드 : 위임 :"및 "ToucheScancelled : Withevent :"
  • 재정의에서 모든 서브 뷰 (및 하위 뷰) 활성화 플래그를 재설정하십시오.
  • 참고 : 카테고리를 사용하고 메소드를 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];
        }
    }
}

참고 편집 : 나는 일할 대답을 얻지 못했습니다. 마찬가지로 : SetDelaysContentTouches : NO (보기 컨트롤러 또는 어딘가에 설정)는 답변 4에서 최상의 결과를 위해 설정되어야합니다. 이는 버튼에 대한 매우 빠른 응답을 제공합니다. SetDelaysContentTouches 설정 : 예, 버튼에 대한 응답 시간에 심각한 영향을 미치고 가볍고 빠르게 만지지 않습니다.

또 다른 방법은 다음과 같습니다.
1. 간단한 사용자 정의 UIView로 DE 버튼을 대체하십시오
2. 깃발을 "userinterationable = yes;"에 넣습니다. init 메소드에서
3.보기에서 UIRSPonder 메소드 "Touchesended"를 무시하면 버튼처럼 필요한 작업을 트리거 할 수 있습니다.

내 경험상 첫 번째 대답은 즉, 간단히 설정하는 것입니다. delaysContentTouches 에게 YES, 문제와 관련하여 아무것도 변경되지 않습니다.버튼은 여전히 ​​스크롤 보기에 추적 결과를 전달하지 않습니다.세 번째 답변은 간단하면서도 매우 유용합니다.고마워요 sieroaoj!

그러나 세 번째 답변이 작동하려면 다음이 필요합니다. delaysContentTouches 로 설정 YES.그렇지 않으면 방법 touchesEnded 또한 뷰 내에서 추적을 위해 호출됩니다.따라서 다음과 같이 문제를 해결할 수 있습니다.

  1. de 버튼을 간단한 사용자 정의 UIView로 대체
  2. 깃발을 "userinterationable = 예"를 넣으십시오. init 방법에서
  3. View에서 Uiresponder 메소드 "ToucheSended"를 무시하면 동작을 트리거 할 수 있습니다.

네번째.세트 delaysContentTouches 에게 YES

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top