2009-02-20 7 views
6

使用していないときに20%のアルファにフェードアウトされるUIPickerViewがあります。UIViewの代わりにUIPickerViewのtouchesBeganに応答する

私はtouchesBeganメソッドをメインビューに置くと動作させることができますが、これはユーザーがビューに触れるときにのみ機能します。これは、ユーザーがピッカーに触れることができます。私はUIPickerViewをサブクラス化しようとしましたが、そこにtouchesBeganを持っていましたが、うまくいきませんでした。

私はそれがレスポンダーチェーンと関係があると思っていますが、それを解決できないようです。

答えて

10

私はこの問題の解決策を1週間以上探してきました。あなたが質問をしても、これが他人を助けることを望むなら、私はあなたに答えています。

私の言語はあまり技術的ではありませんが、私はObjective-CとiPhone開発にはかなり新しいです。

UIpickerViewをサブクラス化するのが正しい方法です。しかし、- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)eventメソッドをオーバーライドする必要があります。これは、画面に触れるたびに呼び出されるメソッドで、タッチに反応するビューを返します。つまり、touchesBegan:withEvent:メソッドが呼び出されるビューです。

UIPickerViewには9つのサブビューがあります。 UIPickerViewクラスの実装では、- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)eventselfを返しません(これは、サブクラスで書かれたtouchesBegan:withEvent:が呼び出されないことを意味します)。サブビュー、正確にはインデックス4のビュー(UIPickerTableと呼ばれる文書化されていないサブクラス)

トリックはそうあなたがtouchesBegan:withEvent:touchesMoved:withEvent:touchesEnded:withEvent:方法を制御できますselfを返すように- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event方法を作ることです。

これらの方法では、UIPickerViewの標準機能を維持するために、UIPickerTableサブビューで再度呼び出す必要があります。

これは意味があると思います。私は今すぐコードを書くことはできません。私が家にいるとすぐに、私はこの答えを編集し、いくつかのコードを追加します。ここで

8

が何をしたいんいくつかのコードです:

@interface TouchDetectionView : UIPickerView { 

} 
- (UIView *)getNextResponderView:(NSSet *)touches withEvent:(UIEvent *)event; 
@end 
@implementation TouchDetectionView 

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event 
{ 
    UIView * hitTestView = [self getNextResponderView:touches withEvent:event]; 
    [hitTestView touchesBegan:touches withEvent:event]; 
} 

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event 
{ 
    UIView * hitTestView = [self getNextResponderView:touches withEvent:event]; 
    [hitTestView touchesMoved:touches withEvent:event]; 
} 

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event 
{ 
    UIView * hitTestView = [self getNextResponderView:touches withEvent:event]; 
    [hitTestView touchesEnded:touches withEvent:event]; 
} 

- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event 
{ 
    UIView * hitTestView = [self getNextResponderView:touches withEvent:event]; 
    [hitTestView touchesCancelled:touches withEvent:event]; 
} 

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event 
{ 
    return self; 
} 

- (UIView *)getNextResponderView:(NSSet *)touches withEvent:(UIEvent *)event 
{ 
    UITouch * touch = [touches anyObject]; 
    CGPoint point = [touch locationInView:self]; 
    UIView * hitTestView = [super hitTest:point withEvent:event]; 

    return (hitTestView == self) ? nil : hitTestView; 
} 
+0

おかげで働いていたNOに親ビューの設定canCancelContentTouchesとdelaysContentTouches、:) – ArunGJ

+1

このコードは、タッチがすぐピッカーホイールを囲む枠の上に発生した場合を除いて、動作しているようです。そうすることで、getNextResponderView:withEvent:メソッドの呼び出しが無限ループするようです。 – pistachionut

+1

私はgetNextResponderViewからのhitTestViewの代わりにnilを返すことによってそれを防ぐ:withEvent:私は周りの車輪に触れた場合。 – ArunGJ

1

上記の答えはどちらも非常に有用だったが、私はUIScrollViewの内にネストUIPickerViewを持っています。私はまた、GUIが存在する間、画面上のどこかで連続レンダリングを行っています。問題は、UIPickerViewが完全に更新されないことです。選択されていない行をタップしたり、ピッカーを移動して2つの行が選択範囲を跨いだり、行がドラッグされてもUIPickerViewの外にスライドしたりします。その後、UIScrollViewが移動されてからピッカーが即時に更新されるまではありません。この結果は醜いです。

問題が原因です:私の継続的なレンダリングは、UIPickerViewのアニメーションがCPUサイクルを終了してから、正しい現在の選択を表示しないようにしていました。私の解決策 - これはうまくいきました - UIPickerViewのtouchesEnded:withEvent:では、レンダリングを一時停止するために何かを実行します。 SubUIPickerView.h、その後、

#import "SubUIPickerView.h" 

@implementation SubUIPickerView 

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

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

- (void) touchesEnded:(NSSet*)touches withEvent:(UIEvent*)event 
{ 
    [singleton set_secondsPauseRendering:0.5f]; // <-- my code to pause rendering 

    [pickerTable touchesEnded:touches withEvent:event]; 
} 

- (void) touchesCancelled:(NSSet*)touches withEvent:(UIEvent*)event 
{ 
    [pickerTable touchesCancelled:touches withEvent:event]; 
} 

- (UIView*) hitTest:(CGPoint)point withEvent:(UIEvent*)event 
{ 
    if (CGRectContainsPoint(self.bounds, point)) 
    { 
     if (pickerTable == nil) 
     { 
      int nSubviews = self.subviews.count; 
      for (int i = 0; i < nSubviews; ++i) 
      { 
       UIView* view = (UIView*) [self.subviews objectAtIndex:i]; 
       if ([view isKindOfClass:NSClassFromString(@"UIPickerTable")]) 
       { 
        pickerTable = (UIPickerTable*) view; 
        break; 
       } 
      } 
     } 
     return self; // i.e., *WE* will respond to the hit and pass it to UIPickerTable, above. 
    } 
    return [super hitTest:point withEvent:event]; 
} 

@end 

とヘッダ::ここでは、コードです

@class UIPickerTable; 

@interface SubUIPickerView : UIPickerView 
{ 
    UIPickerTable* pickerTable; 
} 

@end 

私が言ったように、この作品。UIPickerViewアニメーションを終了させるために、レンダリングがさらに1/2秒間停止します(UIScrollViewをスライドすると既に一時停止しています)。 NSClassFromString()を使用すると、文書化されていないAPIを使用していないことを意味します。レスポンダーチェーンを盗むことは必要ありませんでした。 checccoとTylerc230のおかげで私自身の解決策が生まれました。

+0

これは、iOS 8のUIPickerViewでは使用できなくなりました。 – MatthiasC

+0

@MatthiasCなぜそれがもう動作しないのか知っていますか? – stonedauwg

+0

UIPickerViewに関するこれらの投稿は本当に古いです。当時は新しいフレークだった。 Appleはおそらく(おそらく)これを完全に再実装しました! – electromaggot

0

私のためにそれが働いた

関連する問題