質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Android

Androidは、Google社が開発したスマートフォンやタブレットなど携帯端末向けのプラットフォームです。 カーネル・ミドルウェア・ユーザーインターフェイス・ウェブブラウザ・電話帳などのアプリケーションやソフトウェアをひとつにまとめて構成。 カーネル・ライブラリ・ランタイムはほとんどがC言語/C++、アプリケーションなどはJavaSEのサブセットとAndroid環境で書かれています。

Q&A

解決済

2回答

2876閲覧

マルチタッチにて、二本指(多指)でのタッチの時片方を離してもタッチしたままと判定されてしまいます

ko20vonobird

総合スコア50

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Android

Androidは、Google社が開発したスマートフォンやタブレットなど携帯端末向けのプラットフォームです。 カーネル・ミドルウェア・ユーザーインターフェイス・ウェブブラウザ・電話帳などのアプリケーションやソフトウェアをひとつにまとめて構成。 カーネル・ライブラリ・ランタイムはほとんどがC言語/C++、アプリケーションなどはJavaSEのサブセットとAndroid環境で書かれています。

0グッド

0クリップ

投稿2017/02/09 05:30

編集2017/02/09 08:55

###前提
不具合なくマルチタッチを実現したいです。

###発生している問題
エラーメッセージはありません。
二本指(多指)でタッチしている時だけなのですが、片方を上げても、両方タッチしたままと判定されることが度々あります。

###該当のソースコード
念のためMotionEvent.ACTION_POINTER_UPの部分を抜粋して載せます。
colchkは左右どちらの領域がタッチされているかを表しています。
ttx,ttyは今は使用しておりません。fingidもです。
sc.colchange(),sc.colreturn()は領域の色を変えるためのメソッドを呼び出しています。

Java

1case MotionEvent.ACTION_POINTER_UP: 2 colchk = 0; 3 fingnum = event.getPointerCount(); 4 fingid = new int[fingnum]; 5 ttx = new float[fingnum]; 6 tty = new float[fingnum]; 7 //タッチ箇所が一本以上の時trueを返し、処理を行う。また、下にあるelseifで指が一本の時の処理もある。 8 if (fingnum > 1) { 9 //タッチされている数だけ処理を行う 10 for (int cnt = 0; cnt < fingnum; cnt++) { 11 pid = event.getPointerId(cnt); 12 index = event.findPointerIndex(pid); 13 tx = event.getX(index); 14 ty = event.getY(index); 15 //繰り返し回数一回目の時処理を行う 16 if (cnt == 0){ 17 textView1.setText("tx1:" + tx + " ty1:" + ty); 18 ltx = String.valueOf(tx); 19 lty = String.valueOf(ty); 20 Log.d("tx,ty", "tx:" + ltx + " ty:" + lty); 21 } 22 //繰り返し回数二回目の時処理を行う 23 if (cnt == 1){ 24 textView2.setText("tx2:" + tx + " ty2:" + ty); 25 ltx = String.valueOf(tx); 26 lty = String.valueOf(ty); 27 Log.d("tx,ty", "tx:" + ltx + " ty:" + lty); 28 } 29 ttx[cnt] = tx;//Data indexを基準とする 30 tty[cnt] = ty;//上に同じ 31 //何もタッチされていない初期状態の時処理を行う 32 if (colchk == 0) { 33 //指定領域かどうかを判定し、領域内でタッチされていたら処理を行う。 34 if (pow(tx - (winW * 0.15f), 2) + pow(ty - (winH - (winH * 0.15f)), 2) < pow((winH * 0.1f), 2) || pow(tx - (winW * 0.33f), 2) + pow(ty - (winH - (winH * 0.15f)), 2) < pow((winH * 0.1f), 2) || (winW * 0.15f <= tx && tx <= winW * 0.33f) && (winH - (winH * 0.25f) <= ty && ty <= winH - (winH * 0.05f))) { 35 colchk = 1; 36 sc.colchange(); 37 Log.d("hand", "left"); 38 } 39 //指定領域かどうかを判定し、領域内でタッチされていたら処理を行う。 40 if (pow(tx - (winW - (winW * 0.33f)), 2) + pow(ty - (winH - (winH * 0.15f)), 2) < pow((winH * 0.1f), 2) || pow(tx - (winW - (winW * 0.15f)), 2) + pow(ty - (winH - (winH * 0.15f)), 2) < pow((winH * 0.1f), 2) || (winW - (winW * 0.33f) <= tx && tx <= winW - (winW * 0.15f)) && (winH - (winH * 0.25f) <= ty && ty <= winH - (winH * 0.05f))) { 41 colchk = 2; 42 sc.colchange(); 43 Log.d("hand", "right"); 44 } 45 } 46 //左がタッチされている時に処理を行う。 47 if (colchk == 1) { 48 //指定領域かどうかを判定し、領域内でタッチされていたら処理を行う。 49 if (pow(tx - (winW - (winW * 0.33f)), 2) + pow(ty - (winH - (winH * 0.15f)), 2) < pow((winH * 0.1f), 2) || pow(tx - (winW - (winW * 0.15f)), 2) + pow(ty - (winH - (winH * 0.15f)), 2) < pow((winH * 0.1f), 2) || (winW - (winW * 0.33f) <= tx && tx <= winW - (winW * 0.15f)) && (winH - (winH * 0.25f) <= ty && ty <= winH - (winH * 0.05f))) { 50 colchk = 3; 51 sc.colchange(); 52 Log.d("hand", "leftright"); 53 } 54 } 55 //右がタッチされている時に処理を行う。 56 if (colchk == 2){ 57 //指定領域かどうかを判定し、領域内でタッチされていたら処理を行う。 58 if (pow(tx - (winW * 0.15f), 2) + pow(ty - (winH - (winH * 0.15f)), 2) < pow((winH * 0.1f), 2) || pow(tx - (winW * 0.33f), 2) + pow(ty - (winH - (winH * 0.15f)), 2) < pow((winH * 0.1f), 2) || (winW * 0.15f <= tx && tx <= winW * 0.33f) && (winH - (winH * 0.25f) <= ty && ty <= winH - (winH * 0.05f))) { 59 colchk = 3; 60 sc.colchange(); 61 Log.d("hand", "leftright"); 62 } 63 } 64 //何もタッチされていない時に処理を行う。 65 if (colchk == 0) { 66 sc.colreturn(); 67 Log.d("hand", "out"); 68 } 69 } 70 } else if (fingnum == 1) {//タッチ箇所が一か所の時処理を行う。 71 int cnt = 0; 72 pid = event.getPointerId(cnt); 73 index = event.findPointerIndex(pid); 74 tx = event.getX(index); 75 ty = event.getY(index); 76 textView1.setText("tx1:" + tx + " ty1:" + ty); 77 ltx = String.valueOf(tx); 78 lty = String.valueOf(ty); 79 Log.d("tx,ty", "tx:" + ltx + " ty:" + lty); 80 //指定領域かどうかを判定し、領域内でタッチされていたら処理を行う。 81 if (pow(tx - (winW * 0.15f), 2) + pow(ty - (winH - (winH * 0.15f)), 2) < pow((winW * 0.1f), 2) || pow(tx - (winW * 0.33f), 2) + pow(ty - (winH - (winH * 0.15f)), 2) < pow((winW * 0.1f), 2) || (winW * 0.15f <= tx && tx <= winW * 0.33f) && (winH - (winH * 0.25f) <= ty && ty <= winH - (winH * 0.05f))) { 82 colchk = 1; 83 sc.colchange(); 84 Log.d("hand", "left"); 85 //↓指定領域かどうかを判定し、領域内でタッチされていたら処理を行う。 86 } else if (pow(tx - (winW - (winW * 0.33f)), 2) + pow(ty - (winH - (winH * 0.15f)), 2) < pow((winW * 0.1f), 2) || pow(tx - (winW - (winW * 0.15f)), 2) + pow(ty - (winH - (winH * 0.15f)), 2) < pow((winW * 0.1f), 2) || (winW - (winW * 0.33f) <= tx && tx <= winW - (winW * 0.15f)) && (winH - (winH * 0.25f) <= ty && ty <= winH - (winH * 0.05f))) { 87 colchk = 2; 88 sc.colchange(); 89 Log.d("hand", "right"); 90 } else { 91 sc.colreturn(); 92 Log.d("hand", "out"); 93 } 94 } 95 break;

###試したり考えたりしたこと
ログ出力を試しましたがなぜか実機だとログ自体がなぜか出ません。
手汗が原因ではないかと思いましたが、比較対象がないため分かりません。

###補足情報
前回の質問の延長ですが、本質が違うと感じたので別の質問にしました。
マルチタッチなので実機でテストしています。

###追記
・ログはコード内にありますが、
Log.d("tx,ty", "tx:" + ltx + " ty:" + lty);で座標
Log.d("hand", "left");で左がタッチされている
Log.d("hand", "right");で右がタッチされている
Log.d("hand", "leftright");で左右がタッチされている
Log.d("hand", "out");でタッチされていない
ということを表しています。
・実機はAndroid 6.0のXperia z4です。
・マジックナンバー、指定領域について
→まず、winWとwinHは画面の幅と高さを表しています。そして、txとtyはタッチされた座標です。例えば、winW0.15fは画面幅の15%の位置を使用するという意味で、winW-(winW0.33f)は画面幅の右から33%の位置を使用するという意味です。これを使用する意図は、どんな画面幅になっても対応できるようにということから使用しています。
また、領域は角丸四角形なので、四隅の半径を短い方に合わせて円と長方形、そして円で表現できるようにしています。なので、powを使っているところは円の公式を用いているということになります。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

abs123

2017/02/09 06:01

状態の判断に使用しているログと、デバッグを行っている環境について追記してください。
abs123

2017/02/09 06:15 編集

あと、コード内にコメントを追加してください。少なくとも、if文for文の前には欲しいです。
ko20vonobird

2017/02/09 08:20 編集

依頼ありがとうございます。コメントを取り敢えず最小限の解説で取り入れました。
abs123

2017/02/09 08:28

例えば、if文の場合は、「~の条件を満たしている場合、~と判断して処理を行う。」みたいな形でコメントを書きますね。
abs123

2017/02/09 08:30

どの処理でログ出力しているかなんてのは、コード読めばわかるので、ログの実物を追記してください。
ko20vonobird

2017/02/09 08:31

なるほど、わかりました。少々お待ちください。
ko20vonobird

2017/02/09 08:39 編集

文章に書きましたが、ログが出ないのです。実機の時のみの現象です。
abs123

2017/02/09 08:44

ログが出ないのは、開発を行う上で致命的な問題だとおもいます、それをまず解決すべきですね・・・
abs123

2017/02/09 08:44

コメントの方は、0.15f,0.33f,0.1f,0.05fなどの、いわゆる「マジックナンバー」について説明が欲しいです。
ko20vonobird

2017/02/09 08:47

解決手段を後で用事が終わり次第探ってまいります・・・
ko20vonobird

2017/02/09 08:48

なるほど、わかりました、少々お待ちください
ko20vonobird

2017/02/09 08:56

マジックナンバーについて、全部同じ意味なので追記にて書かせていただきました。
guest

回答2

0

条件式を見る限り、角丸四角形ではなく、
イメージ説明
こんな感じの両端が丸い四角形のようですが…
それはともかく、条件判定が冗長なので、abs123さんのものをもとにさらに手を加えます。

java

1case MotionEvent.ACTION_POINTER_UP: 2{ 3 colchk = 0; 4 fingnum = event.getPointerCount(); 5 fingid = new int[fingnum]; 6 ttx = new float[fingnum]; 7 tty = new float[fingnum]; 8 9 // タッチされている数だけ処理を行う。 10 for (int cnt = 0; cnt < fingnum; cnt++) { 11 pid = event.getPointerId(cnt); 12 index = event.findPointerIndex(pid); 13 tx = event.getX(index); 14 ty = event.getY(index); 15 16 Log.d("tx,ty", "cnt:" + cnt + " tx:" + tx + " ty:" + ty); 17 18 //繰り返し回数一回目の時処理を行う 19 if (cnt == 0){ 20 textView1.setText("tx1:" + tx + " ty1:" + ty); 21 } 22 //繰り返し回数二回目の時処理を行う 23 if (cnt == 1){ 24 textView2.setText("tx2:" + tx + " ty2:" + ty); 25 } 26 27 //左側タッチ判定,trueなら状態を左側タッチに 28 if (leftSideHitTest(tx, ty)){ 29 colchk |= 1; 30 } 31 //右側タッチ判定,trueなら状態を右側タッチに 32 if (rightSideHitTest(tx, ty)) { 33 colchk |= 2; 34 } 35 } 36 37 if (colchk == 1) { 38 sc.colchange(); 39 Log.d("hand", "left"); 40 } else if (colchk == 2) { 41 sc.colchange(); 42 Log.d("hand", "right"); 43 } else if (colchk == 3) { 44 sc.colchange(); 45 Log.d("hand", "leftright"); 46 } else { 47 sc.colreturn(); 48 Log.d("hand", "out"); 49 } 50 break; 51} 52 53/********************************************************/ 54 55/** 左側タッチ判定 */ 56boolean leftSideHitTest(int x, int y) { 57 //Math.hypot(x,y)はsqrt(x^2 + y^2)を計算する 58 if (hypot(x - winW * 0.15f, y - winH * (1 - 0.15f)) < winH * 0.1f) { 59 return true; 60 } 61 if (hypot(x - winW * 0.33f, y - winH * (1 - 0.15f)) < winH * 0.1f) { 62 return true; 63 } 64 65 // 矩形あたり判定 TODO:範囲再確認 66 if (winW * 0.15f <= x && x <= winW * 0.33f && 67 winH * (1 - 0.25f) <= y && y <= winH * (1 - 0.05f)) { 68 return true; 69 } 70 return false; 71} 72 73/** 右側タッチ判定 */ 74boolean rightSideHitTest(int x, int y) { 75 //Math.hypot(x,y)はsqrt(x^2 + y^2)を計算する 76 if (Math.hypot(x - winW * (1 - 0.33f), y - winH * (1 - 0.15f) < winH * 0.1f) { 77 return true; 78 } 79 if (hypot(x - winW * (1 - 0.15f), y - winH * (1 - 0.15f)) < winH * 0.1f) { 80 return true; 81 } 82 83 // 矩形あたり判定 TODO:範囲再確認 84 if (winW * (1 - 0.33f) <= x && x <= winW * (1 - 0.15f) && 85 winH * (1 - 0.25f) <= y && y <= winH * (1 - 0.05f)) { 86 return true; 87 } 88 return false; 89}

投稿2017/02/10 16:24

swordone

総合スコア20649

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

ベストアンサー

コードの添削を行いました。
処理自体は変わっていないと思います。(ログを吐く位置はがっつり変えてます。)

コメントでTODOと書いている周りの処理を確認してみてください。

Java

1case MotionEvent.ACTION_POINTER_UP: 2{ 3 colchk = 0; 4 fingnum = event.getPointerCount(); 5 fingid = new int[fingnum]; 6 ttx = new float[fingnum]; 7 tty = new float[fingnum]; 8 9 // タッチされている数だけ処理を行う。 10 for (int cnt = 0; cnt < fingnum; cnt++) { 11 pid = event.getPointerId(cnt); 12 index = event.findPointerIndex(pid); 13 tx = event.getX(index); 14 ty = event.getY(index); 15 16 Log.d("tx,ty", "cnt:" + cnt + " tx:" + tx + " ty:" + ty); 17 18 //繰り返し回数一回目の時処理を行う 19 if (cnt == 0){ 20 textView1.setText("tx1:" + tx + " ty1:" + ty); 21 } 22 //繰り返し回数二回目の時処理を行う 23 if (cnt == 1){ 24 textView2.setText("tx2:" + tx + " ty2:" + ty); 25 } 26 27 // どっちもまだタッチされていない 28 if (colchk == 0) { 29 //左側タッチ判定,trueなら状態を左側タッチに 30 if (leftSideHitTest(tx, ty)){ 31 colchk = 1; 32 } 33 //右側タッチ判定,trueなら状態を右側タッチに 34 if (rightSideHitTest(tx, ty)) { 35 colchk = 2; 36 } 37 continue; //TODO:判定の成否にかかわらず次の指へ(指が1本の場合はここでfor文終了) 38 } 39 40 // 左側タッチ済み 41 if (colchk == 1) { 42 //右側タッチ判定,trueなら状態を両方タッチに 43 if (rightSideHitTest(tx, ty)) { 44 colchk = 3; 45 } 46 } 47 48 // 右側タッチ済み 49 if (colchk == 2){ 50 //左側タッチ判定,trueなら状態を両方タッチに 51 if (leftSideHitTest(tx, ty)) { 52 colchk = 3; 53 } 54 } 55 } 56 57 if (colchk == 1) { 58 sc.colchange(); 59 Log.d("hand", "left"); 60 } else if (colchk == 2) { 61 sc.colchange(); 62 Log.d("hand", "right"); 63 } else if (colchk == 3) { 64 sc.colchange(); 65 Log.d("hand", "leftright"); 66 } else { 67 sc.colreturn(); 68 Log.d("hand", "out"); 69 } 70 break; 71} 72 73/********************************************************/ 74 75/** 左側タッチ判定 */ 76boolean leftSideHitTest(int x, int y) { 77 // 四隅あたり判定 TODO:のはずだけど・・・2つしかなくて大丈夫? 78 if (pow(x - (winW * 0.15f), 2) + pow(y - (winH - (winH * 0.15f)), 2) < pow((winH * 0.1f), 2)) { 79 return true; 80 } 81 if (pow(x - (winW * 0.33f), 2) + pow(y - (winH - (winH * 0.15f)), 2) < pow((winH * 0.1f), 2)) { 82 return true; 83 } 84 85 // 矩形あたり判定 TODO:範囲再確認 86 if (winW * 0.15f <= x && x <= winW * 0.33f && 87 winH - (winH * 0.25f) <= y && y <= winH - (winH * 0.05f)) { 88 return true; 89 } 90 return false; 91} 92 93/** 右側タッチ判定 */ 94boolean rightSideHitTest(int x, int y) { 95 // 四隅あたり判定 TODO:のはずだけど・・・2つしかなくて大丈夫? 96 if (pow(x - (winW - (winW * 0.33f)), 2) + pow(y - (winH - (winH * 0.15f)), 2) < pow((winH * 0.1f), 2)) { 97 return true; 98 } 99 if (pow(x - (winW - (winW * 0.15f)), 2) + pow(y - (winH - (winH * 0.15f)), 2) < pow((winH * 0.1f), 2)) { 100 return true; 101 } 102 103 // 矩形あたり判定 TODO:範囲再確認 104 if (winW - (winW * 0.33f) <= x && x <= winW - (winW * 0.15f) && 105 winH - (winH * 0.25f) <= y && y <= winH - (winH * 0.05f)) { 106 return true; 107 } 108 return false; 109}

投稿2017/02/09 10:20

abs123

総合スコア1280

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

ko20vonobird

2017/02/09 13:52 編集

回答ありがとうございます。こんな書き方もあるのだととても勉強になります。 取り敢えず、コードをabs123さんが添削してくださったように書き直して実行してみたのですが、やはり両方タッチしている時から片方を離しても両方タッチしたまま、になっていることが度々あります。 ちなみに、タッチされているかどうかを確認するのに領域の色を変えています。
ko20vonobird

2017/02/09 14:15

追加で報告なのですが、たまたまログが出たので色々なタッチを試していたところ、やはり、両方タッチしていると判定している時のログはleftrightでした。
abs123

2017/02/10 01:46

まぁ、処理自体は何も変えてないですからね・・・ 判定処理自体に問題が見つからないのであれば、判定処理を実行する部分に問題があると考えます。 今回はswitch文の中で処理を行っているので、Switch文の式と、case、case内部の処理、 のいずれかに問題が無いか調べた方がよさそうですね。
swordone

2017/02/10 01:53

今回の場合影響はないですが、条件判定の意味合いが変わっていますね。 元の条件がa || b || c && dの形なので、 「a,b,cのいずれかが成立」かつ「dが成立」だったのですが、 このコードだと「aが成立」「bが成立」「cが成立しかつdが成立」のいずれかでtrueになりますから。 結局trueになる画面上の範囲は変わっていないのですがね。
abs123

2017/02/10 02:05

改めて見直せばそうですね・・・ ご指摘ありがとうございます。
ko20vonobird

2017/02/10 06:00

abs123さん、そしてswordoneさん、コメントありがとうございます。 abs123さん、そうですね、caseはまだ大丈夫だと思うのですが(色々調べて同じだったので)、case内部の処理と特にswitch文の式をこちらでも念入りに調べてみます。 もし必要であれば、タッチイベントやその他のコードも出しますので、その際はお声掛けください。
abs123

2017/02/10 06:22

発生したアクションの種別と、 getPointerCount()で取得できる数の関係性について調べてみるといいと思います。
ko20vonobird

2017/02/10 06:40

なるほど、ログが使えないのでテキストビューで表示してやってみます。 あと、調べていてswitch文の中の式が、event.getAction() & MotionEvent.ACTION_MASKだけでなく、MotionEventCompat.getActionMasked(event)でも代用はできるようですが、変化が無かったのでswitchの式の問題の可能性は低くなりました。
ko20vonobird

2017/02/10 06:56

調べてわかったのですが、getPointerCount()で得ている指の数がACTION_POINTER_UPの時だけ実際の残った指+1になっていました。 しかし、これは単に-1すれば良いというわけではないと思うのですが、どうなのでしょうか?
abs123

2017/02/10 07:36

複数の指がタッチされている場合、 MotionEventから、どの指でどのようなアクションが発生したかを取得することが出来ます。 どのようなアクションが発生したかは、すでにgetActionMasked()で取得して利用していますね。 どの指でアクションが発生したかも、取得するためのメソッドが用意されています。調べてみてください。
ko20vonobird

2017/02/10 08:35

調べてみたのですが、いずれも離れた指からアクションが発生していました。 思いついたのですが、根本的な解決ではないですが、このどの指からアクションが発生しているかを調べてその指の処理をしないというのも一応解決策としてはありかな、とも思いました(素人の考えなので、軽く流してください)。
abs123

2017/02/10 08:46

それでいいと思いますよ? ACTION_POINTER_UPが発生した指の位置がいるか、いらないか、の話なので、 いらないのであれば使わなければいいというだけの話です。
ko20vonobird

2017/02/10 09:11

なるほど、そういえばそうですね、ある意味こっちの方が使い勝手が良いのかもしれません。 最後まで丁寧に指導していただきありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問