UIScrollview 与 UIButtons - 如何重新创建跳板?
我正在尝试在我的应用程序中创建一个类似跳板的界面。 我正在尝试使用添加到 UIScrollView 的 UIButtons。 我遇到的问题是按钮没有将任何触摸传递给 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];
I'm trying to create a springboard-like interface within my app. I'm trying to use UIButtons added to a UIScrollView. The problem I'm running in to is with the buttons not passing any touches to the UIScrollView - if I try to flick/slide and happen to press on the button it doesn't register for the UIScrollView, but if I flick the space between buttons it will work. The buttons do click/work if I touch them.
Is there a property or setting that forces the button to send the touch events up to its parent (superview)? Do the buttons need to be added to something else before being added the UIScrollView?
Here is my code:
//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];
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
对我有用的解决方案包括:
UIScrollView
中的canCancelContentTouches
设置为YES
。UIScrollView
以覆盖touchesShouldCancelInContentView:(UIView *)view
以在view
是UIButton 时返回
。YES
根据文档
touchesShouldCancelInContentView
返回“YES
取消进一步查看的触摸消息,NO
让视图继续接收这些消息。默认返回值如果视图不是UIControl
对象,则为YES
;否则,返回NO
。”由于
UIButton
是一个UIControl
,因此需要扩展才能使canCancelContentTouches
生效以启用滚动。Solution that worked for me included:
canCancelContentTouches
inUIScrollView
toYES
.UIScrollView
to overridetouchesShouldCancelInContentView:(UIView *)view
to returnYES
whenview
is aUIButton
.According to documentation
touchesShouldCancelInContentView
returns "YES
to cancel further touch messages to view,NO
to have view continue to receive those messages. The default returned value isYES
if view is not aUIControl
object; otherwise, it returnsNO
."Since
UIButton
is aUIControl
the extension is necessary to getcanCancelContentTouches
to take effect which enables scrolling.为了让 UIScrollView 确定传递到其内容视图的点击与变成滑动或捏合的触摸之间的差异,它需要延迟触摸并查看您的手指是否在此延迟期间已移动。 通过在上面的示例中将
delaysContentTouches
设置为NO
,您可以防止这种情况发生。 因此,滚动视图始终将触摸传递给按钮,而不是在用户执行滑动手势时取消触摸。 尝试将delaysContentTouches
设置为YES
。从结构上讲,将滚动视图中托管的所有视图添加到公共内容视图中并且仅使用该视图作为滚动视图的子视图也可能是一个好主意。
In order for
UIScrollView
to determine the difference between a click that passes through to its content view(s) and a touch that turns into a swipe or pinch, it needs to delay the touch and see if your finger has moved during that delay. By settingdelaysContentTouches
toNO
in your above example, you're preventing this from happening. Therefore, the scroll view is always passing the touch to the button, instead of canceling it when it turns out that the user is performing a swipe gesture. Try settingdelaysContentTouches
toYES
.It might also be a good idea, structurally, to add all the views to be hosted in your scroll view to a common content view and only use that one view as the scroll view's subview.
我有一个类似的情况,UIScrollView 上有许多按钮,我想滚动这些按钮。 一开始,我将 UIScrollView 和 UIButton 都子类化。 但是,我注意到我的子类 UIScrollView 没有收到 TouchEnded 事件,因此我更改为仅子类 UIButton。
I have a similar case that a number of buttons on a UIScrollView, and I want to scroll these buttons. At the beginning, I subclassed both UIScrollView and UIButton. However, I noticed that my subclassed UIScrollView did not receive touchesEnded event, so I changed to only subclass UIButton.
UIScrollView 本身处理很多事件。 您需要手动处理 UIScrollView 内按钮的 TouchDidEnd 和点击测试。
UIScrollView handles a lot of events itself. You need to handle touchesDidEnd and hit test for buttons inside the UIScrollView manually.
好的,这就是您的答案:
子类 UIButton。 (注意:在每次覆盖开始时调用 [super ....]。
(称为enableToRestore)
(称为 startTouchPosition)
initWithFrame,设置
将enableToRestore设置为isEnabled
属性)
存储触摸的开始
位置。
检查是否有水平
移动。
选择NO。
示例代码:
这将激活 UIScrollView。
UIScrollView 的子类。 (注意:在每次覆盖开始时调用 [super ....]。
在
。
:
注意:我从来没有让答案 3 起作用。
同样:setDelaysContentTouches:NO(在视图控制器或其他地方设置)将被设置为在答案 4 上获得最佳结果。这提供了对按钮的非常快速的响应。 设置 setDelaysContentTouches:YES 会对按钮的响应时间产生严重影响(150 毫秒),并且无法实现轻快的触摸。
OK here is your answer:
Subclass UIButton. (NOTE: call [super ....] at the start of each override.
(called enableToRestore)
(called startTouchPosition)
initWithFrame, set the
enableToRestore to the isEnabled
property)
to store the start of the touch
position.
check to see if there is horizontal
movement.
selected to NO.
Sample code:
This will activate the UIScrollView.
Subclass UIScrollView. (NOTE: call [super ....] at the start of each override.
.
.
EDIT
Note: I never got Answer 3 to work.
Likewise: the setDelaysContentTouches:NO (set in the view controller or someplace) is to be set for best results on Answer 4. This provides very fast response to the buttons. Setting setDelaysContentTouches:YES puts a serious impact (150ms) on response time to the buttons and makes light,fast touching not possible.
另一种方法是:
1。 用简单的自定义 UIView 替换按钮
2。 放置标志“userInterationEnable = yes;” 在 init 方法上
3. 在视图中重写 UIResponder 方法“touchesEnded”,您可以像按钮一样触发您需要的操作。
Another way is:
1. Substitute de button by a simple custom UIView
2. Put the flag "userInterationEnable = yes;" on the init method
3. In the view override the UIResponder method "touchesEnded" here you can trigger the action you need like a button.
根据我的经验,第一个答案,即简单地将
delaysContentTouches
设置为YES
,不会改变问题的任何内容。 这些按钮仍然不会将跟踪结果传递到滚动视图。 第三个答案既简单又非常有用。 谢谢谢罗奥!但是,要使第三个答案起作用,您还需要将
delaysContentTouches
设置为YES
。 否则,也会调用方法touchesEnded
来在视图内进行跟踪。 因此我可以通过以下方式解决问题:第四。 将
delaysContentTouches
设置为YES
In my experience the first answer, i.e., simply setting
delaysContentTouches
toYES
, does not change anything with regard to the problem. The buttons will still not deliver tracking results to the scroll view. The third answer is both simple and very usable. Thanks sieroaoj!However, for the third answer to work you also need
delaysContentTouches
set toYES
. Otherwise the methodtouchesEnded
will also be called for tracking within the view. Therefore I could solve the problem by:Fourth. set
delaysContentTouches
toYES