【问题标题】:how to use both Ontouch and Onclick for an ImageButton?如何将 Ontouch 和 Onclick 用于 ImageButton?
【发布时间】:2013-11-01 13:20:18
【问题描述】:

在我的应用程序中,我希望发生两件事。

  1. 当我触摸并拖动 ImageButton 时,它应该会随着我的手指移动。

    我为此使用了OnTouchListener(),它工作正常。

  2. 当我单击 ImageButton 时,它应该关闭活动。

    我为此使用了OnClickListener(),它也可以正常工作。

所以,这是我的问题。每当我移动ImageButton OnTouchListenerImageButton 移动时,OnClickListener 也会在我释放按钮移动时触发。

如何在同一个按钮上使用 ontouch 和 onclick 监听器而不互相干扰?

【问题讨论】:

标签: android


【解决方案1】:

点击监听事件;如果您的组件范围内的 actiondown 和 action up 比调用 onclicklistener。因此,onclick 事件通过触摸检测激活。如果您的组件开始位置上的动作向上和向下动作,您只能设置 onTouchListener 并接收点击事件。

【讨论】:

    【解决方案2】:

    声明一个私有变量,例如:boolean hasMoved = false;

    当图片按钮开始移动时,设置hasMoved = true

    在您的OnClickListener 中仅执行代码if(!hasMoved) - 表示仅在按钮未移动时执行点击功能。之后设置hasMoved = false;

    【讨论】:

      【解决方案3】:

      也许您可以使用布尔值。

      让我们说 布尔 isMoving = false;

      public boolean onTouch(View v, MotionEvent event) {
      
      switch (event.getAction()) {
      
          case MotionEvent.ACTION_MOVE:
                       isMoving = true;
      
                // implement your move codes
          break;
      
          case MotionEvent.ACTION_UP:
                     isMoving = false;
          break;
      
      default:
              break;
          }
      

      然后在您的 onclick 方法中检查布尔值。如果为假,则执行点击动作,如果为真...不动作。

      public void onClick(View arg0) {
      
          switch (arg0.getId()) {
      
          case R.id.imagebutton:
              if(!isMoving) {
                         //code for on click here
                      }
          default:
              break;
          }
      }
      

      【讨论】:

        【解决方案4】:

        当您的 OnTouchListener 被触发时,只需使用一个布尔字段并将其设置为真值。之后,当 OnClickListener 想要触发时,您将检查布尔字段,如果为 true,则不要在您的 onClickListener 中执行任何操作。

            private blnTouch = false;
        
        private OnTouchListener btnOnTouchListener = new OnTouchListener() {
        
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            // TODO Auto-generated method stub
            if (event.getAction()==MotionEvent.ACTION_DOWN){
                blnOnTouch = true;
            }
            if (event.getAction()==MotionEvent.ACTION_UP){
                blnOnTouch = false;
            }
                       }
         };
        
        private OnClickListener btnOnClickListener = new OnClickListener() {
        
            @Override
            public void onClick(View arg0) {
                if (blnOnTouch){
                    // Do Your OnClickJob Here without touch and move
                }
        
            }
        };
        

        【讨论】:

        • onTouch 每次都会被触发,所以在你的逻辑下基本上永远不会调用 onclick。
        【解决方案5】:

        试试这个,可能对你有帮助

        无需设置onClick() 方法onTouch() 将处理这两种情况。

        package com.example.demo;
        
        import android.app.Activity;
        import android.os.Bundle;
        import android.view.GestureDetector;
        import android.view.GestureDetector.SimpleOnGestureListener;
        import android.view.Menu;
        import android.view.MotionEvent;
        import android.view.View;
        import android.view.View.OnTouchListener;
        import android.widget.ImageButton;
        
        public class MainActivity extends Activity {
            private GestureDetector gestureDetector;
        
            @Override
            protected void onCreate(Bundle savedInstanceState) {
                super.onCreate(savedInstanceState);
                setContentView(R.layout.activity_main);
                gestureDetector = new GestureDetector(this, new SingleTapConfirm());
                ImageButton imageButton = (ImageButton) findViewById(R.id.img);
        
                imageButton.setOnTouchListener(new OnTouchListener() {
        
                    @Override
                    public boolean onTouch(View arg0, MotionEvent arg1) {
        
                        if (gestureDetector.onTouchEvent(arg1)) {
                            // single tap
                            return true;
                        } else {
                            // your code for move and drag
                        }
        
                        return false;
                    }
                });
        
            }
        
            private class SingleTapConfirm extends SimpleOnGestureListener {
        
                @Override
                public boolean onSingleTapUp(MotionEvent event) {
                    return true;
                }
            }
        
        }
        

        【讨论】:

        • 就我而言,我不得不使用 onSingleTapUp() 而不是 onSingleTapConfirmed(),但除此之外,这正是我所需要的。
        • 使用 onSingleTapUp().. bravo (Y) 为我工作
        • onSingleTapConfirmed() 不起作用,onSingleTapUp() 不适合这个。
        • @JyotmanSingh SingleTapConfirm 类应该覆盖 onDown 方法 - 它应该返回 true,因为当返回 false 时,其余手势将被忽略
        • @JyotmanSingh 通过为onDown 方法返回true,触摸甚至触发onDown,然后触摸和单击没有区别。你能指导我吗?
        【解决方案6】:

        onClick 和 OnTouch 事件的问题在于,当您单击(意图单击)时,它假定事件为 OnTouch,因此永远不会解释 OnClick。解决方法

        isMove = false;
        case MotionEvent.ACTION_DOWN:
        //Your stuff
        isMove = false;
        case MotionEvent.ACTION_UP:
        if (!isMove || (Xdiff < 10 && Ydiff < 10 ) {
        view.performClick; //The check for Xdiff <10 && YDiff< 10 because sometime elements moves a little
        even when you just click it   
        }
        case MotionEvent.ACTION_MOVE:
        isMove = true;
        

        【讨论】:

        • Xdiff 将是新的 x 坐标和之前的 x 坐标之间的差异。因此,在每一步中,您都会保存上一个位置。即 ontouch xprev 被计算出来,并且在 action up 上 xnew (current x) 被计算出来。 xdiff = xcurrent - xprev。这能回答你的问题吗?
        • 或者你可以在MotionEvent.ACTION_MOVE中设置isMove = true,只有当差值大于10时
        【解决方案7】:

        要在单个View 上拥有Click ListenerDoubleClick ListenerOnLongPress ListenerSwipe LeftSwipe RightSwipe UpSwipe Down,您需要setOnTouchListener。即,

        view.setOnTouchListener(new OnSwipeTouchListener(MainActivity.this) {
        
                    @Override
                    public void onClick() {
                        super.onClick();
                        // your on click here
                    }
        
                    @Override
                    public void onDoubleClick() {
                        super.onDoubleClick();
                        // your on onDoubleClick here
                    }
        
                    @Override
                    public void onLongClick() {
                        super.onLongClick();
                        // your on onLongClick here
                    }
        
                    @Override
                    public void onSwipeUp() {
                        super.onSwipeUp();
                        // your swipe up here
                    }
        
                    @Override
                    public void onSwipeDown() {
                        super.onSwipeDown();
                        // your swipe down here.
                    }
        
                    @Override
                    public void onSwipeLeft() {
                        super.onSwipeLeft();
                        // your swipe left here.
                    }
        
                    @Override
                    public void onSwipeRight() {
                        super.onSwipeRight();
                        // your swipe right here.
                    }
                });
        
        }
        

        为此,您需要实现OnTouchListenerOnSwipeTouchListener 类。

        public class OnSwipeTouchListener implements View.OnTouchListener {
        
        private GestureDetector gestureDetector;
        
        public OnSwipeTouchListener(Context c) {
            gestureDetector = new GestureDetector(c, new GestureListener());
        }
        
        public boolean onTouch(final View view, final MotionEvent motionEvent) {
            return gestureDetector.onTouchEvent(motionEvent);
        }
        
        private final class GestureListener extends GestureDetector.SimpleOnGestureListener {
        
            private static final int SWIPE_THRESHOLD = 100;
            private static final int SWIPE_VELOCITY_THRESHOLD = 100;
        
            @Override
            public boolean onDown(MotionEvent e) {
                return true;
            }
        
            @Override
            public boolean onSingleTapUp(MotionEvent e) {
                onClick();
                return super.onSingleTapUp(e);
            }
        
            @Override
            public boolean onDoubleTap(MotionEvent e) {
                onDoubleClick();
                return super.onDoubleTap(e);
            }
        
            @Override
            public void onLongPress(MotionEvent e) {
                onLongClick();
                super.onLongPress(e);
            }
        
            // Determines the fling velocity and then fires the appropriate swipe event accordingly
            @Override
            public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
                boolean result = false;
                try {
                    float diffY = e2.getY() - e1.getY();
                    float diffX = e2.getX() - e1.getX();
                    if (Math.abs(diffX) > Math.abs(diffY)) {
                        if (Math.abs(diffX) > SWIPE_THRESHOLD && Math.abs(velocityX) > SWIPE_VELOCITY_THRESHOLD) {
                            if (diffX > 0) {
                                onSwipeRight();
                            } else {
                                onSwipeLeft();
                            }
                        }
                    } else {
                        if (Math.abs(diffY) > SWIPE_THRESHOLD && Math.abs(velocityY) > SWIPE_VELOCITY_THRESHOLD) {
                            if (diffY > 0) {
                                onSwipeDown();
                            } else {
                                onSwipeUp();
                            }
                        }
                    }
                } catch (Exception exception) {
                    exception.printStackTrace();
                }
                return result;
            }
        }
        
        public void onSwipeRight() {
        }
        
        public void onSwipeLeft() {
        }
        
        public void onSwipeUp() {
        }
        
        public void onSwipeDown() {
        }
        
        public void onClick() {
        
        }
        
        public void onDoubleClick() {
        
        }
        
        public void onLongClick() {
        
        }
        }
        

        【讨论】:

        • 不使用完整的。双击检测每次单击和双击。
        【解决方案8】:

        我尝试在我的项目中应用@Biraj 解决方案,但没有成功——我注意到SimpleOnGestureListener 的扩展不仅应该覆盖onSingleTapConfirmed 方法,还应该覆盖onDown。由于documentation

        如果你从 onDown() 返回 false,就像 GestureDetector.SimpleOnGestureListener 默认做的那样,系统假定你想忽略手势的其余部分,并且 GestureDetector.OnGestureListener 的其他方法永远不会被调用

        下面是复杂的解决方案:

        public class MainActivity extends Activity {
            private GestureDetector gestureDetector;
        
            @Override
            protected void onCreate(Bundle savedInstanceState) {
                super.onCreate(savedInstanceState);
                setContentView(R.layout.activity_main);
                gestureDetector = new GestureDetectorCompat(this, new SingleTapConfirm());
                ImageButton imageButton = (ImageButton) findViewById(R.id.img);
        
                imageButton.setOnTouchListener(new OnTouchListener() {
        
                    @Override
                    public boolean onTouch(View arg0, MotionEvent arg1) {
        
                        if (gestureDetector.onTouchEvent(arg1)) {
                            // single tap
                            return true;
                        } else {
                            // your code for move and drag
                        }
        
                        return false;
                    }
                });
        
            }
        
            private class SingleTapConfirm extends SimpleOnGestureListener {
        
                @Override
                public boolean onDown(MotionEvent e) {
                    /*it needs to return true if we don't want 
                    to ignore rest of the gestures*/
                    return true;
                }
        
                @Override
                public boolean onSingleTapConfirmed(MotionEvent event) {
                    return true;
                }
            }
        
        }
        

        我想,这种行为可能是由 GestureDetectorCompat 差异引起的,但我会关注documentation,我将使用第二个:

        您应该尽可能使用支持库类以提供与运行 Android 1.6 及更高版本的设备的兼容性

        【讨论】:

        • 这对于滚动事件也会返回 true,因为 onDown() 返回 true。
        • @Krzysztof 有正确的想法;我设法通过使用两个侦听器来避免 Type 1 错误,一个带有我正在寻找的 Tap Up 和 onDown,另一个只带有 onDown;在我的 gridTouched 处理程序中,我以 ` // 只希望点击 ups if(!singleTapUpDetector.onTouchEvent(motionEvent)) return false; // 不希望 onDown if(downCatchDetector.onTouchEvent(motionEvent)) return true; `
        • 我也想要onLongPress,有什么方法我也可以得到它吗?
        【解决方案9】:

        MainActivity 中编码。

        public class OnSwipeTouchListener_imp extends AppCompatActivity {
        
        @Override
        protected void onCreate(Bundle savedInstanceState)
        {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_on_swipe_touch_listener);
        
            ImageView view = (ImageView)findViewById(R.id.view);
        
            view.setOnTouchListener(new OnSwipeTouchListener(OnSwipeTouchListener_imp.this)
            {
                @Override
                public void onClick()
                {
                    super.onClick(); // your on click here              
                    Toast.makeText(getApplicationContext(),"onClick",Toast.LENGTH_SHORT).show();
                }
        
                @Override
                public void onDoubleClick()
                {
                    super.onDoubleClick(); // your on onDoubleClick here               
                }
        
                @Override
                public void onLongClick()
                {
                    super.onLongClick(); // your on onLongClick here                
                }
        
                @Override
                public void onSwipeUp() {
                    super.onSwipeUp(); // your swipe up here                
                }
        
                @Override
                public void onSwipeDown() {
                    super.onSwipeDown();  // your swipe down here.
        
                }
        
                @Override
                public void onSwipeLeft() {
                    super.onSwipeLeft(); // your swipe left here.                
                    Toast.makeText(getApplicationContext(),"onSwipeLeft",Toast.LENGTH_SHORT).show();
                }
        
                @Override
                public void onSwipeRight() {
                    super.onSwipeRight(); // your swipe right here.                
                    Toast.makeText(getApplicationContext(),"onSwipeRight",Toast.LENGTH_SHORT).show();
                }
            });
        }
        }
        

        然后创建一个OnSwipeTouchListener java Class。

        public class OnSwipeTouchListener implements View.OnTouchListener {
        
        private GestureDetector gestureDetector;
        
        public OnSwipeTouchListener(Context c) {
            gestureDetector = new GestureDetector(c, new GestureListener());
        }
        
        public boolean onTouch(final View view, final MotionEvent motionEvent) {
            return gestureDetector.onTouchEvent(motionEvent);
        }
        
        private final class GestureListener extends GestureDetector.SimpleOnGestureListener {
        
            private static final int SWIPE_THRESHOLD = 100;
            private static final int SWIPE_VELOCITY_THRESHOLD = 100;
        
            @Override
            public boolean onDown(MotionEvent e) {
                return true;
            }
        
            @Override
            public boolean onSingleTapUp(MotionEvent e) {
                onClick();
                return super.onSingleTapUp(e);
            }
        
            @Override
            public boolean onDoubleTap(MotionEvent e) {
                onDoubleClick();
                return super.onDoubleTap(e);
            }
        
            @Override
            public void onLongPress(MotionEvent e) {
                onLongClick();
                super.onLongPress(e);
            }
        
            // Determines the fling velocity and then fires the appropriate swipe event accordingly
            @Override
            public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
                boolean result = false;
                try {
                    float diffY = e2.getY() - e1.getY();
                    float diffX = e2.getX() - e1.getX();
                    if (Math.abs(diffX) > Math.abs(diffY)) {
                        if (Math.abs(diffX) > SWIPE_THRESHOLD && Math.abs(velocityX) > SWIPE_VELOCITY_THRESHOLD)
                        {
                            if (diffX > 0)
                            {
                                onSwipeRight(); // Right swipe
                            } else {
                                onSwipeLeft();  // Left swipe
                            }
                        }
                    } else {
                        if (Math.abs(diffY) > SWIPE_THRESHOLD && Math.abs(velocityY) > SWIPE_VELOCITY_THRESHOLD) {
                            if (diffY > 0) {
                                onSwipeDown(); // Down swipe
                            } else {
                                onSwipeUp(); // Up swipe
                            }
                        }
                    }
                } catch (Exception exception) {
                    exception.printStackTrace();
                }
                return result;
            }
        }
        
        public void onSwipeRight() {
        }
        
        public void onSwipeLeft() {
        }
        
        public void onSwipeUp() {
        }
        
        public void onSwipeDown() {
        }
        
        public void onClick() {
        }
        
        public void onDoubleClick() {
        }
        
        public void onLongClick() {
        }
        }
        

        希望这能照亮你:)

        【讨论】:

          【解决方案10】:

          希望我还不算太晚,但您可以通过计时器实现这一目标。 单击只需不到一秒钟,因此请记住这一点....

              long prev=0;
              long current = 0;
              long dif =0; 
             public boolean onTouch(View view, MotionEvent event) {
                      switch (event.getAction() & MotionEvent.ACTION_MASK) {
                          case MotionEvent.ACTION_DOWN:
          
                              prev = System.currentTimeMillis() / 1000;
          
                              break;
                          case MotionEvent.ACTION_UP:
          
                              current = System.currentTimeMillis() / 1000;
                              dif = current - prev;
                              if (dif == 0) {
                                  //Perform Your Click Action
                              }
                              break;
                           }
                     }
          

          希望对大家有所帮助

          【讨论】:

            【解决方案11】:

            您可以通过获取 x,y 值的差异来区分触摸、点击和滑动,例如:

            var prevY = 0
            var prevX = 0
                controls.setOnTouchListener { v, event ->
            
                            when (event?.actionMasked) {
            
                                MotionEvent.ACTION_DOWN -> {
                                    prevY = event.rawY.toInt()
                                    prevX = event.rawX.toInt()
            
                                }
            
                                MotionEvent.ACTION_UP->{
                                    Log.d("Controls","Action up")
                                    var y = event.rawY.toInt()
                                    var x = event.rawX.toInt()
                                    val diffY = Math.abs(prevY - y)
                                    val diffX = Math.abs(prevX - x)
                                    if(diffX in 0..10 && diffY in 0..10){
                                      // its a touch
                                    }
                                     //check diffY if negative, is a swipe down, else swipe up
                                  //check diffX if negative, its a swipe right, else swipe left
                                }
                            }
                            true
                        }
            

            【讨论】:

              【解决方案12】:
              Perfect example for Both touch n tap both    
              private void touchNtap() {
                          GestureDetector gestureDetector = new GestureDetector(itemView.getContext()
                                  , new SingleTapConfirm());
              
              
                          imageView.setOnTouchListener(new View.OnTouchListener() {
              
                              @Override
                              public boolean onTouch(View v, MotionEvent event) {
                                  if (gestureDetector.onTouchEvent(event)) {
                                      // program for click events
                                      gestureDetector.setOnDoubleTapListener(new GestureDetector.OnDoubleTapListener() {
                                          @Override
                                          public boolean onSingleTapConfirmed(MotionEvent e) {
                                              Log.d(TAG, "onSingleTapConfirmed() returned: " + true);
                                              return false;
                                          }
              
                                          @Override
                                          public boolean onDoubleTap(MotionEvent e) {
                                              Log.d(TAG, "onDoubleTap() returned: " + true);
                                              return false;
                                          }
              
                                          @Override
                                          public boolean onDoubleTapEvent(MotionEvent e) {
                                              Log.d(TAG, "onDoubleTapEvent() returned: " + true);
                                              return false;
                                          }
                                      });
                                      return true;
                                  }else {
                                      //program for touch events
                                  }
                                  return false;
                              }
                          });
                      }
              Create a Inner class 
              
                  private class SingleTapConfirm extends GestureDetector.SimpleOnGestureListener {
              
                          @Override
                          public boolean onSingleTapUp(MotionEvent event) {
                              return true;
                          }
              
                          @Override
                          public boolean onDoubleTap(MotionEvent e) {
                              return true;
                          }
                      }
              

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 2021-12-31
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2012-02-25
                相关资源
                最近更新 更多