私はキオスクを開発していて、現在は管理者側にいます。管理者に移動するには、ユーザーは画面を3秒で5回タップするする必要があります。そうしないと、何も起こりません。
コード内のコメントを読んでください、それは非常に簡単です
import Android.app.Activity;
import Android.os.Bundle;
import Android.view.MotionEvent;
public class MainActivity extends Activity {
private int count = 0;
private long startMillis=0;
//detect any touch event in the screen (instead of an specific view)
@Override
public boolean onTouchEvent(MotionEvent event) {
int eventaction = event.getAction();
if (eventaction == MotionEvent.ACTION_UP) {
//get system current milliseconds
long time= System.currentTimeMillis();
//if it is the first time, or if it has been more than 3 seconds since the first tap ( so it is like a new try), we reset everything
if (startMillis==0 || (time-startMillis> 3000) ) {
startMillis=time;
count=1;
}
//it is not the first, and it has been less than 3 seconds since the first
else{ // time-startMillis< 3000
count++;
}
if (count==5) {
//do whatever you need
}
return true;
}
return false;
}
}
私の解決策は Andres's に似ています。初めて指を離したとき、つまりタップが終了したと思ったときにカウントダウンが始まります。これはクリックに似ており、マウスボタンを離すとクリックが発生します。最初のリフトから3秒後、カウンターがリセットされます。反対側のAndresのアプローチは、画面上に指を置くことに基づくロジックを使用します。また、追加のスレッドを使用します。
私の論理は、考えられる多くの論理の1つです。別の合理的なアプローチは、タップのストリームで3秒以内に5つの連続したタップを検出することです。考えてみましょう:
tap1、2000ms、tap2、500ms、tap3、550ms、tap4、10ms、tap5、10ms、tap6。
2番目から6番目のタップには、3秒未満の5つのタップのセットが含まれます。私のアプローチでは、これは検出されません。これを検出するには、FIFO固定サイズ5のキューを使用し、最後の5つのタイムスタンプを記憶します。このシーケンスは増加しています。新しいタップを受信したら、1)少なくとも存在するかどうかを確認します。 5回のタップが発生し、2)最も古いタイムスタンプが3秒以上経過していない。
とにかく、最初のロジックに戻って、このコードをActivity
に配置します。
private int mCounter = 0;
private Handler mHandler = new Handler();
private Runnable mResetCounter = new Runnable() {
@Override
public void run() {
mCounter = 0;
}
};
@Override
public boolean onTouchEvent(MotionEvent event) {
switch(MotionEventCompat.getActionMasked(event)) {
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
if (mCounter == 0)
mHandler.postDelayed(mResetCounter, 3000);
mCounter++;
if (mCounter == 5){
mHandler.removeCallbacks(mResetCounter);
mCounter = 0;
Toast.makeText(this, "Five taps in three seconds", Toast.LENGTH_SHORT).show();
}
return false;
default :
return super.onTouchEvent(event);
}
}
注:構成の変更についても、状態を保持する必要がある可能性があります。数学者が言うように、私はそれを読者への演習としてさせます
アクティビティonTouchEvent()
メソッドをオーバーライドして、画面からタッチイベントを受信します。ユーザーが画面をタップするたびに、変数をインクリメントし、初めてタッチした場合はRunnableを3秒で延期し、3秒が経過すると、タッチイベントはクリアされ、何も起こりません。スレッドは、タッチイベント番号が5以上であるかどうかをチェックします。これらが発生した場合、3秒前に変数がクリアされず、if(touchEvent >= 5)
条件が真になります。私はそれをテストしていません!しかし、それは完全に非同期です:)
// Touch events on screen
@Override
public boolean onTouchEvent(MotionEvent event) {
// User pressed the screen
if(event.getAction() == MotionEvent.ACTION_DOWN){
if(touchEvent == 0) myView.post(mRunnable, 3000); // Execute a Runnable in 3 seconds
++touchEvent;
}
return false;
}
Runnable mRunnable = new Runnable(){
@Override
public void run() {
touchEvent = 0; // 3 seconds passed, clear touch events
}
}
Thread mThread = new Thread(new Runnable(){
@Override
public void run(){
if(touchEvent >= 5){
// Touched 5 times in 3 seconds or less, CARE this is not UI Thread!
}
}
});
mThread.start();
private int touchSequenceCount = 0;
private Handler handlerTouchSequenceDetection;
private Runnable runnableTouchSequenceDetection;
public void setupTouchSequenceDetection(final View view){
try {
view.setOnTouchListener(new View.OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
int action = event.getAction();
switch (action) {
case MotionEvent.ACTION_DOWN:
Log.d("setupTouchSequenceDetection", "touchCount: " + (touchSequenceCount+1));
if(touchSequenceCount == 0){
handlerTouchSequenceDetection.postDelayed(runnableTouchSequenceDetection, 2000);
}else{
if(touchSequenceCount == 2){
new AlertDialog.Builder(Activity_CheckIn_SelectLanguage.this)
.setMessage("warning message here")
.setCancelable(true)
.setPositiveButton("yes", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
resetTouchSequenceDetection(true);
}
})
.setNegativeButton("no", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
resetTouchSequenceDetection(true);
}
}).setOnCancelListener(new DialogInterface.OnCancelListener() {
@Override
public void onCancel(DialogInterface dialog) {
resetTouchSequenceDetection(true);
}
})
.show();
}
}
touchSequenceCount = touchSequenceCount + 1;
break;
}
return false;
}
});
handlerTouchSequenceDetection = new Handler();
runnableTouchSequenceDetection = new Runnable() {
public void run() {
Log.d("setupTouchSequenceDetection", "reset touchCount: " + (touchSequenceCount+1));
resetTouchSequenceDetection(false);
}
};
}
catch(Exception ex){
if(ex != null){
}
}
}
private void resetTouchSequenceDetection(boolean removeRunnable){
try{
if(removeRunnable){
handlerTouchSequenceDetection.removeCallbacks(runnableTouchSequenceDetection);
}
touchSequenceCount = 0;
}
catch(Exception ex){
if(ex != null){
}
}
}