【问题标题】:Using the same onTouchEvent in various Activity在各种Activity中使用相同的onTouchEvent
【发布时间】:2017-02-14 17:22:40
【问题描述】:

我在我的MainActivity.class 中使用onTouchEvent。它工作正常:如果用户用手指制作双 L,我称之为片段。 我想在另一个Activity 中使用这个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);
    }
}

问题是我从不输入我的日志。它根本不起作用......

【问题讨论】:

  • 谁得到了赏金?
  • 真的很抱歉......我等了这么久,所以赏金已经过期......我真的很抱歉:(

标签: android ontouchlistener


【解决方案1】:

您只需稍作修改即可使用@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 上的双L 将此侦听器设置在View 上。

view.setOnTouchListener(imp);

我假设您想在主布局上检测 double L。为此,您可以这样做

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

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

【讨论】:

  • 谢谢,但是当我触摸屏幕时,它永远不会通过 TouchListenerImpl 的 onTouch。
  • @Jéwôm' 您需要在 MainActivity 中覆盖 onTouch 并在其中调用 imp.onTouch(v, event)
  • 感谢您的回复,我编辑了我的答案。但它仍然无法正常工作。请看我的代码:)
  • 所以即使debugTouch: inTouch 也没有显示在日志中?
  • 这是因为您没有在任何View 上设置监听器。
【解决方案2】:

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

public abstract class BaseActivity extends AppCompatActivity {

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

}

然后是你的 MainActivity:

public class MainActivity extends BaseActivity {

}

【讨论】:

  • 谢谢,但我如何声明我的 frameLayoutAdmin 和我的 img_close ? (我用它来改变可见性)
  • 如何将片段更改为 DialogFragment?这样您就不需要依赖容器来添加片段。
【解决方案3】:

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

【讨论】:

  • 我已经用这个方法更新了我的问题,但是还是不行。
【解决方案4】:

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

【讨论】:

  • 谢谢,但我如何声明我的 frameLayoutAdmin 和我的 img_close ? (我用它来改变可见性)
  • 我已经用这个方法更新了我的问题,但还是不行。
【解决方案5】:

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

我以最小的更改测试了您的侦听器,并获得了日志。我有一次双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 触摸侦听器的框架布局子类,然后将此类布局用作视图和活动的根类。让我知道这是否有帮助。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-12-06
    • 2017-09-07
    • 1970-01-01
    • 1970-01-01
    • 2017-01-24
    • 2021-05-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多