私のアプリには、さまざまなイベントをトリガーするボタンがいくつかあります。ユーザーは複数のボタンを押し続けてはいけません。とにかく、いくつかのボタンを押し続けるとアプリがクラッシュします。
そのため、アプリでマルチタッチを無効にしようとしています。
すべてのxibファイルで「Multiple Touch」のチェックを外しました。私ができる限り、プロパティ「multipleTouchEnabled」と「exclusiveTouch」は、ビューがマルチタッチを使用するかどうかを制御します。だから私のapplicationDidFinishLaunchingにこれを入れました:
self.mainViewController.view.multipleTouchEnabled=NO;
self.mainViewController.view.exclusiveTouch =YES;
そして、各ビューコントローラーで、これをviewDidLoadに入れました
self.view.multipleTouchEnabled=NO;
self.view.exclusiveTouch=YES;
ただし、stillは複数のタッチを受け入れます。タッチダウンイベントを取得した後で他のボタンを無効にするなどの操作を行うこともできますが、これは醜いハックになります。確かにマルチタッチを適切に無効にする方法はありますか?
一度に1つのボタンのみがタッチに応答するようにしたい場合は、親ビューではなく、そのボタンにexclusiveTouchを設定する必要があります。または、ボタンが「タッチダウン」イベントを受け取ったときに、他のボタンを無効にすることもできます。
後者の例は次のとおりです。これは、私のテストでより効果的に機能しました。ボタンにexclusiveTouchを設定することは一種の方法で機能しましたが、単にクリックするのではなく、ボタンの端から指を離したときにいくつかの興味深い問題が発生しました。
コントローラのアウトレットを各ボタンに接続し、コントローラの適切なメソッドに接続した「タッチダウン」、「タッチアップインサイド」、「タッチアウトアウトサイド」イベントを用意する必要があります。
#import "multibuttonsViewController.h"
@implementation multibuttonsViewController
// hook this up to "Touch Down" for each button
- (IBAction) pressed: (id) sender
{
if (sender == one)
{
two.enabled = false;
three.enabled = false;
[label setText: @"One"]; // or whatever you want to do
}
else if (sender == two)
{
one.enabled = false;
three.enabled = false;
[label setText: @"Two"]; // or whatever you want to do
}
else
{
one.enabled = false;
two.enabled = false;
[label setText: @"Three"]; // or whatever you want to do
}
}
// hook this up to "Touch Up Inside" and "Touch Up Outside"
- (IBAction) released: (id) sender
{
one.enabled = true;
two.enabled = true;
three.enabled = true;
}
@end
- (void)viewDidLoad {
[super viewDidLoad];
for(UIView* v in self.view.subviews)
{
if([v isKindOfClass:[UIButton class]])
{
UIButton* btn = (UIButton*)v;
[btn setExclusiveTouch:YES];
}
}
}
- (void)viewDidLoad {
[super viewDidLoad];
for(UIView* v in self.view.subviews)
{
if([v isKindOfClass:[UIButton class]])
{
UIButton* btn = (UIButton*)v;
[btn setExclusiveTouch:YES];
}
}
}
このコードはテスト済みであり、私にとっては完全に機能しています。一度に複数のボタンを押しても、アプリがクラッシュすることはありません。
アプリは何らかの理由でクラッシュします。さらに調査し、デバッガを使用して、バグを隠そうとするのではなく、何が問題かを確認します。
編集:
わかった、わかった、私は少し厳しいと認めざるを得なかった。 each buttonにexclusiveTouchプロパティを設定する必要があります。それで全部です。 multipleTouchEnabledプロパティは無関係です。
アプリケーション全体でマルチタッチを無効にし、各ボタンのコードを記述したくない場合は、ボタンのAppearance
を使用できます。以下の行をdidFinishLaunchingWithOptions
に記述します。
UIButton.appearance().isExclusiveTouch = true
それは素晴らしいことです!! IAppearance
いくつかのボタンでマルチタッチを無効にする場合は、UIView
クラスのいずれにも使用できます。ボタンのCustomClassを作成し、次に
CustomButton.appearance().isExclusiveTouch = true
あなたを助けることができるもう一つの利点があります。特定のViewController
のボタンのマルチタッチを無効にする場合
UIButton.appearance(whenContainedInInstancesOf: [ViewController2.self]).isExclusiveTouch = true
Neoevokeの回答に基づいて、サブビューの子もチェックするように少しだけ改善し、この関数を作成してutilsファイルに追加しました。
// Set exclusive touch to all children
+ (void)setExclusiveTouchToChildrenOf:(NSArray *)subviews
{
for (UIView *v in subviews) {
[self setExclusiveTouchToChildrenOf:v.subviews];
if ([v isKindOfClass:[UIButton class]]) {
UIButton *btn = (UIButton *)v;
[btn setExclusiveTouch:YES];
}
}
}
次に、単純な呼び出し:
[Utils setExclusiveTouchToChildrenOf:self.view.subviews];
...トリックを行います。
これは、テスターから報告されている問題であることがよくあります。私が時々使用しているアプローチの1つは、意識的に使用する必要がありますが、次のようにUIView
のカテゴリを作成することです。
@implementation UIView (ExclusiveTouch)
- (BOOL)isExclusiveTouch
{
return YES;
}
この場合、ExclusiveTouchプロパティを使用して、かなり簡単に使用できます。
[youBtn setExclusiveTouch:YES];
これは、レシーバーがタッチイベントのみを処理するかどうかを示すブール値です。
このプロパティをYESに設定すると、レシーバーは同じウィンドウ内の他のビューへのタッチイベントの配信をブロックします。このプロパティのデフォルト値はNOです。
Swiftでマルチタッチを無効にするには:
最初に、すべてのボタンのアウトレットを用意する必要があります。その後、エクスクルーシブタッチをtrueに設定するだけです。したがって、viewDidLoad()
には次のようになります。
yourButton.exclusiveTouch = true
。
//本当に必要ではありませんが、追加することもできます:
self.view.multipleTouchEnabled = false
Xamarin.iOSでグローバルマルチタッチを無効にする場合
以下のコードをコピーして貼り付けます。
[DllImport(ObjCRuntime.Constants.ObjectiveCLibrary, EntryPoint = "objc_msgSend")]
internal extern static IntPtr IntPtr_objc_msgSend(IntPtr receiver, IntPtr selector, bool isExclusiveTouch);
static void SetExclusiveTouch(bool isExclusiveTouch)
{
var selector = new ObjCRuntime.Selector("setExclusiveTouch:");
IntPtr_objc_msgSend(UIView.Appearance.Handle, selector.Handle, isExclusiveTouch);
}
AppDelegateに設定します。
public override bool FinishedLaunching(UIApplication app, NSDictionary options)
{
...
SetExclusiveTouch(true); // setting exlusive to true disables the multitouch
...
}
私の経験では、デフォルトでは、新しいプロジェクトではマルチタッチすら許可されていないため、オンにする必要があります。しかし、それはあなたがどのように始めたかに依存すると思います。マルチタッチの例をテンプレートとして使用しましたか?
まず最初に、マルチタッチがオンになっていると確信していますか?シングルタッチをシーケンスで非常に迅速に生成することが可能です。マルチタッチとは、2本以上の指を表面に置いた後の操作のことです。多分あなたはシングルタッチを持っていますが、2つのボタンがほぼ同時に押された場合に何が起こるかを正しく扱っていません。
ビューの周りでオブジェクトをドラッグするときに、別のオブジェクトに同時に触れた場合にtouchesBeganメソッドが起動するという奇妙なケースに悩まされていました。私の回避策は、touchesEndedまたはtouchesCancelledが呼び出されるまで、親ビューのユーザー操作を無効にすることでした。
override func touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent?) {
// whatever setup you need
self.view.userInteractionEnabled = false
}
override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?) {
// whatever setup you need
self.view.userInteractionEnabled = true
}
override func touchesCancelled(touches: Set<UITouch>?, withEvent event: UIEvent?) {
// whatever setup you need
self.view.userInteractionEnabled = true
}
私はこの方法でこの問題を決定しました:
NSTimeInterval intervalButtonPressed;
- (IBAction)buttonPicturePressed:(id)sender{
if (([[NSDate date] timeIntervalSince1970] - intervalButtonPressed) > 0.1f) {
intervalButtonPressed = [[NSDate date] timeIntervalSince1970];
//your code for button
}
}
UIView Class Extensionを作成し、この2つの関数を追加しました。ビュータッチを無効にする場合は、[view makeExclusiveTouch]を呼び出します。
- (void) makeExclusiveTouchForViews:(NSArray*)views {
for (UIView * view in views) {
[view makeExclusiveTouch];
}
}
- (void) makeExclusiveTouch {
self.multipleTouchEnabled = NO;
self.exclusiveTouch = YES;
[self makeExclusiveTouchForViews:self.subviews];
}
プログラムでマルチタッチを無効にする場合、またはcocos2d(multipleTouchEnabledオプションなし)を使用している場合は、ccTouchesデリゲートで次のコードを使用できます。
- (BOOL)ccTouchesBegan:(NSSet *)touches
withEvent:(UIEvent *)event {
NSSet *multiTouch = [event allTouches];
if( [multiTouch count] > 1) {
return;
}
else {
//else your rest of the code
}
私はまさにこの問題を抱えていました。
私たちが思いついた解決策は、単にinitWithCoderメソッドをオーバーライドするUIButtonから新しいクラスを継承し、一度に1つのボタンプッシュが必要な場所(つまり、どこでも)を使用することでした:
@implementation ExclusiveButton
(id)initWithCoder: (NSCoder*)decoder
{
[self setExclusiveTouch:YES];
return [super initWithCoder:decoder]
}
@end
これはnibファイルからロードされたボタンでのみ機能することに注意してください。
"Touch Down"イベントでビュー上のすべてのボタンを無効にし、"Touch Up Inside"イベントで有効にします。
例えば
- (void) handleTouchDown {
for (UIButton *btn in views) {
btn.enable = NO;
}
}
- (void) handleTouchUpInside {
for (UIButton *btn in views) {
btn.enable = Yes;
}
------
------
}