我在圖層背景視圖上有一個子圖層。子圖層的內容設置爲圖像參考,並且是25x25矩形。
當touchesBegan和touchesMoved方法被調用時,我對super層執行命中測試。實際上,擊中測試方法確實會在觸摸時返回子圖層,但只有在圖像的下半部分被觸摸時纔會返回。如果圖像的上半部分被觸摸,它將返回超級圖層。圖層觸擊測試僅在觸摸圖層下半部分時返回圖層
我知道iPhone OS補償了用戶觸摸的趨勢低於預期。即使我將子圖調整爲更大尺寸(50x50),它也表現出相同的行爲。
有什麼想法?
我在圖層背景視圖上有一個子圖層。子圖層的內容設置爲圖像參考,並且是25x25矩形。
當touchesBegan和touchesMoved方法被調用時,我對super層執行命中測試。實際上,擊中測試方法確實會在觸摸時返回子圖層,但只有在圖像的下半部分被觸摸時纔會返回。如果圖像的上半部分被觸摸,它將返回超級圖層。圖層觸擊測試僅在觸摸圖層下半部分時返回圖層
我知道iPhone OS補償了用戶觸摸的趨勢低於預期。即使我將子圖調整爲更大尺寸(50x50),它也表現出相同的行爲。
有什麼想法?
感謝凱文...
我結束了剛剛重做我的代碼與UIViews。試圖弄清爲什麼UIView不知道什麼層被觸摸,這太麻煩了。我的理念背後的全部理由是,我將在屏幕上同時擁有100多個項目,並且認爲Layers在處理器上比UIViews更容易。我現在已經啓動並運行了應用程序,100個視圖並未給出任何打嗝。
我對別人只是命中測試UIViews可能的情況下堅持下去的建議,它使代碼更簡單
看來,該層不僅僅是接收底部像素的觸摸。相反,屏幕圖層上的「實際」和圖層內容似乎是由不同的CGRects定義的。圖像顯示在預期的座標上,而對觸摸作出響應的圖層位於圖像下方。通過下面,我的意思是圖像的起源在(200,200),並且響應觸摸的層的原點在(200,220)。
下面我發佈一些測試代碼,我用來重新創建問題。首先我的視圖子類,然後我的視圖控制器。任何推理這個問題的原因是不勝感激。
我的視圖子類:
#import "myView.h"
#import <QuartzCore/QuartzCore.h>
@implementation myView
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
CGPoint currentLocation = [[touches anyObject] locationInView:self];
CALayer *currentLayer = [self.layer hitTest:currentLocation];
CGPoint center = [currentLayer position];
NSLog([currentLayer valueForKey:@"isRootLayer"]);
if(![currentLayer valueForKey:@"isRootLayer"]) {
if (center.x != 200) {
[currentLayer setPosition:CGPointMake(200.0f, 200.0f)];
} else {
[currentLayer setPosition:CGPointMake(100.0f, 100.0f)];
}
}
}
- (id)initWithFrame:(CGRect)frame {
if (self = [super initWithFrame:frame]) {
// Initialization code
}
return self;
}
- (void)drawRect:(CGRect)rect {
// Drawing code
}
- (void)dealloc {
[super dealloc];
}
@end
我的視圖控制器:
#import "layerTestViewController.h"
#import <QuartzCore/QuartzCore.h>
#define ELEMENT_PERIOD_SIZE 50
#define ELEMENT_GROUP_SIZE 50
@implementation layerTestViewController
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad {
[super viewDidLoad];
CALayer *myLayer = [CALayer layer];
CGRect layerFrame =CGRectMake(0.0f, 0.0f, ELEMENT_GROUP_SIZE, ELEMENT_PERIOD_SIZE);
myLayer.frame = layerFrame;
[myLayer setName:[NSString stringWithString:@"test"]];
[myLayer setValue:[NSString stringWithString:@"testkey"] forKey:@"key"];
UIGraphicsBeginImageContext(layerFrame.size);
[[UIColor blueColor] set];
UIRectFill(layerFrame);
UIImage *theImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
myLayer.contents = (id)[theImage CGImage];
myLayer.position = CGPointMake(100.0f, 100.0f);
[self.view.layer addSublayer:myLayer];
[self.view.layer setValue:[NSString stringWithString:@"YES"] forKey:@"isRootLayer"];
NSLog([self.view.layer valueForKey:@"isRootLayer"]);
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning]; // Releases the view if it doesn't have a superview
// Release anything that's not essential, such as cached data
}
- (void)dealloc {
[super dealloc];
}
@end
如果觸摸正在對下部只承認,一種可能性是另一個子視圖被覆蓋的這個上半子視圖。你有多個子視圖還是隻有一個圖像?如果您有多個子視圖,並且其中任何一個都具有clearColor的背景顏色,請嘗試爲其提供穩定的背景顏色以供測試。這種方式你會知道你的子視圖是否被另一個子視圖覆蓋。
希望有所幫助。
我簡化了我的代碼以找到問題。我在屏幕上只有一個子圖層,沒有子視圖。上面列出的代碼就是我在模擬器中運行的代碼。由於屏幕上只有2個圖層,主視圖的背層和添加的子圖層都不會影響命中測試。
如果不清楚,當觸摸子圖層的頂部時,點擊測試會返回背層圖層。另外,如果我在底層下面的某點觸摸底層,則底層會通過命中測試返回。
這很難解釋,但如果你運行代碼,它變得清晰。
感謝
當我嘗試你的代碼,我得到幾乎正確的行爲,除了觸摸往往沒有在底層上的最邊緣的認可。至於發生了什麼,我有點困惑。你可能想嘗試做一些事情,比如當你註冊觸摸時,在發生觸摸的地方(比如5x5的某種顏色的方塊)拋出一個新的小圖層,然後在3秒後再次移除它。通過這種方式,您可以跟蹤CA認爲觸摸發生的位置與光標的實際位置。
順便說一句,你不需要爲你的藍色內容創建一個CGImage,你可以將圖層的backgroundColor
設置爲[UIColor blueColor].CGColor
。
的則hitTest文檔說:
/* Returns the farthest descendant of the layer containing point 'p'.
* Siblings are searched in top-to-bottom order. 'p' is in the
* coordinate system of the receiver's superlayer. */
所以,你需要做的(這樣的事情):
CGPoint thePoint = [touch locationInView:self];
thePoint = [self.layer convertPoint:thePoint toLayer:self.layer.superlayer];
CALayer *theLayer = [self.layer hitTest:thePoint];
(從其他崗位重複的答案完整起見)
接受的答案並不能解決問題,但schwa的答案確實如此。
我有一個窗口,一個視圖控制器和視圖。該視圖會在其圖層上接觸並調用hitTest:
。我遇到了同樣的問題,並發現視圖中的點是正確的,但在hitTest:
中,該點的y座標是20px off,恰好是狀態欄的高度。
通過將點映射到schwa建議的超層座標系,此問題得到修復。 「神祕」超級玩家是superview的根層。在我的情況下,它是窗口層(frame(0,0,320,480))。
謝謝!我遇到了同樣的問題,這讓我瘋狂。我仍然有點困惑,爲什麼它是必要的,但它似乎工作。 – 2009-03-20 22:51:45