使用していないときに 20% アルファにフェードアウトする UIPickerView があります。ユーザーがピッカーに触れてフェードインできるようにしたい.
メイン ビューに touchesBegan メソッドを配置すれば機能しますが、これはユーザーがビューに触れたときにのみ機能します。UIPickerView をサブクラス化し、そこに touchesBegan を入れようとしましたが、うまくいきませんでした。
レスポンダー チェーンと関係があると思いますが、解決できないようです。
使用していないときに 20% アルファにフェードアウトする UIPickerView があります。ユーザーがピッカーに触れてフェードインできるようにしたい.
メイン ビューに touchesBegan メソッドを配置すれば機能しますが、これはユーザーがビューに触れたときにのみ機能します。UIPickerView をサブクラス化し、そこに touchesBegan を入れようとしましたが、うまくいきませんでした。
レスポンダー チェーンと関係があると思いますが、解決できないようです。
この問題の解決策を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 サブビューでそれらを再度呼び出すことを忘れないでください。
これが理にかなっていることを願っています。今はコードを書くことができません。家に帰ったらすぐに、この回答を編集してコードを追加します。
ここにあなたが望むことをするいくつかのコードがあります:
@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;
}
親ビューのcanCancelContentTouchesとdelaysContentTouchesをNOに設定すると、うまくいきました
上記の回答は両方とも非常に役に立ちましたが、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 が、私自身の解決策を考え出すのを手伝ってくれてありがとう!