堆叠的 UIView 层不移动
Posted
技术标签:
【中文标题】堆叠的 UIView 层不移动【英文标题】:Stacked UIView Layers Don't Move 【发布时间】:2009-01-16 21:19:38 【问题描述】:我正在开发一个 iPhone 应用程序,它根据加速度计在其他 UIView 层之间移动 UIView 层。
如果最顶层是根据加速度计移动的那一层,那没问题。如果我在它上面添加一个 UIView ,移动就会非常延迟。如果我在其上添加第二个 UIView,则移动停止。
updateInterval 为 60,我正在使用 UIView 的 drawAtPoint: 方法来移动图层。
我的问题:是否需要启用 UIView 属性(例如 opaque、clipsToBounds 等)才能使夹层 UIView 发生基于加速度计的准确移动?
提前感谢您提供的任何帮助。
更新:
底层是不透明的,上面的层是透明的PNG。
我在访问 UIView 的 frame 属性时遇到了困难。这是我的Object2D
课程中的一些代码:
- (id)initWithImage:(NSString*)imageName
if (self = [super init])
position = [[Point2D alloc] init];
vector = [[Vector2D alloc] init];
imagePath = [[NSBundle mainBundle] pathForResource:imageName ofType:@"png"];
myImageObj = [[UIImage alloc] initWithContentsOfFile:imagePath];
size.width = myImageObj.size.width;
size.height = myImageObj.size.height;
return self;
这是从 ViewController
类调用的类的原始 draw:
方法:
- (void)draw
[myImageObj drawAtPoint:CGPointMake( position.X, position.Y ) ];
[ self setNeedsDisplay ];
我尝试了各种方法来访问框架属性,但无济于事:
myImageObj.frame = CGRectMake(position.X, position.Y, size.width, size.height);
myImageObj.CGImage.frame.y = position.Y;
查看 API 文档表明第一种方法可行,但没有。
你知道如何访问 UIView 的 frame 属性吗?
提前致谢。
【问题讨论】:
【参考方案1】:您不能直接设置单个帧参数。您必须创建一个新的 CGRect 并将框架设置为该 CGRect。创建 CGRect 后,有多种方法可以更改其参数。
CGRect myNewFrame = someView.frame;
myNewFrame.origin.x = 1.0;
myNewFrame.size = CGSizeMake(100.0f, 50.0f);
someView.frame = myNewFrame;
这个想法是按照你想要的方式设置 CGRect,然后将视图的 frame 属性设置为那个 CGRect,然后你就可以了。
就 UIView... 你可能会遇到一些问题。首先,如上所述,drawAtPoint 方法很昂贵。其次,也许更糟的是,你有几个透明图像。透明度是 iPhone 上最昂贵的操作之一,事实上,在 Instruments 中有一个测试就是为了这个。您应该不惜一切代价避免透明度。一些在旋转期间全部重绘的透明 PNG 很可能会给您的应用程序带来麻烦。
我的下一个建议是考虑是否需要在透明胶片中间放置视图,也许另一层可以完成这项工作。如果您需要触摸功能,您可以使用层层次结构根部的视图来处理触摸。换句话说,从后到前你有这个: 界面视图 图层 界面视图 图层 CALayer
但你可以这样: UIView(现在处理所有触摸) 图层 CALayer(以前的视图) 图层 CALayer
这也将有所帮助,因为 CALayer 的开销比 UIViews 少。
希望这会有所帮助。
【讨论】:
【参考方案2】:每次您使用 drawAtPoint: 您都在强制将 UIView 重新渲染到图形层中。这很贵。
UIView 已经有一个定义其位置和大小的 -frame 属性。仅更新位置允许图形硬件移动已经合成的图层。
我不确定您所说的“夹层”是什么意思,但我假设它将图层放置在不同的 z 索引处?如果是这样,我假设中间层(您要移动的层)和顶层必须是透明的,而底层应该是不透明的才能发挥作用。
如果这不是你要找的,请告诉我……
【讨论】:
【参考方案3】:我认为您误解了 UIView 的工作原理。首先,您要创建 UIImageViews 来托管您的 UIImages。然后,您想使用其 addSubview: 方法将它们添加到一个超级视图中。最后,你想改变你的中间 UIImageView 的 frame 属性(如果你想让它平滑动画,在 beginAnimations / commitAnimations 块内),让它移动到你的新位置。
如果您将 UIImage 放置在封装的 UIImageView 中,它会作为纹理缓存在 GPU 上,并且 UIImageView 位置的任何更改都将通过硬件加速。 drawAtPoint:,正如 Dan 指出的那样,非常昂贵,如果可以的话,应该避免使用。您的 myImageObj.frame = CGRectMake 代码走在了正确的轨道上,它只需要应用于 UIImageView,而不是 UIImage。
对于简单的三层结构,除非您有大量图像,否则即使具有大量透明度的图像也能流畅地制作动画。我已经为几十个透明的 UIView(它们只是 CALayers 周围的非常轻的包装器)做了这个,没有性能问题。
顺便说一句,如果您的 Point2D 和 Vector2D 类只是二维坐标的包装器,您可能希望考虑用 CGPoint 结构替换它们。围绕这种轻量级数据类型有很多支持功能。
【讨论】:
以上是关于堆叠的 UIView 层不移动的主要内容,如果未能解决你的问题,请参考以下文章
是否有可能有一个可变高度的 UIView 蒙版层不拉伸,也许只是坐在顶部? (例如,“撕纸”式边缘?)
iOS Auto Layout - 如何让两个堆叠的纵向视图在横向中并排移动?