6

使用していないときに 20% アルファにフェードアウトする UIPickerView があります。ユーザーがピッカーに触れてフェードインできるようにしたい.

メイン ビューに touchesBegan メソッドを配置すれば機能しますが、これはユーザーがビューに触れたときにのみ機能します。UIPickerView をサブクラス化し、そこに touchesBegan を入れようとしましたが、うまくいきませんでした。

レスポンダー チェーンと関係があると思いますが、解決できないようです。

4

5 に答える 5

10

この問題の解決策を1週間以上探していました。質問が 1 年以上前のものであっても、これが他の人の役に立てば幸いです。

私の言葉があまり技術的でない場合は申し訳ありませんが、私は Objective-C と iPhone の開発にかなり慣れていません。

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

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

トリックは、- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)eventメソッドを返すようにして、 、およびメソッドselfを制御できるようにすることです。touchesBegan:withEvent:touchesMoved:withEvent:touchesEnded:withEvent:

これらのメソッドでは、UIPickerView の標準機能を維持するために、UIPickerTable サブビューでそれらを再度呼び出すことを忘れないでください。

これが理にかなっていることを願っています。今はコードを書くことができません。家に帰ったらすぐに、この回答を編集してコードを追加します。

于 2010-07-15T08:59:17.763 に答える
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;
}
于 2011-05-07T00:24:55.013 に答える
1

親ビューのcanCancelContentTouchesとdelaysContentTouchesをNOに設定すると、うまくいきました

于 2013-01-04T16:57:35.137 に答える
1

上記の回答は両方とも非常に役に立ちましたが、UIScrollView 内にネストされた UIPickerView があります。また、GUI が存在する間、画面上の別の場所で継続的なレンダリングも行っています。問題は、次の場合に UIPickerView が完全に更新されないことです: 選択されていない行がタップされた場合、2 つの行が選択領域をまたぐようにピッカーが移動された場合、または行がドラッグされたが指が UIPickerView の外にスライドした場合。その後、ピッカーが即座に更新されるのは、UIScrollView が移動されるまでではありません。この結果は醜いです。

問題の原因: 継続的なレンダリングにより、UIPickerView のアニメーションが終了するのに必要な CPU サイクルを取得できず、正しい現在の選択を表示できませんでした。私の解決策 - これは機能します - はこれでした: UIPickerView でtouchesEnded:withEvent:、レンダリングを一時停止するために何かを実行します。コードは次のとおりです。

#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

そしてヘッダー SubUIPickerView.h:

@class UIPickerTable;

@interface SubUIPickerView : UIPickerView
{
    UIPickerTable*  pickerTable;
}

@end

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

于 2011-07-06T05:34:45.030 に答える