检测触摸按VS长按VS运动?

我目前正在摆弄Android编程,但是我在检测不同的触摸事件时遇到了一个小问题,即正常的触摸按下(在屏幕上按下并立即释放),长按(触摸屏幕并按住它的手指)和移动(在屏幕上拖动)。

我想要做的是在屏幕上有一个图像(一个圆圈),我可以拖动。 然后当我按下一次(短/正常按)一个吐司来了一些关于它的基本信息。 当我长时间按下它时,带有列表的AlertDialog出现以select不同的图像(圆形,矩形或三angular形)。

我用自己的OnTouchListener做了一个自定义View来检测事件并在onDraw中绘制图像。 OnTouchListener.onTouch就像这样:

// has a touch press started? private boolean touchStarted = false; // co-ordinates of image private int x, y; public boolean onTouch(View v, MotionEvent event) { int action = event.getAction(); if (action == MotionEvent.ACTION_DOWN) { touchStarted = true; } else if (action == MotionEvent.ACTION_MOVE) { // movement: cancel the touch press touchStarted = false; x = event.getX(); y = event.getY(); invalidate(); // request draw } else if (action == MotionEvent.ACTION_UP) { if (touchStarted) { // touch press complete, show toast Toast.makeText(v.getContext(), "Coords: " + x + ", " + y, 1000).show(); } } return true; } 

问题在于印刷机不能按预期工作,因为当我随意触摸屏幕时,它也检测到一点点的移动,取消了触摸按键,而是在图像周围移动。

我“砍死”了一下,我介绍了一个新的variables“mTouchDelay”,我在ACTION_DOWN上设置为0,在MOVE中增加,如果在MOVE中大于3,我执行我的“移动”代码。 但我有一种感觉,这不是真的要走的路。

我也没有发现如何检测长按。 罪魁祸首确实是似乎始终触发的MOVE。

有关我想要的内容的示例,请参阅Android应用程序“DailyStrip”:它显示漫画的图像。 如果屏幕太大,可以拖动它。 您可以点击一次,以便popup一些控件,然后长按选项菜单。

PS。 我试图让它在Android 1.5上工作,因为我的手机只能运行在1.5。

此代码可以区分点击和移动(拖动,滚动)。 在onTouchEvent中设置一个标志isOnClick,并在ACTION_DOWN上初始化X,Y坐标。 清除ACTION_MOVE上的标志(意识到经常检测到可以用THRESHOLD const解决的无意移动)。

 private float mDownX; private float mDownY; private final float SCROLL_THRESHOLD = 10; private boolean isOnClick; @Override public boolean onTouchEvent(MotionEvent ev) { switch (ev.getAction() & MotionEvent.ACTION_MASK) { case MotionEvent.ACTION_DOWN: mDownX = ev.getX(); mDownY = ev.getY(); isOnClick = true; break; case MotionEvent.ACTION_CANCEL: case MotionEvent.ACTION_UP: if (isOnClick) { Log.i(LOG_TAG, "onClick "); //TODO onClick code } break; case MotionEvent.ACTION_MOVE: if (isOnClick && (Math.abs(mDownX - ev.getX()) > SCROLL_THRESHOLD || Math.abs(mDownY - ev.getY()) > SCROLL_THRESHOLD)) { Log.i(LOG_TAG, "movement detected"); isOnClick = false; } break; default: break; } return true; } 

对于上述build议的LongPress,GestureDetector是最好的select。 检查这个问答:

用Android检测一个长按

从Android文档 –

onLongClick()

从View.OnLongClickListener。 当用户触摸并握住物品时(触摸模式时),或者用导航键或轨迹球对物品进行对焦,并按住合适的“进入”键或按住轨迹球一秒钟)。

onTouch()

从View.OnTouchListener。 当用户执行限定为触摸事件的操作(包括按下,释放或屏幕上的任何移动手势(在项目的范围内)时调用)。

至于“移动发生,甚至当我触摸”我会设置一个三angular洲,并确保视图已被移动至less三angular洲踢在运动代码之前。 如果没有,请启动触摸代码。

我经过试验发现了这个。

在你的活动的初始化:

 setOnLongClickListener(new View.OnLongClickListener() { public boolean onLongClick(View view) { activity.openContextMenu(view); return true; // avoid extra click events } }); setOnTouch(new View.OnTouchListener(){ public boolean onTouch(View v, MotionEvent e){ switch(e.getAction & MotionEvent.ACTION_MASK){ // do drag/gesture processing. } // you MUST return false for ACTION_DOWN and ACTION_UP, for long click to work // you can return true for ACTION_MOVEs that you consume. // DOWN/UP are needed by the long click timer. // if you want, you can consume the UP if you have made a drag - so that after // a long drag, no long-click is generated. return false; } }); setLongClickable(true); 

我正在寻找类似的解决scheme,这是我会build议的。 在OnTouch方法中,loggingMotionEvent.ACTION_DOWN事件的时间,然后loggingMotionEvent.ACTION_UP,再次logging时间。 这样你也可以设置你自己的门槛。 经过几次试验,你会知道毫秒的最大时间,它需要logging一个简单的触摸,你可以使用这个移动或其他方法,只要你喜欢。

希望这有助于。 如果您使用了不同的方法并解决了您的问题,请发表评论。

如果您需要在点击,longpress和滚动之间进行区分,请使用GestureDetector

活动实现了GestureDetector.OnGestureListener

然后在onCreate中创build检测器

 mDetector = new GestureDetectorCompat(getActivity().getApplicationContext(),this); 

然后可以selectsetOnTouchListener在你的视图(例如webview)的地方

 onTouch(View v, MotionEvent event) { return mDetector.onTouchEvent(event); } 

现在你可以使用覆盖onScroll,onFling,showPress(检测长按)或onSingleTapUp(检测一个点击)

我认为你应该实现GestureDetector.OnGestureListener,如使用 GestureDetector中所描述的那样,在Android和androidsnippets中检测长触摸,双敲击,滚动或其他触摸事件 ,然后在onSingleTapUp中实现敲击逻辑,并在onScroll事件中移动逻辑

在想要点击事件之后,我只是在处理这个混乱。

这是我做的。

 public boolean onLongClick(View arg0) { Toast.makeText(getContext(), "long click", Toast.LENGTH_SHORT).show(); longClicked = true; return false; } public void onClick(View arg0) { if(!longClicked){ Toast.makeText(getContext(), "click", Toast.LENGTH_SHORT).show(); } longClick = false; // sets the clickability enabled } boolean longClicked = false; 

这是一个黑客,但它的作品。

它只需要覆盖类中的ontouch事件。 检查这个,它帮助了我

http://mirnauman.wordpress.com/2012/04/16/android-google-maps-tutorial-part-6-getting-the-location-that-is-touched/

在这三种情况下,GestureDetector.SimpleOnGestureListener有帮助的方法;

  GestureDetector gestureDetector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() { //for single click event. @Override public boolean onSingleTapUp(MotionEvent motionEvent) { return true; } //for detecting a press event. Code for drag can be added here. @Override public void onShowPress(MotionEvent e) { View child = recyclerView.findChildViewUnder(e.getX(), e.getY()); ClipboardManager clipboardManager = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE); ClipData clipData = ClipData.newPlainText("..", "..."); clipboardManager.setPrimaryClip(clipData); ConceptDragShadowBuilder dragShadowBuilder = new CustomDragShadowBuilder(child); // drag child view. child.startDrag(clipData, dragShadowBuilder, child, 0); } //for detecting longpress event @Override public void onLongPress(MotionEvent e) { super.onLongPress(e); } });