与 CATiledLayer 一起使用时,UIView 的“contentScaleFactor”背后的秘密是啥?

     2023-04-15     58

关键词:

【中文标题】与 CATiledLayer 一起使用时,UIView 的“contentScaleFactor”背后的秘密是啥?【英文标题】:What is the secret behind "contentScaleFactor" of UIView when used with CATiledLayer?与 CATiledLayer 一起使用时,UIView 的“contentScaleFactor”背后的秘密是什么? 【发布时间】:2011-07-13 11:00:36 【问题描述】:

您好,

我正在开发一个受 iOS SDK 附带的“ZoomingPDFViewer”示例启发的应用程序。在某个时候,我发现了以下代码:

// to handle the interaction between CATiledLayer and high resolution
// screens, we need to manually set the tiling view's 
// contentScaleFactor to 1.0. (If we omitted this, it would be 2.0 
// on high resolution screens, which would cause the CATiledLayer 
// to ask us for tiles of the wrong scales.)
pageContentView.contentScaleFactor = 1.0;

我试图了解更多关于contentScaleFactor 及其作用的信息。在阅读了所有提到它的 Apple 文档后,我搜索了 Google,但从未找到它实际作用的明确答案。

以下是一些我很好奇的事情:

    在绘制 UIView/CALayer 的内容时,contentScaleFactor 似乎对图形上下文有某种影响。这似乎与高分辨率显示器(如 Retina 显示器)有关。 contentScaleFactor 究竟有什么样的影响?

    当使用UIScrollView 并将其设置为缩放时,比如说我的contentViewcontentView 的所有子视图也在缩放。这是如何运作的? UIScrollView 修改了哪些属性以使视频播放器变得模糊和放大?

TL;DR:UIScrollView 的缩放功能是如何“在后台”工作的?我想了解它是如何工作的,以便编写正确的代码。

非常感谢任何提示和解释! :)

【问题讨论】:

【参考方案1】:

坐标以点而不是像素表示。 contentScaleFactor 定义了点和像素的关系:如果是1,点和像素是一样的,如果是2(就像retina display),就意味着每个点都有两个像素。

在普通绘图中,使用点意味着您不必担心分辨率:在 iphone 3(scaleFactor 1)和 iphone4(scaleFactor 2 和 2x 分辨率)中,您可以使用相同的坐标和绘图代码。但是,如果您正在绘制图像(直接,作为纹理......)并且仅使用法线坐标(点),则您不能相信像素到点的映射是 1 比 1。如果这样做,那么每个像素如果 scaleFactor 为 2(x 方向为 2,y 方向为 2),图像将对应 1 个点但 4 个像素,因此图像可能会变得有点模糊

使用CATiledLayer 时,使用比例因子2 可能会产生一些意想不到的结果。我猜想UIViewcontentScaleFactor==2 层和contentScale==2 层会混淆系统,有时还会使比例倍增。 Scrollview 可能会发生类似的情况。

希望这能澄清一点

【讨论】:

很好的答案,这是最新的摘要和点、比例因子和分辨率paintcodeapp.com/news/ultimate-guide-to-iphone-resolutions【参考方案2】:

Apple 在 iOS 开发文档的“支持高分辨率屏幕”页面上有一个关于此的部分。

页面说:

更新您的自定义绘图代码

当您在应用程序中进行任何自定义绘图时,大多数时候 你不需要关心底层证券的分辨率 屏幕。原生绘图技术自动确保 您在逻辑坐标空间图中正确指定的坐标 到底层屏幕上的像素。但是,有时您可能需要 知道当前的比例因子是什么,以便呈现您的 内容正确。对于这些情况,UIKit、Core Animation 和 其他系统框架为您提供绘图所需的帮助 正确。

以编程方式创建高分辨率位图图像 目前使用 UIGraphicsBeginImageContext 函数创建 位图,您可能需要调整代码以将比例因子纳入 帐户。 UIGraphicsBeginImageContext 函数总是创建 比例因子为 1.0 的图像。如果底层设备有一个 高分辨率屏幕,使用此功能创建的图像可能无法 渲染时看起来很平滑。创建具有比例因子的图像 除了 1.0,使用 UIGraphicsBeginImageContextWithOptions 反而。使用此功能的过程与使用相同 UIGraphicsBeginImageContext 函数:

    调用 UIGraphicsBeginImageContextWithOptions 创建位图 上下文(使用适当的比例因子)并将其推送到 图形堆栈。 使用 UIKit 或 Core Graphics 例程绘制 图片。 调用 UIGraphicsGetImageFromCurrentImageContext 来获取位图的 内容。 调用 UIGraphicsEndImageContext 从堆栈中弹出上下文。

例如下面的代码sn -p 创建一个 200 x 200 像素的位图。 (像素数为 通过将图像的大小乘以比例来确定 因素。)

UIGraphicsBeginImageContextWithOptions(CGSizeMake(100.0,100.0), NO, 2.0);

在这里查看:Supporting High-Resolution Screens

【讨论】:

请注意,将 0.0 作为比例传递会导致 UIGraphicsBeginImageContextWithOptions: 使用设备主屏幕的 contentScaleFactor。在我看来,这是充分利用您所使用的任何分辨率设备的最简单选择。这将自动将 1.0 用于“普通”设备,将 2.0 用于 Retina 设备。很好,很容易!

如何使用 UIScrollView 和 CATiledLayer 在可缩放的 UIView 上绘制标记

】如何使用UIScrollView和CATiledLayer在可缩放的UIView上绘制标记【英文标题】:HowtodrawmarkersonazoomableUIViewusingUIScrollViewandCATiledLayer【发布时间】:2012-06-0101:06:01【问题描述】:我想在使用UIScrollView和CATiledLayer的可缩放UIView上绘制标记... 查看详情

CATiledLayer 在 iPad 第 3 代放大时被移除和刷新

】CATiledLayer在iPad第3代放大时被移除和刷新【英文标题】:CATiledLayerbeingremovedandrefreshedwhilezoomediniPad3rdgen【发布时间】:2012-05-1301:04:10【问题描述】:当父UIScrollView放大时,我在CATiledLayer上遇到重绘问题。我在CATiledLayer支持的UIVie... 查看详情

CATiledLayer drawLayer:inContext:在检索要绘制的图像时释放视图时崩溃

】CATiledLayerdrawLayer:inContext:在检索要绘制的图像时释放视图时崩溃【英文标题】:CATiledLayerdrawLayer:inContext:crashingwhentheviewisdeallocatedwhiletheimagetodrawisbeingretrieved【发布时间】:2011-04-0900:47:44【问题描述】:当我的CATiledLayer正在检... 查看详情

CATiledLayer 显示以前的图块

】CATiledLayer显示以前的图块【英文标题】:CATiledLayershowsprevioustiles【发布时间】:2017-02-1422:21:35【问题描述】:当使由CATiledLayer支持的视图无效时,前一个图块仍然“卡住”并且未正确无效。这似乎发生在视图无效时(在主线程... 查看详情

使用 CoreGraphics CGContextDrawImage 在 CATiledLayer 中绘图

】使用CoreGraphicsCGContextDrawImage在CATiledLayer中绘图【英文标题】:DrawinginCATiledLayerwithCoreGraphicsCGContextDrawImage【发布时间】:2011-05-0307:45:19【问题描述】:我想在iPhoneOS3.1.3中使用CATiledLayer,为此,-(void)drawLayer:(CALayer*)layerinContext: 查看详情

UIPopoverController 与 PresentFromBarButtonItem 一起使用时设置高度

】UIPopoverController与PresentFromBarButtonItem一起使用时设置高度【英文标题】:UIPopoverControllerSettingheightwhenusedwithPresentFromBarButtonItem【发布时间】:2010-12-1607:51:58【问题描述】:我有一个显示UItableview的UIPopoverController。我使用PresentFromB... 查看详情

当 v-for 与对象的属性一起使用时,将 v-model 与复选框一起使用

】当v-for与对象的属性一起使用时,将v-model与复选框一起使用【英文标题】:Usev-modelwithacheckboxwhenv-forisusedwithpropertiesofanobject【发布时间】:2019-03-1211:46:36【问题描述】:将v-model与复选框一起使用当v-for与对象数组一起使用时:n... 查看详情

将码头与 Repast simphony 一起使用时出错

】将码头与Repastsimphony一起使用时出错【英文标题】:ErrorwhenusingjettywithRepastsimphony【发布时间】:2015-10-0905:00:31【问题描述】:我想将javawebsocket与Repastsimphony一起使用,但它不起作用,我收到以下错误:java.lang.NoSuchMethodError:javax... 查看详情

与核心数据一起使用时预览崩溃

】与核心数据一起使用时预览崩溃【英文标题】:Previewscrashingwhenusingwithcore-data【发布时间】:2020-08-2912:23:53【问题描述】:我正在尝试使用swiftui和core-data创建一个简单的待办事项应用程序,但是在添加视图时遇到了一些问题。... 查看详情

与 cartopy 一起使用时,上下颠倒映射

】与cartopy一起使用时,上下颠倒映射【英文标题】:Contextilymapupsidedownwhenusedwithcartopy【发布时间】:2020-08-2711:01:26【问题描述】:将contextily底图添加到以cartopy投影的轴时,地图会上下颠倒。这是一个最小的例子:importmatplotlib.p... 查看详情

将 ArrayFire 与 OpenCL 一起使用时出错

】将ArrayFire与OpenCL一起使用时出错【英文标题】:ErrorwhenusingArrayFirewithOpenCL【发布时间】:2016-06-0707:48:01【问题描述】:我成功安装了ArrayFire,当我选择VisualStudio配置CUDA_x64时,示例helloworld工作正常。但是当我更改为OpenCL_x64时... 查看详情

JdbcTemplate queryForObject() 与参数一起使用时出错 [重复]

】JdbcTemplatequeryForObject()与参数一起使用时出错[重复]【英文标题】:JdbcTemplatequeryForObject()witherrorwhenusingwithparameters[duplicate]【发布时间】:2021-08-1916:34:48【问题描述】:我收到错误org.springframework.dao.EmptyResultDataAccessException带有deta... 查看详情

尝试将 tensorboard 与 google colab 一起使用时出错

】尝试将tensorboard与googlecolab一起使用时出错【英文标题】:Errorontryingtousetensorboardwithgooglecolab【发布时间】:2019-08-2417:52:15【问题描述】:我在尝试将tensorboard与googlecollab一起使用时遇到错误。我正在使用ngork运行张量板。错误... 查看详情

与后台线程一起使用时异步队列挂起

】与后台线程一起使用时异步队列挂起【英文标题】:asyncqueuehangswhenusedwithbackgroundthread【发布时间】:2017-11-0614:20:03【问题描述】:好像asyncio.Queue只能被同一个线程推送读取吧?例如:importasynciofromthreadingimportThreadimporttimeq=async... 查看详情

尝试将指针与结构一起使用时出错

】尝试将指针与结构一起使用时出错【英文标题】:Gettingerrorwhentryingtousepointerwithstruct【发布时间】:2018-10-1816:26:48【问题描述】:我正在尝试将RGB值编码到一个结构中,它工作正常,但是当我尝试运行一个访问该结构的函数时... 查看详情

MySQL:与案例一起使用时按子句分组不使用索引

】MySQL:与案例一起使用时按子句分组不使用索引【英文标题】:MySQL:GroupByClauseNotUsingIndexwhenusedwithCase【发布时间】:2016-05-0310:24:03【问题描述】:我正在使用MySQL我无法更改数据库结构,所以遗憾的是,这不是一个选项问题:... 查看详情

使用 EnumTypeAdapter 时,将 proguard 与 GSON 和 RoboGuice 一起使用会失败

】使用EnumTypeAdapter时,将proguard与GSON和RoboGuice一起使用会失败【英文标题】:UsingproguardwithGSONandRoboGuicefailswhenusingaEnumTypeAdapter【发布时间】:2013-03-0704:40:06【问题描述】:当尝试将EnumTypeAdapter与Proguard一起使用时,会导致Gson.getAd... 查看详情

为啥使用与父级一起声明的 std::function 在与子级一起使用时会显示错误?

】为啥使用与父级一起声明的std::function在与子级一起使用时会显示错误?【英文标题】:Whydoesusingastd::functiondeclaredwiththeparentshowmeanerrorwhenusedwithachild?为什么使用与父级一起声明的std::function在与子级一起使用时会显示错误?【发... 查看详情