Нажмите на экран 5 раз за 3 секунды в Android
Я разрабатываю киоск и теперь на стороне администратора. Для того, чтобы перейти к администратору, пользователю нужно нажать на экран 5 раз всего за 3 секунды, иначе ничего не произойдет. Может ли кто-нибудь помочь мне с этим беспокойством? Заранее спасибо!
4 ответа
Пожалуйста, прочитайте комментарии в коде, это довольно просто
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;
}
}
Мое решение похоже на решение Андреса. Обратный отсчет начинается, когда вы впервые поднимаете палец, то есть когда я считаю, что нажатие закончено. Это похоже на щелчки, щелчок происходит, когда вы отпустите кнопку мыши. Через 3 секунды после первого подъема счетчик сбрасывается. Подход Андреса, с другой стороны, использует логику, основанную на помещении пальца на экран. Также используется дополнительная нить.
Моя логика одна из многих возможных. Другим разумным подходом было бы обнаружение 5 последовательных нажатий в течение 3 секунд в потоке нажатий. Рассматривать:
tap1, 2000ms, tap2, 500ms, tap3, 550ms, tap4, 10ms, tap5, 10ms, tap6.
Отвод со второго по шестой охватывает набор из пяти отводов менее чем за 3 секунды; в моем подходе это не будет обнаружено. Чтобы обнаружить это, вы можете использовать очередь 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 var count = 0
private var startMillis: Long = 0
textView.setOnTouchListener { v, event ->
if (event.action == MotionEvent.ACTION_UP) {
val currentTime = System.currentTimeMillis()
if (startMillis == 0L || currentTime - startMillis > 3000) {
startMillis = currentTime
count = 1
} else {
count++
}
if (count == 4) {
}
logd("count -- $count")
}
false
}
В Java: /questions/1534874/nazhmite-na-ekran-5-raz-za-3-sekundyi-v-android/1534890#1534890
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){
}
}
}