Использование одного и того же onTouchEvent в различных действиях

Я использую onTouchEvent для своего MainActivity.class . Он работает нормально: если пользователь делает двойной L пальцами, я называю фрагмент. Я хотел бы использовать этот onTouchEvent в другом onTouchEvent но я думаю, что это грязно, если я onTouchEvent весь свой код.

Теперь для этого я создал инструмент TouchListenerImpl для этого:

 class TouchListenerImpl implements View.OnTouchListener { private boolean movingDownL, movingDownR, movingLeft, movingRight, movingSuccessL, movingSuccessR = false; private Point oldCoordsL, oldCoordsR, startPointL, startPointR = new Point(0, 0); private boolean admin_touch = false; private OnLTouch callback; void setCallback(OnLTouch c) { callback = c; } interface OnLTouch { void lTouchSuccess(); } @Override public boolean onTouch(View v, MotionEvent event) { Log.d("debugTouch", "onTouch"); int pIndexL = event.findPointerIndex(event.getPointerId(0)); int pIndexR = 0; if(event.getPointerCount() > 1) pIndexR = event.findPointerIndex(event.getPointerId(1)); 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; movingDownR = true; movingSuccessL = false; movingSuccessR = false; 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: int downMinDistance = 300; int lnrInaccuracy = 10; int downInaccuracy = 30; if(event.getPointerCount() > 1) { if(!movingDownR) { if(Math.abs(oldCoordsR.x - event.getX(pIndexR)) < downInaccuracy && oldCoordsR.y < event.getY(pIndexR)) break; 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){ movingDownR = false; } } } if(!movingDownL) { if(Math.abs(oldCoordsL.x - event.getX(pIndexL)) < downInaccuracy && oldCoordsL.y < event.getY(pIndexL)) break; 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){ movingDownL = false; } } int lnrMinDistance = 50; 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; } } 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; } } if(movingSuccessL && movingSuccessR) { if (!admin_touch) { admin_touch = true; if (callback != null) callback.lTouchSuccess(); } } 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)); } } 

В моей деятельности я называю реализацию следующим образом:

 public class MainActivity extends AppCompatActivity implements View.OnTouchListener { TouchListenerImpl imp = new TouchListenerImpl(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); imp.setCallback(new TouchListenerImpl.OnLTouch() { @Override public void lTouchSuccess() { Log.d("debugTouch", "WORKING !"); } }); } @Override public boolean onTouch(View v, MotionEvent event) { Log.d("debugTouch", "onTouch"); return imp.onTouch(v, event); } } 

Проблема в том, что я никогда не вхожу в свои журналы. Это не работает вообще …

Solutions Collecting From Web of "Использование одного и того же onTouchEvent в различных действиях"

Вы можете использовать решение @DrilonBlakqori с небольшими изменениями.

Создайте отдельный класс, содержащий общий код, но используйте обратный вызов, чтобы сделать View видимым.

 class TouchListenerImpl implements OnTouchListener { private OnLTouch callback; @Override public boolean onTouch(View v, MotionEvent event) { // all your code ... if (callback != null) callback.lTouchSuccess(); ... } void setCallback(OnLTouch c) { callback = c; } interface OnLTouch { void lTouchSuccess(); } } 

Создайте новый экземпляр TouchListenerImpl и setCallback в TouchListenerImpl setCallback

 TouchListenerImpl imp = new TouchListenerImpl(); imp.setCallback(new OnLTouch() { public void lTouchSuccess() { frameLayoutAdmin.setVisibility(View.VISIBLE); getSupportFragmentManager().beginTransaction() .replace(R.id.framelayout_admin,new AdminLoginFragment()) .commit(); img_close.setVisibility(View.VISIBLE); } }); 

И в MainActivity , View в котором вы хотите обнаружить двойной L в этом View задает этот прослушиватель в этом View .

 view.setOnTouchListener(imp); 

Я предполагаю, что вы хотите обнаружить двойной L на главном макете. Для этого вы можете сделать

 findViewById(R.id.mylayout).setOnTouchListener(imp); 

Надеюсь, это решит вашу проблему.

Вы можете создать суперкласс Activity, переопределить onTouchEvent и перейти от него. Что-то вроде этого:

 public abstract class BaseActivity extends AppCompatActivity { @Override public boolean onTouchEvent(MotionEvent event) { // Your implementation. } } 

И затем ваша MainActivity:

 public class MainActivity extends BaseActivity { } 

Вы можете создать суперкласс, который расширяет активность и реализует ваш метод onTouchEvent, и в любом действии, которое вы хотите использовать методом onTouchEvent, расширяет ваш суперкласс. MainActivity также должен был расширить его. Или просто расширьте MainActivity в других действиях, где вы хотите использовать свой метод onTouchEvent.

Скопируйте весь свой код вместе с переменными поля в класс, который реализует OnTouchListener . Затем просто передайте новый TouchListenerImpl всякий раз, когда вам это нужно.

 class TouchListenerImpl implements OnTouchListener { // your field variables @Override public boolean onTouch(View v, MotionEvent event) { // all your code return false; } // getters for the variables that you need } 

Вам нужно установить слушателя в корневой каталог активности, и вам нужно обратить внимание на свою иерархию представлений. События Touch могут быть использованы другими представлениями в иерархии, что может быть причиной того, что вы не получаете никаких журналов.

Я проверил вашего слушателя с минимальными изменениями, и я получил журналы. Однажды я получил двойное касание.

 public class TouchListenerImpl implements View.OnTouchListener { private boolean movingDownL, movingDownR, movingLeft, movingRight, movingSuccessL, movingSuccessR = false; private Point oldCoordsL, oldCoordsR, startPointL, startPointR = new Point(0, 0); private boolean admin_touch = false; private OnLTouch callback; public TouchListenerImpl(OnLTouch callback){ setCallback(callback); } void setCallback(OnLTouch c) { callback = c; } public interface OnLTouch { void lTouchSuccess(); } @Override public boolean onTouch(View v, MotionEvent event) { Log.d("debugTouch", "onTouch"); int pIndexL = event.findPointerIndex(event.getPointerId(0)); int pIndexR = 0; if(event.getPointerCount() > 1) pIndexR = event.findPointerIndex(event.getPointerId(1)); 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; movingDownR = true; movingSuccessL = false; movingSuccessR = false; 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: int downMinDistance = 300; int lnrInaccuracy = 10; int downInaccuracy = 30; if(event.getPointerCount() > 1) { if(!movingDownR) { if(Math.abs(oldCoordsR.x - event.getX(pIndexR)) < downInaccuracy && oldCoordsR.y < event.getY(pIndexR)) break; 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){ movingDownR = false; } } } if(!movingDownL) { if(Math.abs(oldCoordsL.x - event.getX(pIndexL)) < downInaccuracy && oldCoordsL.y < event.getY(pIndexL)) break; 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){ movingDownL = false; } } int lnrMinDistance = 50; 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; } } 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; } } if(movingSuccessL && movingSuccessR) { if (!admin_touch) { admin_touch = true; if (callback != null) callback.lTouchSuccess(); } } 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)); } } 

И использование этого:

 public class SplashActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_splash); RelativeLayout layout = (RelativeLayout) findViewById(R.id.activity_splash); layout.setOnTouchListener(new TouchListenerImpl(new TouchListenerImpl.OnLTouch() { @Override public void lTouchSuccess() { Toast.makeText(getThis(), "L touched!", Toast.LENGTH_SHORT).show(); } })); } public AppCompatActivity getThis(){ return this; } } 

Как я уже говорил, причина, по которой вы не получаете никаких журналов, может быть вашей иерархией. Убедитесь, что ваши события касания не используются другими видами сверху. Чтобы быть в самой безопасной, вы должны использовать FrameLayout в качестве корневого элемента для такого поведения и логическую переменную, которая позволяет вам решить, должен ли использоваться L-слушатель или нет.

Проверьте это для дальнейшей справки: https://github.com/fcopardo/EnhancedMapView. Если вы проверите файл EnhancedMapView, вы найдете следующее:

  public void setOnEnhancedCameraChangeListener(OnEnhancedCameraChangeListener listener){ if(map!=null){ map.setOnCameraChangeListener(camera -> { if(!isContentTouched() && !isCaptureTouches()){ listener.onCameraChange(camera); } }); } } 

Это очень похоже на то, что вы делаете. Я предлагаю вам использовать аналогичный подход, подкласс фрейма, реализующий ваш L-touch-слушатель, а затем используйте такой макет, как корневой класс для ваших представлений и действий. Позвольте мне знать, если это помогает.