我FrameLayout
封装了两个ImageView
。这就是我想要的:
在用户触摸和拖动时移动整个布局,但是当有点击时,应由个别ImageView
处理(通过各自的View.OnClickListener()
)< / em>的
当前行为:目前,当我尝试拖动视图组时,它会随机跳转一次(每个拖动事件),然后开始用手指移动。所以,就像你将手指移到视图组之外并且它正在移动。
其次,没有点击事件被路由到孩子ImageView
我尝试了什么:
我尝试扩展封装FrameLayout
s的<{1}}:
ImageView
那么,这段代码有什么问题?
答案 0 :(得分:1)
首先,getRawX()的结果被转换为屏幕0,0,getX()相对于它自己的视图。
此外,initialX和getCurrentX的累积量将只是拖动的值,你需要存储屏幕x并使用它拖动或计算ACTION_MOVE的每个差异并使用它
//remember the initial position
initialTouchX = event.getX();
initialTouchY = event.getY();
screenX = getX();
screenY = getY();
然后ON_MOVE
setX(screenX + event.getX() - initialTouchX);
setY(screenY + event.getY() - initialTouchY);
其次,你必须调用super.onTouchEvent(MotionEvent.obtain(event))或super.dispatchTouchEvent作为onTouchEvent的第一行,因为你的视图正在消耗所有事件。
答案 1 :(得分:0)
事实证明这比我预期的要简单得多(见下面评论中的解释):
react-native run-android
这个解决方案有一个警告:点击事件完全基于移动的距离。通常,要区分点击和长按,您还可以执行this之类的操作:
@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
// The plan is to intercept the events here and if,
// 1) The move is an ACTION_DOWN, return false indicating we want more events
// to be able to ascertain if we want this ViewGroup to move or the children
// views to handle the click event.
// 2) On receiving the ACTION_MOVE, of course, move the ViewGroup but the sure short
// indication of click would be to check it for in ACTION_DOWN with threshold of 5px.
// In that case, we would return super.onInterceptTouchEvent(event); meaning, let the
// event handling happen normally without interception
// (Remember - the ACTION_DOWN had been recorded by the children previously when we
// returned false and on receiving the ACTION_UP, it would constitute the complete event)
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
// remember the initial position
initialTouchX = event.getX();
//Log.d(TAG, "onInterceptTouchEvent().ACTION_DOWN.initialTouchX: " + initialTouchX);
initialTouchY = event.getY();
//Log.d(TAG, "onInterceptTouchEvent().ACTION_DOWN.initialTouchY: " + initialTouchY);
return false;
case MotionEvent.ACTION_UP:
int xDiff = (int) (event.getX() - initialTouchX);
int yDiff = (int) (event.getY() - initialTouchY);
//The check for Xdiff <5 && YDiff< 5 because sometime elements moves a little while clicking.
//So that is click event.
if (xDiff < 5 && yDiff < 5) {
return super.onInterceptTouchEvent(event);
}
return false;
case MotionEvent.ACTION_MOVE:
int moveX = (int) (event.getX() - initialTouchX + getX());
int moveY = (int) (event.getY() - initialTouchY + getY());
setX(moveX);
setY(moveY);
//Update the layout with new X & Y coordinate
invalidate();
}
return false;
}
P.S:在提供的解决方案中无需覆盖private long lastTouchDown;
private static int CLICK_ACTION_THRESHHOLD = 200;
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
lastTouchDown = System.currentTimeMillis();
break;
case MotionEvent.ACTION_UP:
if (System.currentTimeMillis() - lastTouchDown < CLICK_ACTION_THRESHHOLD) {
Log.w("App", "You clicked!");
}
break;
}
return true;
}
方法。