在各种Activity中使用相同的onTouchEvent

时间:2017-02-14 17:22:41

标签: android ontouchlistener

我在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));
    }
}

在我的Activity中,我将这个工具称为:

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 个答案:

答案 0 :(得分:6)

您可以使用@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中,创建TouchListenerImplsetCallback的新实例

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上要View检测View上的双L ,在view.setOnTouchListener(imp); 上设置此侦听器。

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

我假设您要检测主布局上的 double L 。为此你可以做到

<script type="text/javascript" src="bower_components/angular/angular.min.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-bootstrap/2.5.0/ui-bootstrap.min.js"></script>

我希望这能解决你的问题。

答案 1 :(得分:2)

您可以创建一个超类Activity,在那里覆盖onTouchEvent并从中扩展。 像这样:

public abstract class BaseActivity extends AppCompatActivity {

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

}

然后是您的MainActivity:

public class MainActivity extends BaseActivity {

}

答案 2 :(得分:1)

您可以创建一个扩展活动的超类并实现onTouchEvent方法,并且在您要使用onTouchEvent方法的任何活动中扩展您的超类。 MainActivity也必须扩展它。或者只是在要使用onTouchEvent方法的其他活动中扩展MainActivity。

答案 3 :(得分:1)

将所有代码与字段变量一起复制到实现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
}

答案 4 :(得分:0)

您需要在活动的根目录中设置侦听器,并且需要注意视图层次结构。触摸事件可以被层次结构中的其他视图使用,这可能是您没有获取任何日志的原因。

我用最少的更改测试了你的听众,我得到了日志。我有一次双L触摸。

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监听器的框架布局子类,然后使用这样的布局作为视图和活动的根类。如果这有帮助,请告诉我。