Android:使用onTouch,onClick和onLongClick Together

时间:2014-05-04 05:26:54

标签: android ontouchlistener

在我的应用中,我必须在布局的任何位置移动视图。所以我使用了onTouchListener。在onClickonLongClick,我必须执行其他一些任务。我能够移动视图。但是,听众彼此冲突。当我移动视图时,有时会调用onClickonLongClick。并且,当用户移动视图时,我不希望它们被调用。我怎么能避免这个?我已经提到这个link来交叉检查我的代码。但是,找不到错误。以下是我的代码:

OnTouch of view

broItemView.setOnTouchListener(new View.OnTouchListener() {
        private int deltaX;
        private int deltaY;
        private float initialTouchX;
        private float initialTouchY;
        private boolean isMoved;
        private int lastTouchX;
        private int lastTouchY;

        @Override
        public boolean onTouch(final View v, final MotionEvent event) {
            ViewGroup vg = (ViewGroup) v.getParent();
            draggedViewIndex = vg.indexOfChild(v);
            initialTouchX = event.getRawX();
            initialTouchY = event.getRawY();

            boolean result = v.onTouchEvent(event);
            switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN: {
                isMoved = false;
                FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) v
                        .getLayoutParams();

                deltaX = (int) initialTouchX - params.leftMargin;
                deltaY = (int) initialTouchY - params.topMargin;
                new Handler().postDelayed(new Runnable() {

                    @Override
                    public void run() {
                        runOnUiThread(new Runnable() {

                            @Override
                            public void run() {
                                if (!isMoved
                                        && event.getAction() != MotionEvent.ACTION_UP) {
                                    ViewGroup vg = (ViewGroup) v
                                            .getParent();
                                    draggedViewIndex = vg.indexOfChild(v);

                                    ClipData data = ClipData.newPlainText(
                                            "", "");
                                    DragShadowBuilder shadowBuilder = new View.DragShadowBuilder(
                                            v);
                                    v.startDrag(data, shadowBuilder, v, 0);
                                    v.setVisibility(View.INVISIBLE);

                                    Animation slideUp = AnimationUtils
                                            .loadAnimation(
                                                    WMMBFragmentContainerActivity.this,
                                                    R.anim.slide_up_dialog);
                                    crossImage.setVisibility(View.VISIBLE);
                                    crossImage.startAnimation(slideUp);
                                }
                            }
                        });
                    }
                }, 1000);
                break;
            }

            case MotionEvent.ACTION_MOVE: {
                Log.e(TAG, "ACTION_MOVE");
                FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) v
                        .getLayoutParams();
                params.leftMargin = (int) initialTouchX - deltaX;
                params.topMargin = (int) initialTouchY - deltaY;
                v.setLayoutParams(params);

                isMoved = true;

                break;
            }
            case MotionEvent.ACTION_UP: {
                Log.e(TAG, "ACTION_UP");
                initialTouchX = 0;
                initialTouchY = 0;
                deltaX = 0;
                deltaY = 0;
                if (!isMoved) {
                    Log.e(TAG, "ACTION_UP if");
                    showRunningTransactionFragment(mBroList
                            .get(draggedViewIndex));
                } else {
                    Log.e(TAG, "ACTION_UP else");
                    isMoved = false;
                }
                break;
            }
            default:
                Log.e(TAG, "default");
                return result;
            }
            relBroCircle.invalidate();
            Log.e(TAG, "defaultqqq ");
            return true;
        }
    });

更新1:

所以,根据Viswanath的建议,我修改了我的代码。但是,我仍面临着问题。当我在onTouch移动视图时,有时候,我在处理程序中编写的代码会被执行。我不希望在用户移动视图时执行此操作。我希望像Facebook Messenger ChatHeads那样顺利。当用户想要执行它们时,只调用它们onClick or onLongClick。我没弄到错误的地方。

更新2:

现在,我删除了多个侦听器并尝试在onTouch中执行所有我想要的操作。它的工作除了一个问题。即使我点击了视图(直到现在我还没有移动视图),ACTION_MOVE被调用,因此isMoved变为 true 。因此,在这种情况下,if block中的ACTION_UP内的代码永远不会被执行。为了弄清楚我是否做错了什么,我创建了一个虚拟项目,选择了textview并添加了onTouchListeneronClickListener。然后,执行单击操作。还有,我发现在ACTION_MOVE之前先调用onClick,然后执行onClick内的代码。那么,我怎样才能获得onClick效果呢?我更新了我的代码。

2 个答案:

答案 0 :(得分:1)

当您使用onTouch时,可能会发生这种情况。以下是onclick

的解决方法

通常我们会手动设置一个像

这样的标志

boolean isMoved;

case MotionEvent.ACTION_DOWN: 
    isMoved = false;

case MotionEvent.ACTION_MOVE:
    isMoved = true;

case MotionEvent.ACTION_UP:
    if(!isMoved)
       YourOnClick();

答案 1 :(得分:1)

最后,我设法实现了我想要的目标。该解决方案基于上面提出的Viswanath's想法。这是我的代码:

broItemView.setOnTouchListener(new View.OnTouchListener() {
        private int deltaX;
        private int deltaY;
        private float initialTouchX;
        private float initialTouchY;
        private boolean isMoved;
        private int lastTouchX;
        private int lastTouchY;

        @Override
        public boolean onTouch(final View v, final MotionEvent event) {
            ViewGroup vg = (ViewGroup) v.getParent();
            draggedViewIndex = vg.indexOfChild(v);
            initialTouchX = event.getRawX();
            initialTouchY = event.getRawY();
            boolean result = v.onTouchEvent(event);
            switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN: {
                isMoved = false;
                FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) v
                        .getLayoutParams();

                deltaX = (int) initialTouchX - params.leftMargin;
                deltaY = (int) initialTouchY - params.topMargin;

                lastTouchX = (int) initialTouchX;
                lastTouchY = (int) initialTouchY;
                Log.e(TAG, "ACTION_DOWN lasttouchX: " + lastTouchX);
                Log.e(TAG, "ACTION_DOWN lasttouchY: " + lastTouchY);
                new Handler().postDelayed(new Runnable() {

                    @Override
                    public void run() {
                        runOnUiThread(new Runnable() {

                            @Override
                            public void run() {
                                if (!isMoved
                                        && event.getAction() != MotionEvent.ACTION_UP) {
                                    //perform LongClickOperation
                                }
                            }
                        });
                    }
                }, 1000);
                break;
            }

            case MotionEvent.ACTION_MOVE: {
                FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) v
                        .getLayoutParams();

                params.leftMargin = (int) initialTouchX - deltaX;
                params.topMargin = (int) initialTouchY - deltaY;

                v.setLayoutParams(params);

                break;
            }
            case MotionEvent.ACTION_UP: {

                if ((lastTouchX == (int) initialTouchX)
                        && (lastTouchY == (int) initialTouchY)) {
                    isMoved = false;
                } else if ((lastTouchX > (int) initialTouchX)) {
                    if (((lastTouchX - (int) initialTouchX) <= 10)) {
                        isMoved = false;
                    } else {
                        isMoved = true;
                    }
                } else if ((lastTouchX < (int) initialTouchX)) {
                    if ((((int) initialTouchX - lastTouchX) <= 10)) {
                        isMoved = false;
                    } else {
                        isMoved = true;
                    }
                } else if ((lastTouchY > (int) initialTouchY)) {
                    if (((lastTouchY - (int) initialTouchY) <= 10)) {
                        isMoved = false;
                    } else {
                        isMoved = true;
                    }
                } else if ((lastTouchY < (int) initialTouchY)) {
                    if ((((int) initialTouchY - lastTouchY) <= 10)) {
                        isMoved = false;
                    } else {
                        isMoved = true;
                    }
                } else {
                    isMoved = true;
                }

                if (!isMoved) {
                    //perform onClick operation
                } else {
                    isMoved = false;
                }
                initialTouchX = 0;
                initialTouchY = 0;
                deltaX = 0;
                deltaY = 0;
                break;
            }
            default:
                return result;
            }
            relBroCircle.invalidate();
            return true;
        }
    });

ACTION_UP中,我不得不添加额外的检查以确定视图是否实际移动,因为我发现即使用户只是点击了视图,ACTION_MOVE仍然会被调用。我已经单独检查了这个,因为我已经提到了我的帖子的 Update 2 。而且,当我在10英寸平板电脑上测试我的代码时,我的onclick代码从未执行过。所以,为了避免这个问题,我不得不编写那些代码。但是,我认为它不是优雅的解决方案,似乎是我的黑客。如果有人有更好的解决方案,那么请告知我,以便我可以更新我的代码。