次のように初期化されるカスタムUITableViewCellがあります。
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
NSArray *nibArray = [[NSBundle mainBundle] loadNibNamed:@"CustomCell" owner:self options:nil];
self = [nibArray objectAtIndex:0];
[self setSelectionStyle:UITableViewCellSelectionStyleNone];
[self.downButton setBackgroundImage:[UIImage imageNamed:@"button"] forState:UIControlStateNormal];
[self.downButton setBackgroundImage:[UIImage imageNamed:@"buttonSelected"] forState:UIControlStateHighlighted];
}
return self;
}
ボタンは適切な背景画像とともに適切に表示されますが、強調表示された画像はボタンが押された/クリックされたときに瞬時に表示されません。代わりに、変更が発生する前に1〜2秒間押し続ける必要があります。一方、ボタンを離すと、元の背景画像に戻るinstant変更が行われます。
強調表示された画像に切り替えるときに遅刻の変化を緩和しようとして、次の方法で変更を加えました。
- (IBAction)downDown:(id)sender {
[self.downButton setBackgroundColor:[UIColor redColor]];
}
上記の方法は「Touch Down」(より一般的な「Touch Up Inside」とは反対)に設定されており、setBackgroundImage:forState:
強調表示された状態。上記と同じ問題。色は最終的に赤に変わりますが、ボタンをクリックして1、2秒間押した後のみです。
「Touch Up Inside」が発生したときに呼び出されるボタンのメソッドがあり、そのメソッドは問題なく実行されます-ボタンをすばやくタップするか、リリースする前にしばらくクリックして長押しするかに関わらず。
それでは、なぜ「タッチダウン」またはUIControlStateHighlighted
の遅延なのでしょうか?ボタンが押されたことを示すために、ユーザーに即座にフィードバックを提供しようとしています。
必要に応じてより多くのコードを提供できますが、これらは背景の外観に関係する唯一のビットです。
これは、UIScrollView
プロパティdelaysContentTouches
が原因です。
NO
自体のプロパティをUITableView
に設定するだけで十分でしたが、別のUIScrollView
に含まれていないテーブルのサブビューでのみ機能します。
UITableViewCells
にはiOS 7の内部スクロールビューが含まれているため、ボタンが含まれるすべてのセルのセルレベルでこのプロパティの値を変更する必要があります。
ここにあなたがする必要があるものがあります:
1.in viewDidLoad
またはUITableView
が初期化されたらどこかに似た場所に、これを入れます:
self.tableView.delaysContentTouches = NO;
2. iOS 7サポートの場合、UITableViewCell
(initWithStyle:reuseIdentifier:
またはinitWithCoder:
(NIBの場合)、これを最後に入力します。
for (UIView *currentView in self.subviews)
{
if([currentView isKindOfClass:[UIScrollView class]])
{
((UIScrollView *)currentView).delaysContentTouches = NO;
break;
}
}
Appleは将来、セル内のビュー階層を再び変更できる可能性があります(おそらく、スクロールビューを別のレイヤーに移動したり、別のループをネストする必要がある場合があります)そこにあります)、しかし、彼らが何らかの形でクラスまたは少なくともプロパティを開発者に明らかにするまで、これは私たちが持っている最高のものです。
Swift 3ソリューション(iOS8 +の場合):
まず、viewDidLoad()
メソッド内など、正常にロードされた後のUITableView
の遅延をオフにします。
someTableView.delaysContentTouches = false
次に、UITableView
内に含まれるスクロールビューの遅延をオフにします。
for case let scrollView as UIScrollView in someTableView.subviews {
scrollView.delaysContentTouches = false
}
IOS7に関する注意:UITableViewCell
の遅延を無効にする必要がある場合があります。 (ディマの答えを確認してください)。
他にもいくつかのヒントがあります こちら 。
uIButtonをサブクラス化することでコード内のこの問題を解決し、
客観的C
@interface TBButton : UIButton
@end
@implementation TBButton
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
self.highlighted = true;
[super touchesBegan:touches withEvent:event];
}
- (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
self.highlighted = false;
[super touchesEnded:touches withEvent:event];
}
- (void)touchesCancelled:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
self.highlighted = false;
[super touchesCancelled:touches withEvent:event];
}
@end
Swift
class TBButton: UIButton {
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
highlighted = true
super.touchesBegan(touches, withEvent: event)
}
override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?) {
highlighted = false
super.touchesEnded(touches, withEvent: event)
}
override func touchesCancelled(touches: Set<UITouch>?, withEvent event: UIEvent?) {
highlighted = false
super.touchesCancelled(touches, withEvent: event)
}
}
スイフト3
class TBButton: UIButton {
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
isHighlighted = true
super.touchesBegan(touches, with: event)
}
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
isHighlighted = false
super.touchesEnded(touches, with: event)
}
override func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent?) {
isHighlighted = false
super.touchesCancelled(touches, with: event)
}
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
isHighlighted = true
super.touchesBegan(touches, with: event)
}
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
isHighlighted = false
super.touchesEnded(touches, with: event)
}
override func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent?) {
isHighlighted = false
super.touchesCancelled(touches, with: event)
}
以下は、View Controllerに追加できる再帰的なソリューションです。
+ (void)disableDelayedTouches:(UIView*)view
{
for(UIView *currentView in view.subviews) {
if([currentView isKindOfClass:[UIScrollView class]]) {
((UIScrollView *)currentView).delaysContentTouches = NO;
}
[self disableDelayedTouches:currentView];
}
}
- (void)viewDidLoad
{
[super viewDidLoad];
[self.class disableDelayedTouches:self.view];
}
それでは、なぜ「タッチダウン」または
UIControlStateHighlighted
の遅延なのでしょうか?ボタンが押されたことを示すために、ユーザーに即座にフィードバックを提供しようとしています。
Appleまだ説明していませんか?