2012-08-12 22 views
5

想象你的鍵盤。想象一下,將一個手指放在一個按鍵上,然後(按住時)將手指移動到鍵盤上的另一個按鍵。現在,假設鍵盤上的每個鍵都是UIButton。當您按住當前鍵時,此鍵(UIButton)將突出顯示。然後,當用戶移動到另一個鍵時,第一個鍵不再突出顯示,並且當前按下的鍵被突出顯示。如何在使用一個UIButton的同時按住手指切換?

現在,我有一個6 x 8網格的UIButtons,每個53 x 53像素。所以,我有48 UIButtons。我想複製這種想法。用戶手指所在的按鈕將具有稍微更輕的圖像(看起來像選擇),其他所有按鈕都不會輕微點亮。

這裏是我的如何去這個想法,

1)viewDidLoad創建所有48 UIButtons。將所有UIButtons的圖片添加到UIControlStateHighlighted

2)爲touchUpOutside添加某種target,它以某種方式使當前按鈕不突出顯示並且不可用。 (也許設置突出顯示並且userInteractionEnabled爲否)。但是,我怎麼能告訴下一個按鈕被使用?我怎麼能說,我想要的用戶手指下的特定UIButton變得突出顯示並用於檢測手勢和東西。

而且,這個touchUpOutside方法可能無法正常工作,因爲所有的按鈕都是緊挨着的,我認爲你必須拖動很遠才能運行這個touchUpOutside

注意到按鈕沒有放在相同的行和列中也很重要。有時一個按鈕實際上是UIImage,但看起來像是UIButton。因此,由於某種原因做某種快速枚舉比較幀將不起作用。

+0

您描述了一些低級別的行爲(如果按下並將您的手指拖動到另一個按鈕),但是您沒有描述您要解決的更廣泛的問題,所以它會使您的問題有點回答強硬。你想做什麼?只需檢測一個按鈕的觸摸並觸摸另一個按鈕?或者像Swype一樣的打字方案中的整個系列?建議的答案可能取決於你想要做的事情。 – Rob 2012-08-12 03:39:18

+0

我也不明白你的最後一點,關於不快速枚舉框架不工作(因爲如果你擔心不同的子視圖類型,你只需檢查'isKindOfClass'知道什麼是正確的行爲)。看到我的答案。 – Rob 2012-08-12 03:39:55

+0

我認爲你的意思是UIImageView而不是UIImage – WolfLink 2012-08-12 06:24:36

回答

4

兩個意見:

  1. 我通常使用手勢識別爲這樣的東西,而不是各種touchUp...方法。

  2. 我知道你說你不想通過子視圖快速列舉,但爲什麼不呢?僅僅因爲有些人不同於其他人不是問題(因爲你只能測試isKindOfClass方法)。 (另外,我不確定爲什麼有些人會是按鈕,有些人不會。)僅僅因爲他們不排隊也沒有什麼區別。

無論如何,對於像這樣的東西,我經常會把手勢識別上的共享父視圖(例如典型視圖控制器的視圖),然後枚舉通過子視圖看,其中電流CGPoint載?

CGPoint location = [sender locationInView:self.view]; 

for (UIView *subview in self.view.subviews) 
{ 
    if (CGRectContainsPoint(subview.frame, location)) 
    { 
     // do your appropriate highlighting 

     if ([subview isKindOfClass:[UIButton class]]) 
     { 
      // something for buttons 
     } 
     else if ([subview isKindOfClass:[UIImageView class]]) 
     { 
      // something for imageviews 
     } 

     return; 
    } 
} 

我不知道這對你是否有意義,但對我來說似乎最簡單。如果你澄清你的意圖,也許我可以進一步完善我的答案。

就像一個實際的例子,你可以定義一個連續的手勢識別器,跟蹤被點擊的第一個和最後一個子視圖(如果你沒有在子視圖上開始你的手勢,沒有手勢產生,如果你不停止在一個子視圖您的姿態,它取消了整個事情),例如:

@interface SubviewGestureRecognizer : UIGestureRecognizer 

@property (nonatomic,strong) UIView *firstSubview; 
@property (nonatomic,strong) UIView *currentSubview; 

@end 

@implementation SubviewGestureRecognizer 

- (id) initWithTarget:(id)target action:(SEL)action 
{ 
    self = [super initWithTarget:target action:action]; 
    if (self) 
    { 
     self.firstSubview = nil; 
     self.currentSubview = nil; 
    } 

    return self; 
} 

// you might want to tweak this `identifySubview` to only look 
// for buttons and imageviews, or items with nonzero tag properties, 
// or recursively navigate if it encounters container UIViews 
// or whatever suits your app 

- (UIView *)identifySubview:(NSSet *)touches 
{ 
    CGPoint location = [[touches anyObject] locationInView:self.view]; 

    for (UIView *subview in self.view.subviews) 
    { 
     if (CGRectContainsPoint(subview.frame, location)) 
     { 
      return subview; 
     } 
    } 

    return nil; 
} 

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event 
{ 
    [super touchesBegan:touches withEvent:event]; 

    if ([touches count] != 1) 
    { 
     self.state = UIGestureRecognizerStateFailed; 
     return; 
    } 

    self.firstSubview = [self identifySubview:touches]; 
    self.currentSubview = self.firstSubview; 

    if (self.firstSubview == nil) 
     self.state = UIGestureRecognizerStateFailed; 
    else 
     self.state = UIGestureRecognizerStateBegan; 
} 

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event 
{ 
    [super touchesMoved:touches withEvent:event]; 

    if (self.state == UIGestureRecognizerStateFailed) return; 

    self.currentSubview = [self identifySubview:touches]; 

    self.state = UIGestureRecognizerStateChanged; 
} 

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event 
{ 
    [super touchesEnded:touches withEvent:event]; 

    self.currentSubview = [self identifySubview:touches]; 

    if (self.currentSubview != nil) 
     self.state = UIGestureRecognizerStateEnded; 
    else 
     self.state = UIGestureRecognizerStateFailed; 
} 

- (void)reset 
{ 
    [super reset]; 

    self.firstSubview = nil; 
    self.currentSubview = nil; 
} 

然後,您可以在viewDidLoad此設置:

SubviewGestureRecognizer *recognizer = [[SubviewGestureRecognizer alloc] initWithTarget:self action:@selector(handleTouches:)]; 
[self.view addGestureRecognizer:recognizer]; 

,然後定義您的處理程序這樣(這適用於按鈕和圖像視圖,採取優點:支持setHighlighted):

- (void)handleTouches:(SubviewGestureRecognizer *)sender 
{ 
    static UIControl *previousControl = nil; 

    if (sender.state == UIGestureRecognizerStateBegan || sender.state == UIGestureRecognizerStateChanged) 
    { 
     if (sender.state == UIGestureRecognizerStateBegan) 
      previousControl = nil; 

     UIView *subview = sender.currentSubview; 
     if (previousControl != subview) 
     { 
      // reset the old one (if any) 

      [previousControl setHighlighted:NO]; 

      // highlight the new one 

      previousControl = (UIControl *)subview; 
      [previousControl setHighlighted:YES]; 
     } 
    } 
    else if (sender.state == UIGestureRecognizerStateEnded) 
    { 
     if (previousControl) 
     { 
      [previousControl setHighlighted:NO]; 
      NSLog(@"successfully touchdown on %@ and touchup on %@", sender.firstSubview, sender.currentSubview); 
     } 
    } 
    else if (sender.state == UIGestureRecognizerStateCancelled || sender.state == UIGestureRecognizerStateFailed) 
    { 
     [previousControl setHighlighted:NO]; 
     NSLog(@"cancelled/failed gesture"); 
    } 
} 
+0

那麼,我有點猶豫,這樣做。因爲當用戶移動他的手指時,我希望它是即時的。而且,如果我每次運行這個方法都會產生一點阻力,我認爲可能會出現問題。 – bmende 2012-08-12 04:17:36

+0

我想你會發現它是瞬間的,但如果你願意的話,顯然可以採用其他方法。但在最基本的層面上,我認爲幕後所有這些技術都可能使用相同的「UIResponder」方法,「touchesBegan」,「touchesMoved」,「touchedEnded」等,所以我不確定它是否會有很大的不同。順便說一句,我已經用自定義手勢識別器更新了我的答案,該手勢識別器隱藏了很多「我已經完成了哪個子視圖」的邏輯,所以它在觸摸處理程序中有點清潔。但是,如果你發現另一種更符合自己喜好的技術,那麼當然不會冒犯任何人。 – Rob 2012-08-12 04:41:15

+2

@Sasquatch除非你有成千上萬的按鈕,我不會擔心。過早優化是根... – 2012-08-12 06:38:41

0

這是一個相當簡單的方法來做到這一點。假設您以編程方式創建按鈕(使用界面構建器完成此操作將會非常痛苦)。此方法在UIViewController,UIView和UIGestureRecognizer的子類中工作。

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { 

    //get the touch object 
    UITouch *myTouch = [touches anyObject]; 

    //get the location of the touch 
    CGPoint *myPoint = [myTouch locationInView:self.view]; 

    //detect if the touch is in one of your buttons 
    if (CGRectContainsPoint(myButton.frame, myPoint){ 
     /*do whatever needs to be done when the button is pressed 
     repeat the CGRectContainsPoint for all buttons, 
     perhaps using a while or for loop to look through an array?*/ 
    } 

} 

此方法只檢測當用戶將他們的手指下來,你將需要使用這些方法來檢測其他運動:

touchesMoved:withEvent檢測時,在屏幕上移動手指沒有擡起

touchesEnded:withEvent檢測手指離開屏幕時的位置

touchesCancelled:withEvent:檢測何時中斷應用程序,如接收呼叫或鎖定屏幕

相關問題