在我的应用中,我必须在布局的任何位置移动视图。所以我使用了onTouchListener
。在onClick
和onLongClick
,我必须执行其他一些任务。我能够移动视图。但是,听众彼此冲突。当我移动视图时,有时会调用onClick
或onLongClick
。并且,当用户移动视图时,我不希望它们被调用。我怎么能避免这个?我已经提到这个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
并添加了onTouchListener
和onClickListener
。然后,执行单击操作。还有,我发现在ACTION_MOVE
之前先调用onClick
,然后执行onClick
内的代码。那么,我怎样才能获得onClick
效果呢?我更新了我的代码。
答案 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
代码从未执行过。所以,为了避免这个问题,我不得不编写那些代码。但是,我认为它不是优雅的解决方案,似乎是我的黑客。如果有人有更好的解决方案,那么请告知我,以便我可以更新我的代码。