Используя тот же onTouchEvent в различные активности

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

теперь для этого я создал реализацию 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);
    }
}

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

5 ответов


вы можете использовать решение @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();
    }
}

в своем MainActivity создать новый экземпляр 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, the View на котором вы хотите обнаружить двойной L на View установите этот слушатель на этом View.

view.setOnTouchListener(imp);

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

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

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


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

public abstract class BaseActivity extends AppCompatActivity {

@Override
public boolean onTouchEvent(MotionEvent event) {
    // Your implementation.
}

}

а затем ваша основная активность:

public class MainActivity extends BaseActivity {

}

вы можете создать суперкласс, который расширяет activity и реализует ваш метод 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
}

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

Я проверил ваш слушатель с минимальными изменениями, и я получил журналы. Однажды я получил двойной L 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 listener, а затем использовать такой макет, как корневой класс для ваших представлений и действий. Дай мне знать, если это поможет.