我已经在网上搜索了一个问题的答案,这个问题一直困扰着我好几天。我正在创建一个小部件,允许用户通过在查看区域内拖动(仅在Y轴周围)来平移整个小部件。然后,我在这里有一个较小的视图(如按钮,监听onTouchEvent),用户也可以拖动。这个想法是用户将向上或向下拖动此视图,如果他们想要更高或更低,他们可以平移整个小部件,然后继续向上或向下拖动视图。现在,我有两个问题。首先,在拖动主视图(整个小部件)之后,我想要移动的视图仍然位于翻译整个画布之前的区域。
因此,例如,如果我在Y位置将整个画布移动50,那么我想移动较小的视图,但必须触摸旧位置而不是偏移的位置(50)。所以看起来我没有点击现在的小视图,而是过去的位置(我希望这是有意义的)。
下一期,我移动较小的视图后。我无法再触发触摸事件。我假设这是因为它被移动到其父级之外(因为我将clipChildren设置为false,因此仍然可以查看)和它的" z-order"低于布局中的其他视图。有没有办法始终把它放在最上面?我正在使用Android API 17.即使我将这个较小的视图(我触摸时移动并触发ACTION_MOVE事件)设置为主布局中的最后一个子节点,我需要能够将它拖出这里(我can)并继续将它拖到新的onTouchEvent上。任何帮助是极大的赞赏。我在下面添加了一些布局xml和代码片段来帮助。
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipChildren="false"
android:clipToPadding="false">
<RelativeLayout
android:id="@+id/main_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipChildren="false"
android:clipToPadding="false">
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_centerHorizontal="true"
android:clipChildren="false"
android:clipToPadding="false">
<ImageView
android:id="@+id/ref_image"
android:layout_width="wrap_content"
android:layout_height="216dp"
android:src="@drawable/my_ref_image"
android:layout_centerInParent="true"
android:clipChildren="false"/>
<RelativeLayout
android:id="@+id/selection_view"
style="@style/MyStyle"
android:layout_alignTop="@id/ref_image"
android:layout_marginTop="116dp"
android:clipChildren="false"
android:clipToPadding="false">
<RelativeLayout
android:id="@+id/selection_area"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:clipChildren="false"
android:clipToPadding="false">
<ImageView
android:id="@+id/underlay_image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/translucent_image"
android:layout_centerInParent="true"/>
<ImageView
android:id="@+id/point_area"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/point_image"
android:layout_centerInParent="true"/>
</RelativeLayout>
</RelativeLayout>
</RelativeLayout>
</RelativeLayout>
所以感兴趣的代码片段是:
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (DEBUG) {
Log.d(TAG, TAG + "::onDraw: ");
}
canvas.translate(0, backgroundPositionY);
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
final int action = ev.getAction();
Log.d(TAG, TAG + "::onTouchEvent: parent touch event");
switch (action) {
case MotionEvent.ACTION_DOWN: {
final float y = ev.getY();
// Remember where we started
lastTouchY = y;
if (DEBUG) {
Log.d(TAG, TAG + "::onTouchEvent: parent ACTION_DOWN");
}
return true;
}
case MotionEvent.ACTION_MOVE: {
final float y = ev.getY();
// Calculate the distance moved
final float dy = y - lastTouchY;
backgroundPositionY += dy
// Remember this touch position for the next move event
lastTouchY = y;
// Invalidate to request a redraw
invalidate();
break;
}
case MotionEvent.ACTION_UP: {
lastTouchY = ev.getY();
}
}
return false;
}
// called upon initialization (selectionArea refs view id = selection_area)
private void initPointListener() {
this.setClipChildren(false);
this.setClipToPadding(false);
if (selectionArea != null) {
selectionArea .setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
RelativeLayout.LayoutParams pointParams = (RelativeLayout.LayoutParams) selectionArea.getLayoutParams();
final int action = motionEvent.getAction();
switch (action) {
case MotionEvent.ACTION_DOWN: {
pointLastTouchY = motionEvent.getY();
}
break;
}
case MotionEvent.ACTION_MOVE: {
float moveY = motionEvent.getY();
final float dy = moveY - pointLastTouchY;
pointPosY += dy;
selectionArea.setY(pointPosY);
break;
}
}
return true;
}
});
}
}
请注意,我已尝试设置填充,并在SO上引用了以下内容,但没有取得任何好结果:
How to translate the canvas and still get the touch events on the correct places
Android : click / touch event not working after canvas translate
答案 0 :(得分:0)
好吧,好吧......我找到了一个解决方法。基本上,我的父视图(小部件本身)总是可以看到触摸事件。但孩子们不能给出我上面提到的情况。所以,我所做的是跟踪我相对于观察区域拖动的子视图的x和y位置。然后每当我收到触摸事件时,我都会检查是否触摸了孩子区域。如果我碰巧在孩子位于旧位置时触发了onTouchEvent,如果它没有通过此检查,我会忽略它。它草率,但它是我能让它工作的唯一方法。现在我有一个可视空的视图和一个可拖动的对象
答案 1 :(得分:0)
我不确定我是否理解你问题的所有内容但也许这可以帮到你 View with horizontal and vertical pan/drag and pinch-zoom您应该尝试Alex答案中的代码。代码正在做一些额外的事情,但你可以只关闭scalelistener(用于缩放)和当前的X轴平移。该代码也在移动子视图&#34;内部&#34;因此,在onTouch调用后,你不应该翻译点击位置。
答案 2 :(得分:0)
更好的解决方案是保持您的观点。然后将矩阵变换应用于视图,将反转矩阵应用于MotionEvents。通过这种方式,您可以始终正确地获取视图并无条件地委派您的事件,并且所有平移都在场景的绘制中进行。移动视图也会遇到一个基本上无法解决的问题,即你无法获得超出真实视图范围的MotionEvents。因此,如果你缩小,并按屏幕 之外的区域,它会忽略它并且不会在那里发送触摸事件。
此外,它在一些实现上变得疯狂,我认为galaxy tab 10,它只是可怕的fubar和不可能的错误。它使视图的失效与其他平板电脑略有不同,并刷新了视图的错误部分。