堆叠的 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 蒙版层不拉伸,也许只是坐在顶部? (例如,“撕纸”式边缘?)

在移动设备上垂直堆叠的引导列

css 移动堆叠属性修复

iOS Auto Layout - 如何让两个堆叠的纵向视图在横向中并排移动?

css 在GeneratePress上移动和平板电脑之间的堆叠标头

移动设备上的 Woocommerce 产品页面 - “您可能也喜欢”错误地堆叠在一列中