Я действительно не могу понять, зачем вам нужен этот жест. Но вот мое решение. Мы должны улавливать события касания, поэтому переопределяем метод onTouchEvent. Там нам нужно прочитать индекс пальцев, который на экране теперь.
Если мы получили более чем одно касание, примените правый указатель для пальца, который X координаты больше, чем «левый палец». Я не могу сказать, найду ли я правильные индексы. Поэтому я проверяю координаты индексов.
В следующем шаге мы сохраняем начальную точку и начинаем двигаться вниз. Если у нас есть 2 пальца на экране, проверьте правые и левые пальцы, остальные останутся (или вправо, как вы пожелаете).
Если мы поймаем событие, когда расстояние «вниз» больше минимального, и мы начинаем движение влево/вправо, нам нужно сохранить новую начальную точку, чтобы вычислить расстояние от нее.
И подождите, пока пользователь переместится влево/вправо с расстоянием больше мин. В конце концов проверьте успех «левым» и «правым» пальцами или просто слева (одним касанием).
Мы также должны думать о неточности (ошибки, ошибки) при перемещении. Пользователи не могут двигаться вниз или оставлять совершенно правильными, поэтому решение сильно зависит от этого параметра. Вы должны балансировать параметры диапазона и точности для удобства управления жестов.
Код не оптимизирован, показывается только основная идея. Возможно, вы найдете более мелкое решение. Извините за мой уровень Английский
public class MainMenuActivity extends AppCompatActivity {
boolean movingDownL = false;
boolean movingDownR = false;
boolean movingLeft = false;
boolean movingRight = false;
boolean movingSuccessL = false;
boolean movingSuccessR = false;
// Deviation in pixels from the route (error value)
int downInaccuracy = 30; // Down
int lnrInaccuracy = 10; // Left and Right
// Minimum distance to apply move (300 px in down and 100 to the left/right)
int downMinDistance = 300;
int lnrMinDistance = 50;
Point oldCoordsL = new Point(0, 0); // Old coordinates left
Point oldCoordsR = new Point(0, 0); // Old coordinates right
Point startPointL = new Point(0, 0);
Point startPointR = new Point(0, 0);
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main_menu);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
int pIndexL = event.findPointerIndex(event.getPointerId(0));
int pIndexR = 0;
// If we have more than 1 touch read second finger index
if(event.getPointerCount() > 1) pIndexR = event.findPointerIndex(event.getPointerId(1));
// Check if we do not mistake when read fingers id
if(event.getPointerCount() > 1 && event.getX(pIndexL) > event.getX(pIndexR)) {
int tmp = pIndexR;
pIndexR = pIndexL;
pIndexL = tmp;
}
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
movingDownL = true; // Start moving fingers
movingDownR = true;
movingSuccessL = false;
movingSuccessR = false;
// Get start point left and right if we need
if(event.getPointerCount() > 1) {
startPointR = new Point((int) event.getX(pIndexR), (int) event.getY(pIndexR));
oldCoordsR = new Point((int) event.getX(pIndexR), (int) event.getY(pIndexR));
}
startPointL = new Point((int) event.getX(pIndexL), (int) event.getY(pIndexL));
oldCoordsL = new Point((int) event.getX(pIndexL), (int) event.getY(pIndexL));
break;
case MotionEvent.ACTION_MOVE:
// Add right finger handler
if(event.getPointerCount() > 1) {
if(!movingDownR) {
// Check if we still moving to down
if(Math.abs(oldCoordsR.x - event.getX(pIndexR)) < downInaccuracy &&
oldCoordsR.y < event.getY(pIndexR)) break;
// Start moving to the right
if(Math.abs(oldCoordsR.y - event.getY(pIndexR)) < lnrInaccuracy &&
oldCoordsR.x > event.getX(pIndexR) && !movingRight) {
movingRight = true;
startPointR = new Point(new Point((int)event.getX(pIndexR), (int)event.getY(pIndexR)));
}
}else {
if (Math.abs(oldCoordsR.x - event.getX(pIndexR)) > downInaccuracy ||
oldCoordsR.y < event.getY(pIndexR)) {
movingDownR = false;
break;
} else if(findDistance(startPointR,
new Point((int)event.getX(pIndexR), (int)event.getY(pIndexR))) >= downMinDistance){
// Start moving to the left/right
movingDownR = false;
}
}
}
// Left finger handler by default even if we got only one touch
// Check if we need move to any side
if(!movingDownL) {
// Check if we still moving to down
if(Math.abs(oldCoordsL.x - event.getX(pIndexL)) < downInaccuracy &&
oldCoordsL.y < event.getY(pIndexL)) break;
// Start moving to the left
if(Math.abs(oldCoordsL.y - event.getY(pIndexL)) < lnrInaccuracy &&
oldCoordsL.x < event.getX(pIndexL) && !movingLeft) {
movingLeft = true;
startPointL = new Point(new Point((int)event.getX(pIndexL), (int)event.getY(pIndexL)));
}
}else {
if (Math.abs(oldCoordsL.x - event.getX(pIndexL)) > downInaccuracy ||
oldCoordsL.y > event.getY(pIndexL)) {
movingDownL = false;
break;
} else if(findDistance(startPointL,
new Point((int)event.getX(pIndexL), (int)event.getY(pIndexL))) >= downMinDistance){
// Start moving to the left/right
movingDownL = false;
}
}
// Left move handler
if(movingLeft) {
if (Math.abs(oldCoordsL.y - event.getY(pIndexL)) > lnrInaccuracy ||
oldCoordsL.x > event.getX(pIndexL)) {
movingLeft = false;
break;
} else if(findDistance(startPointL,
new Point((int)event.getX(pIndexL), (int)event.getY(pIndexL))) >= lnrMinDistance) {
movingLeft = false;
movingSuccessL = true; // L from left finger is OK
}
}
// Right move handler
if(movingRight) {
if (Math.abs(oldCoordsR.y - event.getY(pIndexR)) > lnrInaccuracy ||
oldCoordsR.x < event.getX(pIndexR)) {
movingRight = false;
break;
} else if(findDistance(startPointR,
new Point((int)event.getX(pIndexR), (int)event.getY(pIndexR))) >= lnrMinDistance) {
movingRight = false;
movingSuccessR = true; // L from right finger is OK
}
}
if(movingSuccessL && movingSuccessR) {
Toast.makeText(this, "Yeah, it's look like double L", Toast.LENGTH_SHORT).show();
} else if(movingSuccessL) Toast.makeText(this, "Yeah, it's look like L", Toast.LENGTH_SHORT).show();
oldCoordsL = new Point((int)event.getX(pIndexL), (int)event.getY(pIndexL));
oldCoordsR = new Point((int)event.getX(pIndexR), (int)event.getY(pIndexR));
break;
case MotionEvent.ACTION_UP:
movingDownL = false;
movingDownR = false;
movingLeft = false;
movingRight = false;
break;
default:
return false;
}
return true;
}
private double findDistance(Point p1, Point p2) {
return Math.sqrt(Math.pow(p1.x - p2.x, 2) + Math.pow(p1.y - p2.y, 2));
}
}
У меня есть сообщение «Да, это похоже на двойной L» все время, когда я касаюсь экрана. –
Странно. Я тестировал приложение на двух устройствах, все работает нормально. Вы правильно скопировали мой код? Или что-то изменить?Он не может делать сообщения с сенсорным управлением, потому что moveSuccessL и movingSuccessR всегда ложны. –
Теперь он работает извините. Проблема в том, что если я добавлю отладку в качестве примера, я вижу разное время моего отладки, когда я делаю двойной L. Это большая проблема, потому что после этого я должен вызвать фрагмент, а приложение вызывает разное время этого фрагмента. Как я могу позвонить только 1 раз? –