سؤال

أحاول خلق نقطة انطلاق مثل واجهة داخل التطبيق.أحاول استخدام 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];
هل كانت مفيدة؟

المحلول

في أجل UIScrollView لتحديد الفرق بين النقرة الذي يمر من خلال وجهة نظرها المحتوى (ق) ولمسة أن يتحول إلى انتقاد أو قرصة، فإنه يحتاج إلى تأخير اتصال ومعرفة ما إذا كان قد تحرك اصبعك خلال تلك تأخير. عن طريق وضع delaysContentTouches إلى NO في المثال أعلاه الخاص بك، وأنت منع هذا من الحدوث. ولذلك، فإن عرض التمرير يمر دائما لمسة زر، بدلا من إلغائها عندما اتضح أن المستخدم هو المنفذ لفتة انتقاد. حاول إعداد delaysContentTouches إلى YES.

وكما قد يكون فكرة جيدة، من الناحية الهيكلية، إضافة إلى جميع وجهات النظر التي ستستضيفها في عرض التمرير الخاص بك إلى طريقة عرض المحتوى المشترك واستخدام فقط أن رأي واحد كما subview وجهة نظر التمرير ل.

نصائح أخرى

الحل التي عملت بالنسبة لي وشملت:

  1. الإعداد canCancelContentTouches في UIScrollView إلى YES.
  2. تمديد UIScrollView لتجاوز touchesShouldCancelInContentView:(UIView *)view العودة YES عندما view هو UIButton.

وحسب الوثائق touchesShouldCancelInContentView يعود "YES إلى إلغاء المزيد من لمسة رسائل إلى نظر ، NO أن يكون عرض تستمر في تلقي هذه الرسائل.الافتراضي عاد القيمة YES إذا نظر ليس UIControl الكائن ؛ وإلا فإنه يعود NO."

منذ UIButton هو UIControl التمديد ضروري للحصول على canCancelContentTouches المفعول والتي تمكن التمرير.

ولدي قضية مماثلة أن عددا من الأزرار على UIScrollView، وأريد أن انتقل هذه الأزرار. في البداية، I subclassed كلا UIScrollView وUIButton. ومع ذلك، لاحظت أن بلدي subclassed 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

وUIScrollView يعالج الكثير من الأحداث نفسها. تحتاج إلى التعامل مع touchesDidEnd وضرب اختبار لأزرار داخل UIScrollView يدويا.

حسنا هنا هو الجواب:

فرعية UIButton.(ملاحظة:دعوة [سوبر ....] في بداية كل تجاوز.

  • إضافة خاصية.واحدة من نوع BOOL (يسمى enableToRestore)
  • إضافة خاصية.واحدة من نوع CGPoint (يسمى startTouchPosition)
  • في awakeFromNib ، initWithFrame تعيين enableToRestore إلى isEnabled الملكية)
  • تجاوز "touchesBegan:withEvent:" تخزين تبدأ من لمسة الموقف.
  • تجاوز "touchesMoved:withEvent:" أن تحقق لمعرفة ما إذا كان هناك أفقي الحركة.
  • إذا كان الجواب نعم, مجموعة تمكين لا ، اختيار أي.

نموذج التعليمات البرمجية:

- (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.(ملاحظة:دعوة [سوبر ....] في بداية كل تجاوز.

  • تجاوز كل من "touchesEnded:withEvent:" و "touchesCancelled:withEvent:"
  • في تجاوز إعادة تعيين جميع subviews (و subviews) تمكين العلم.
  • ملاحظة:استخدام فئة وإضافة طريقة 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:لا (في نظر المراقب أو مكان) وهي للحصول على أفضل النتائج على الإجابة 4.وهذا يوفر استجابة سريعة جدا على الأزرار.إعداد setDelaysContentTouches:نعم يضع له تأثير خطير (150ms) على وقت استجابة أزرار ويجعل خفيفة وسريعة لمس غير ممكن.

وهناك طريقة أخرى هي:
1. بديل دي زر من قبل مخصص بسيط UIView الصفحة 2. وضع علم "userInterationEnable = نعم؛" على طريقة الحرف الأول
3. ويرى تجاوز أسلوب UIResponder "touchesEnded" هنا يمكنك تحريك العمل التي تحتاج إليها مثل زر واحدة.

في تجربتي الجواب الأول ، أي ببساطة وضع delaysContentTouches إلى YES, لا تغيير أي شيء فيما يتعلق المشكلة.الأزرار سوف لا يزال يتم تسليم تتبع نتائج عرض التمرير.الجواب الثالث هو بسيط جدا للاستخدام.شكرا sieroaoj!

ومع ذلك ، بالنسبة الجواب الثالث للعمل تحتاج أيضا delaysContentTouches تعيين YES.وإلا فإن الطريقة touchesEnded كما سيتم دعا تتبع في الرأي.ولذلك لم أتمكن من حل المشكلة عن طريق:

  1. بديل دي زر بسيطة مخصصة UIView
  2. وضع العلم "userInterationEnable = نعم ؛" على طريقة الحرف الأول
  3. في رأي تجاوز UIResponder طريقة "touchesEnded" هنا يمكنك تحريك العمل لك

الرابع.مجموعة delaysContentTouches إلى YES

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top