【问题标题】:How to get a continuous Touch Event?如何获得连续的触摸事件?
【发布时间】:2010-03-29 16:21:19
【问题描述】:

我的类扩展了 View,我需要在它上面获取连续的触摸事件。

如果我使用:

public boolean onTouchEvent(MotionEvent me) {

    if(me.getAction()==MotionEvent.ACTION_DOWN) {
        myAction();
    }
    return true;
}

...触摸事件被捕获一次。

如果我需要在不移动手指的情况下进行连续触摸怎么办? 请告诉我我不需要使用线程或计时器。我的应用已经太重了。

谢谢。

【问题讨论】:

    标签: android events touch continuous


    【解决方案1】:

    使用if(me.getAction() == MotionEvent.ACTION_MOVE)。让手指 100% 完全静止在屏幕上是不可能的,因此每次手指移动时都会调用 Action_Move,即使它只有一两个像素。

    您也可以收听me.getAction() == MotionEvent.ACTION_UP - 在此之前,用户必须仍将手指放在屏幕上。

    【讨论】:

    • 正确,我希望解决方案在 ACTION_DOWN 上设置一个标志并使用它直到 ACTION_UP 上的标志设置为 false
    • 我看到到处都提到了这一点,但对我来说似乎并非如此。如果我触摸并保持不动,我不会收到 ACTION_MOVE 事件。 ACTION_MOVE 似乎只有在我以一种或另一种方式倾斜手指时才会触发。会不会是我手机上的设置降低了它的敏感度?
    • @clusterflux 如果您依赖 ACTION_MOVE 连续触发,即使手指保持不动,您也可能做错了什么。我(非常老!)答案的后半部分,例如在 down 中设置一个标志并在 up 中清除它,这确实是正确的方法。
    • @SteveHaley 感谢您的帮助。我有一个后续问题。我有一个在 ACTION_DOWN 上调用的函数。我希望它被连续调用,直到 ACTION_UP 发生。我已尝试按照您的建议使用标志,但我遇到的问题是我正在使用 while(!up_flag) 循环在发生 ACTION_DOWN 时重复调用该函数。但是,一旦我进入 while() 循环,我就无法再感知到触摸事件,因此永远不会感知到 ACTION_UP,因此不会更改标志。我陷入了一个连续的while循环。对替代方法有什么建议吗?
    • 很好,但是...不能在模拟器上工作。与手指不同,鼠标可以保持静止。
    【解决方案2】:

    您需要为元素设置此属性 机器人:焦点=“真” 安卓:可点击=“真” 如果没有,就产生向下的动作。

    【讨论】:

      【解决方案3】:

      她是简单的代码 sn-p,它显示了如何处理持续触摸事件。当您触摸设备并按住触摸并移动取景器时,会执行“触摸移动”操作。

      @Override
      public boolean onTouchEvent(MotionEvent event) {
          float x = event.getX();
          float y = event.getY();
          if(isTsunami){
          switch (event.getAction()) {
              case MotionEvent.ACTION_DOWN:
                  // Write your code to perform an action on down
                  break;
              case MotionEvent.ACTION_MOVE:
                  // Write your code to perform an action on contineus touch move
                  break;
              case MotionEvent.ACTION_UP:
                  // Write your code to perform an action on touch up
                  break;
          }
          }
          return true;
      }
      

      【讨论】:

        【解决方案4】:

        试试这个。它对我有用:

        public static OnTouchListener loadContainerOnTouchListener() {
            OnTouchListener listener = new OnTouchListener(){
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                LinearLayout layout = (LinearLayout)v;
                for(int i =0; i< layout.getChildCount(); i++)
                {
                    View view = layout.getChildAt(i);
                    Rect outRect = new Rect(view.getLeft(), view.getTop(), view.getRight(), view.getBottom());
                    if(outRect.contains((int)event.getX(), (int)event.getY()))
                    {
                        Log.d(this.getClass().getName(), String.format("Over view.id[%d]", view.getId()));
                    }
                }
        
            }
        

        请记住:您将设置的侦听器必须是容器布局(网格、相对、线性)。

        LinearLayout layout = findViewById(R.id.yourlayoutid);
        layout.setOnTouchListener(HelperClass.loadContainerOnTouchListener());
        

        【讨论】:

          【解决方案5】:

          这可能会有所帮助,

          requestDisallowInterceptTouchEvent(true);
          

          在父视图上,像这样 -

                  @Override
                  public boolean onTouch(View view, MotionEvent motionEvent) {
                      view.getParent().requestDisallowInterceptTouchEvent(true);
                      switch(motionEvent.getAction()){
                      }
          
                      return false; 
          
                   }
          

          【讨论】:

            【解决方案6】:

            我正在制作一款游戏,其中包含用作拇指控件的自定义视图。 . .这就是我所做的

            float x = 0, y = 0;
            
            @Override
            public boolean onTouchEvent(MotionEvent event) {
                x = event.getX();
                y = event.getY();
            
                // handle touch events with 
                switch( event.getActionMasked() ) {
                    case MotionEvent.ACTION_DOWN :
                        if(cont)
                        {
                            // remove any previous callbacks
                            removeCallbacks(contin);
            
                            // post new runnable
                            postDelayed(contin, 10);
                        }
                        invalidate();
                        return true;
                    case MotionEvent.ACTION_MOVE :
                        if(!cont && thumbing != null)
                        {
                            //  do non-continuous operations here
                        }
                        invalidate();       
                        return true;
                    case MotionEvent.ACTION_UP :
            
                        // set runnable condition to false
                        x = 0;
            
                        // remove the callbacks to the thread
                        removeCallbacks(contin);
                        invalidate();
                        return true;
                    default :
                        return super.onTouchEvent(event);
                }
            }
            
            public boolean cont = false;
            
            // sets input to continuous
            public void set_continuous(boolean b) { cont = b; }
            
            
            public Runnable contin = new Runnable()
            {
            
                @Override
                public void run() {
                    if(x != 0)
                    {
                        //  do continuous operations here
                        postDelayed(this, 10);
                    }
                }
            
            };
            

            但是,请确保在调用此视图的主要活动中通过 onPause 方法手动删除回调,如下所示

            @Override
            protected void onPause() {
                if(left.cont) left.removeCallbacks(left.contin);
                if(right.cont) right.removeCallbacks(left.contin); 
                super.onPause();
            }
            

            这样,如果您暂停并返回,触摸事件不会被处理两次,并且视图不会产生线程开销。

            ** 在带有硬件加速的三星 Galaxy S3 上测试 **

            【讨论】:

              【解决方案7】:

              所有这些答案都是部分正确的,但它们并没有以正确的方式解决问题。

              首先,对于所有决定跟踪事件何时为 ACTION_MOVE 的人。好吧,那只能猜测什么时候?当用户移动他的手指时,如果您决定实现自定义拇指控件也可以,但对于普通的自定义按钮则不然。

              其次,在 ACTION_DOWN 中使用标志并在 ACTION_UP 中检查它似乎是执行此操作的逻辑方法,但是当 Clusterfux 发现您是否实现 while(!up_flag) 逻辑时,您会陷入困境;)

              所以这里提到了正确的方法:

              Continuous "Action_DOWN" in Android

              请记住,如果您要在连续按下期间编写的逻辑必须以某种方式修改 UI,那么在所有其他情况下,您必须从主线程执行此操作,最好使用另一个线程。

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多