- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
所以我有一个精简的 ViewController 示例,它重现了我似乎无法理解的这种行为。我正在使用 UIPanGestureRecognizer 和一些代码,这些代码可以正确地允许 UIView 在窗口中移动。但是,如果我更新框架,即使是更新框架本身, View 也会跳到一个意想不到的位置,大概是基于 View 的中心。
关于这段代码我有两个问题。首先,为什么 View 的中心是最后一次触摸的位置(基本上是映射到 View 边界的 anchor ),而且显然与 View 框架的中心没有任何关系?
其次,为什么将 frame 属性更改为当前值时 View 会移动?在我看来, View 的中心和框架只是部分相关,我不确定我遗漏了什么。
这个例子只是在应用委托(delegate)中创建了一个基本的测试 View Controller :
TestViewController *vc = [[TestViewController alloc] init];
self.window.rootViewController = vc;
TestViewController.m:
#import "TestViewController.h"
#import <QuartzCore/QuartzCore.h>
@implementation TestViewController
- (void)loadView
{
self.view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 1024, 748)];
self.view.backgroundColor = UIColor.redColor;
UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(onPan:)];
pan.maximumNumberOfTouches = 1;
[self.view addGestureRecognizer:pan];
}
- (void)onPan:(UIPanGestureRecognizer*)recognizer
{
if (recognizer.state == UIGestureRecognizerStateBegan) {
UIView *view = recognizer.view;
CGPoint locationInView = [recognizer locationInView:view];
CGPoint locationInSuperview = [recognizer locationInView:view.superview];
view.layer.anchorPoint = CGPointMake(locationInView.x / view.bounds.size.width, locationInView.y / view.bounds.size.height);
view.center = locationInSuperview;
}
if (recognizer.state == UIGestureRecognizerStateBegan || recognizer.state == UIGestureRecognizerStateChanged) {
CGPoint translation = [recognizer translationInView:[recognizer.view superview]];
[recognizer.view setCenter:CGPointMake(recognizer.view.center.x + translation.x, recognizer.view.center.y+translation.y)];
[recognizer setTranslation:CGPointZero inView:[recognizer.view superview]];
}
if(recognizer.state == UIGestureRecognizerStateEnded) {
NSLog(@"AnchorPoint: %@", NSStringFromCGPoint(self.view.layer.anchorPoint));
NSLog(@"Center: %@", NSStringFromCGPoint(self.view.center));
NSLog(@"Frame: %@", NSStringFromCGRect(self.view.frame));
self.view.frame = self.view.frame;
}
}
@end
当平移手势结束时,如果我删除以下行,平移会按预期工作:
self.view.frame = self.view.frame;
我真的不明白那条线是如何导致 View 四处移动的,除非之前的 center 属性没有“完全粘住”之类的。此外,我不明白 center 属性的值(value),因为它似乎是最后触摸的地方,而不是 View 的中心。示例日志:
AnchorPoint: {0.204427, 0.748506}
Center: {625, 218.5}
Frame: {{14, -34}, {768, 1004}}
从长远来看,我在这里尝试实现的是一个可以缩放的 View ,但是当滚动到边缘之外时会快速返回(就像 UIScrollView 那样)。
最佳答案
如果去掉这两行
view.layer.anchorPoint = CGPointMake(locationInView.x / view.bounds.size.width, locationInView.y / view.bounds.size.height);
view.center = locationInSuperview;
然后您的 View 平移将按照您的预期运行。你为什么要改变图层的 anchor 呢?一般来说,您的代码对于您要实现的目标来说似乎过于复杂。参见 David Rönnqvist,understanding the anchor point关于更改 anchor 如何(通常是意想不到的)影响 View 的框架属性。
此外,单独保留顶层 View ( View Controller 的 self.view
)并操作 subview 通常是个好主意。这样你就知道一切与 viewController 的 View 是如何相关的,而不用想知道 UIWindow 发生了什么。当您旋转设备时,旋转变换将应用于该顶层 View ,这在您检查帧数据时无济于事。它的 subview 的属性不受该转换的影响。
您的代码在未转换的纵向模式下的行为与您预期的一样,并且只会在横向或纵向颠倒时抛出奇怪的结果。这些是 View 应用了旋转变换的情况。 Apple 表示当对 View 应用变换时,框架的 origin 属性未定义,因此当您这样做时:
self.view.frame = self.view.frame
您正在分配未定义状态的属性。期待意外。
您可以这样更改您的 View 加载代码:
- (void)viewDidLoad
{
[super viewDidLoad];
UIView* subview = [[UIView alloc] initWithFrame:
CGRectMake(0, 0
, self.view.bounds.size.width
, self.view.bounds.size.height)];
[self.view addSubview:subview];
subview.backgroundColor = UIColor.redColor;
[subview setAutoresizingMask:UIViewAutoresizingFlexibleWidth
|UIViewAutoresizingFlexibleHeight];
UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc]
initWithTarget:self
action:@selector(onPan:)];
pan.maximumNumberOfTouches = 1;
[subview addGestureRecognizer:pan];
}
这里我们不覆盖-loadView,让它自动创建顶层 View ,然后我们在viewDidLoad
中实现一个 subview 。现在您的测试应用可以正常运行。
关于ios - pan码更新center后UIView frame和center不相关?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16234631/
我查看了网站上的一些问题,但还没有完全弄清楚我做错了什么。我有一些这样的代码: var mongoose = require('mongoose'), db = mongoose.connect('m
基本上,根据 this bl.ocks,我试图在开始新序列之前让所有 block 都变为 0。我认为我需要的是以下顺序: 更新为0 退出到0 更新随机数 输入新号码 我尝试通过添加以下代码块来遵循上述
我试图通过使用随机数在循环中设置 JSlider 位置来模拟“赛马”的投注结果。我的问题是,当然,我无法在线程执行时更新 GUI,因此我的 JSlider 似乎没有在竞赛,它们从头到尾都在运行。我尝试
该功能非常简单: 变量:$table是正在更新的表$fields 是表中的字段,$values 从帖子生成并放入 $values 数组中而$where是表的索引字段的id值$indxfldnm 是索引
让我们想象一个环境:有一个数据库客户端和一个数据库服务器。数据库客户端可以是 Java 程序或其他程序等;数据库服务器可以是mysql、oracle等。 需求是在数据库服务器上的一个表中插入大量记录。
在我当前的应用程序中,我正在制作一个菜单结构,它可以递归地创建自己的子菜单。然而,由于这个原因,我发现很难也允许某种重新排序方法。大多数应用程序可能只是通过“排序”列进行排序,但是在这种情况下,尽管这
Provisioning Profile 有 key , key 链依赖于它。我想知道 key 什么时候会改变。 Key will change after renew Provisioning Pr
截至目前,我在\server\publications.js 中有我的 MongoDB“选择”,例如: Meteor.publish("jobLocations", function () { r
我读到 UI 应该始终在主线程上更新。但是,当谈到实现这些更新的首选方法时,我有点困惑。 我有各种函数可以执行一些条件检查,然后使用结果来确定如何更新 UI。我的问题是整个函数应该在主线程上运行吗?应
我在代理后面,我无法构建 Docker 镜像。 我试过 FROM ubuntu , FROM centos和 FROM alpine ,但是 apt-get update/yum update/apk
我构建了一个 Java 应用程序,它向外部授权客户端公开网络服务。 Web 服务使用带有证书身份验证的 WS-security。基本上我们充当自定义证书颁发机构 - 我们在我们的服务器上维护一个 ja
因此,我有时会在上传新版本时使用 app_offline.htm 使应用程序离线。 但是,当我上传较大的 dll 时,我收到黄色错误屏幕,指出无法加载 dll。 这似乎与我对 app_offline.
我刚刚下载了 VS Apache Cordova Tools Update 5,但遇到了 Node 和 NPM 的问题。我使用默认的空白 cordova 项目进行测试。 版本 如果我在 VS 项目中对
所以我有一个使用传单库实例化的 map 对象。 map 实例在单独的模板中创建并以这种方式路由:- var app = angular.module('myApp', ['ui', 'ngResour
我使用较早的 Java 6 u 3 获得的帧速率是新版本的两倍。很奇怪。谁能解释一下? 在 Core 2 Duo 1.83ghz 上,集成视频(仅使用一个内核)- 1500(较旧的 java)与 70
我正在使用 angular 1.2 ng-repeat 创建的 div 也包含 ng-click 点击时 ng-click 更新 $scope $scope 中的变化反射(reflect)在使用 $a
这些方法有什么区别 public final void moveCamera(CameraUpdate更新)和public final void animateCamera (CameraUpdate
我尝试了另一篇文章中某人评论中关于如何将树更改为列表的建议。但是,我在某处(或某物)有未声明的变量,所以我列表中的值是 [_G667, _G673, _G679],而不是 [5, 2, 6],这是正确
实现以下场景的最佳方法是什么? 我需要从java应用程序调用/查询包含数百万条记录的数据库表。然后,对于表中的每条记录,我的应用程序应该调用第三方 API 并获取状态字段作为响应。然后我的应用程序应该
只是在编写一些与 java 图形相关的代码,这是我今天的讲座中的非常简单的示例。不管怎样,互联网似乎说更新不会被系统触发器调用,例如调整框架大小等。在这个例子中,更新是由这样的触发器调用的(因此当我只
我是一名优秀的程序员,十分优秀!