Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/objective-c/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/vim/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Objective c 带UIButtons的UIScrollview-如何重新创建跳板?_Objective C_Uiscrollview_Uibutton_Programmatically Created - Fatal编程技术网

Objective c 带UIButtons的UIScrollview-如何重新创建跳板?

Objective c 带UIButtons的UIScrollview-如何重新创建跳板?,objective-c,uiscrollview,uibutton,programmatically-created,Objective C,Uiscrollview,Uibutton,Programmatically Created,我正在尝试在我的应用程序中创建一个类似跳板的界面。我正在尝试使用添加到UIScrollView的UIButtons。我遇到的问题是按钮没有向UIScrollView传递任何触摸信息-如果我尝试轻弹/滑动并碰巧按下按钮,它不会注册为UIScrollView,但是如果我轻弹按钮之间的空间,它会工作。如果我触摸按钮,它们会发出咔嗒声 是否有强制按钮将触摸事件发送到其父级(superview)的属性或设置?在添加到UIScrollView之前,是否需要将按钮添加到其他内容 这是我的密码: //init

我正在尝试在我的应用程序中创建一个类似跳板的界面。我正在尝试使用添加到UIScrollView的UIButtons。我遇到的问题是按钮没有向UIScrollView传递任何触摸信息-如果我尝试轻弹/滑动并碰巧按下按钮,它不会注册为UIScrollView,但是如果我轻弹按钮之间的空间,它会工作。如果我触摸按钮,它们会发出咔嗒声

是否有强制按钮将触摸事件发送到其父级(superview)的属性或设置?在添加到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本身处理很多事件。您需要手动处理UIScrollView内按钮的触控DIDEND和hit测试。

为了让
UIScrollView
确定通过其内容视图的点击与变成滑动或挤压的触控之间的差异,它需要延迟触摸,并查看您的手指是否在延迟期间移动。在上面的示例中,通过将
delaysContentTouches
设置为
NO
,可以防止这种情况发生。因此,滚动视图总是将触摸传递给按钮,而不是在用户执行滑动手势时取消触摸。尝试将
delaysContentTouches
设置为
YES


从结构上讲,最好将滚动视图中要承载的所有视图添加到公共内容视图中,并仅将该视图用作滚动视图的子视图。

另一种方法是:
1。用简单的自定义UIView替换de按钮
2。在init方法上设置标志“userinteractionenable=yes;”
3。在视图中,覆盖UIResponder方法“touchesend”,您可以像按钮一样触发所需的操作。

根据我的经验,第一个答案,即简单地将
延迟内容切换设置为
,不会改变与问题相关的任何内容。这些按钮仍不会将跟踪结果传送到滚动视图。第三个答案既简单又实用。谢谢sieroaoj

但是,要使第三个答案起作用,您还需要将
delaysContentTouches
设置为
YES
。否则,也将调用方法
touchesend
在视图中进行跟踪。因此,我可以通过以下方式解决问题:

  • 用简单的自定义UIView替换de按钮
  • 在init方法上放置标志“userinteractionenable=yes;”
  • 在视图中,在此处覆盖UIResponder方法“touchesEnded” 你可以触发你想要的动作

  • 四,。将
    delaysContentTouches
    设置为
    YES
    确定以下是您的答案:

    子类UIButton。(注意:在每次覆盖开始时调用[super…]

    • 添加属性。类型为BOOL的属性之一 (称为enableToRestore)
    • 添加属性。CGPoint类型之一 (称为startTouchPosition)
    • 从笔尖和 initWithFrame,设置 启用存储到已启用的 财产)
    • 覆盖“触摸开始: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。(注意:在每次覆盖开始时调用[super…]

    • 覆盖“touchesEnded:withEvent:”和“touchesCancelled:withEvent:”
    • 在替代中,重置所有子视图(及其子视图)启用标志
    • 注意:使用类别并将方法添加到UIView:

    • 在类别中:

    编辑 注:我从未得到过答案3。
    同样,设置setDelaysContentTouches:NO(在视图控制器或某处设置)可在回答4时获得最佳结果。这可提供对按钮的快速响应。设置setDelaysContentTouches:YES会产生严重影响(150毫秒)在按钮的响应时间上,使轻巧、快速的触摸变得不可能。

    我有一个类似的情况,在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
    

    对我有效的解决方案包括:

  • UIScrollView
    中的
    canCancelContentTouches
    设置为
    YES
  • 扩展
    UIScrollView
    以覆盖
    touchesShouldCancelInContentView:(UIView*)视图
    以在
    view
    UIButton
    时返回
    YES
  • 根据文档
    touchesshouldcanceincontview
    返回“
    YES
    取消要查看的进一步触摸消息,
    NO
    让视图继续接收这些消息。如果视图不是
    UIControl
    对象,默认返回值为
    YES
    ,否则返回
    NO


    由于
    ui按钮
    是一个
    UIControl
    扩展是必要的,以使
    CanCancancelContentTouches
    生效,从而启用滚动。

    执行延迟ContentTouches的一个可能问题是,它会在按钮高亮显示之前添加延迟。下面的Roman K回答将允许您没有延迟,但在按下按钮后仍能滚动。结构建议很棒,但我想知道原因。谢谢。非常感谢!澄清一下,这在delaysContentTouches=NO时最有效。这就是方法!(至少对于iOS 4+)我发现这样的覆盖最通用:
    -(BOOL)touchesShouldCancelInContentView:(UIView*)视图{return![view isKindOfClass:[UISlider class]];}
    它仍然不适用于
    -(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];
            }
        }
    }
    
    
    @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