Java 检测触摸按压vs长按压vs移动?
我目前正忙于Android编程,但我在检测不同的触摸事件时遇到了一个小问题,即正常的触摸按键(按下屏幕并立即释放)、长按(触摸屏幕并按住手指)和移动(在屏幕上拖动) 我想做的是在我的屏幕上有一个(圆的)图像,我可以拖动它。然后,当我按一次(短按/普通按)时,会出现一个祝酒词,上面有一些关于它的基本信息。当我长按它时,会出现一个带有列表的AlertDialog来选择不同的图像(圆形、矩形或三角形) 我用自己的OnTouchListener创建了一个自定义视图,用于检测事件并在onDraw中绘制图像。OnTouchListener.onTouch是这样的:Java 检测触摸按压vs长按压vs移动?,java,android,touch,move,long-press,Java,Android,Touch,Move,Long Press,我目前正忙于Android编程,但我在检测不同的触摸事件时遇到了一个小问题,即正常的触摸按键(按下屏幕并立即释放)、长按(触摸屏幕并按住手指)和移动(在屏幕上拖动) 我想做的是在我的屏幕上有一个(圆的)图像,我可以拖动它。然后,当我按一次(短按/普通按)时,会出现一个祝酒词,上面有一些关于它的基本信息。当我长按它时,会出现一个带有列表的AlertDialog来选择不同的图像(圆形、矩形或三角形) 我用自己的OnTouchListener创建了一个自定义视图,用于检测事件并在onDraw中绘制图像
// 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;
}
问题是,按键并没有像预期的那样工作,因为当我随意触摸屏幕时,它也会检测到一点移动,并取消触摸按键,转而在图像周围移动
我引入了一个新的变量“mTouchDelay”,我在操作时将其设置为0,在移动中增加,如果在移动中大于等于3,则执行我的“移动”代码。但我有一种感觉,这不是真正的方式去
我还没有发现如何检测长按。真正的罪魁祸首是似乎总是触发的行动
有关我大致想要的示例,请参见Android应用程序“DailyStrip”:它显示一幅漫画的图像。如果屏幕太大,你可以拖动它。您可以点击它一次以弹出一些控件,然后长按它以显示选项菜单
另外,我正试图让它在安卓1.5上运行,因为我的手机只在安卓1.5上运行。来自安卓文档- onLongClick() 从View.OnLongClickListener。当用户触摸并按住项目(处于触摸模式时),或使用导航键或轨迹球聚焦项目并按住适当的“回车”键或按住轨迹球(一秒钟)时,调用此选项 onTouch() 从View.OnTouchListener。当用户执行符合触摸事件条件的操作时,会调用此操作,包括按下、释放或屏幕上的任何移动手势(在项目范围内)
至于“即使在我触摸时也会发生移动”,我会设置一个增量,并确保在输入移动代码之前视图至少移动了增量。如果没有,请启动触摸代码。经过大量实验,我发现了这一点 在初始化您的活动时:
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);
我一直在寻找类似的解决方案,这就是我的建议。 在OnTouch方法中,记录MotionEvent.ACTION\u DOWN事件的时间,然后再次记录MotionEvent.ACTION\u UP事件的时间。这样,您也可以设置自己的阈值。经过几次实验后,你会知道记录一次简单的触摸所需的最大时间(毫秒),你可以在移动或其他方式中使用它
希望这有帮助。如果您使用了不同的方法并解决了您的问题,请发表评论。我认为您应该实现GestureDetector.OnTestureListener 如和中所述
然后在onSingleTapUp中实现tap逻辑,在onScroll事件中实现move逻辑在希望longclick不以click事件结束后,我正在处理这个混乱 这就是我所做的
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;
这有点像黑客,但它可以工作。它只需要在overlay类中使用一个ontouch事件。检查这个,它帮助了我
此代码可以区分单击和移动(拖动、滚动)。在onTouchEvent中,设置一个标志isOnClick,并在操作上设置初始X、Y坐标。清除动作移动时的标志(注意经常检测到无意移动,这可以通过阈值常量解决) 如上所述,对于LongPress,GestureDetector是一个不错的选择。检查此问答:
如果需要区分单击、长按和滚动,请使用手势检测器 活动实现了
GestureDetector.OnTestureListener
例如,在onCreate中创建检测器
mDetector = new GestureDetectorCompat(getActivity().getApplicationContext(),this);
然后选择在视图(例如webview)上设置TouchListener,其中
现在,您可以使用Override onScroll、onFling、showPress(检测长按)或onSingleTapUp(检测单击)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);
}
});
用onLongClick和longclick的“那种”效果不错,但我仍然面临两个问题。首先,onLongClick触发两次长时间单击(我只需显示一个Toast并返回true,我得到两个Toast)。而且,当我按住时,我会在按住的同时得到长时间的点击,但当我松开时,我仍然会从onTouch中得到动作。我怎样才能防止onLongClick触发后的操作发生?双击onLongClick让我担心,我不知道为什么会触发两次。至于仍在发射的动作,我想问你为什么需要追踪动作向上和向下。测试onLongClick()被激发时onTouch()是否被激发。如果不是,我不确定你是否需要捕捉这些。您应该只需要在实际触摸项目和移动项目时使用onTouch()。您还可以查看将onClick()用于“onTouch()”和仅将onTouch()用于移动。但不确定这是否满足您的要求。这需要一个Java标记。然而,如果你曾经在一个可以通过jQuery访问的web应用程序中发现了这一点,那么我也在试图找出如何拦截长点击(点击保持,长按)的方法?抱歉,这里是新手。哦,如果我被发送了一个事件,我可以“消费”它,这意味着其他正在监听同一事件的钩子也不会被调用。例如,当我把手从屏幕上举起时,可能会沿着组件层次结构发送一条“UP”消息,除非我使用它。我看到了。我原则上理解你写的东西,但是你实际上是如何“消费”的,比如说,“上升”事件?啊-消费
onTouch(View v, MotionEvent event) {
return mDetector.onTouchEvent(event);
}
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);
}
});