2015-06-30 35 views
0

我已经搜遍网络寻找一个问题的答案,这个问题一直在困扰着我好几天。我正在制作一个小部件,它允许用户通过在查看区域内拖动(仅围绕Y轴)来平移整个小部件。然后我在这里有一个较小的视图(像一个按钮,监听onTouchEvent),用户也可以拖动它。想法是,用户将向上或向下拖动此视图,如果他们想要更高或更低,则可以平移整个窗口小部件,然后继续将视图拖动到更高或更低的位置。现在,我有两个问题。首先,在拖动主视图(整个窗口小部件)之后,我想要移动的视图仍然位于翻译整个画布之前的区域。例如,如果我在Y位置将整个画布移动50,然后我想要移动较小的视图,但必须在旧位置而不是抵消位置(50)移动。所以它看起来像我现在不点击小视图,但它曾经是(我希望这是有道理的)。翻译帆布后的Android没有触摸事件

下一个问题,我移动后的小视图。我无法触发任何触摸事件。我假设这是因为它被移出它的父(它仍然可见,因为我把clipChildren设置为false),它的“z顺序”比布局中的其他视图要低。有没有一种方法可以始终将其置于顶端?我正在使用Android API 17.即使我将主视图中的最后一个子视图设置为较小的视图(即触摸时发生移动并触发ACTION_MOVE事件),我需要能够将其拖出此处(其中I可以)并继续将其拖放到新的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; 
     } 
    }); 
    } 
} 

请注意,我已经尝试设置填充和我已经提到的,没有良好的效果因此继:

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

好吧,好吧...我找到了一个工作。基本上,我的父视图(小部件本身)总是可以看到触摸事件。但是,孩子们无法解释我上面提到的情况。所以,我所做的就是跟踪我相对于查看区域拖动的子视图的x和y位置。然后,每当我收到触摸事件时,我都会检查是否触摸了儿童区域。如果我碰巧触发了它在旧位置的孩子的onTouchEvent,如果它没有通过这个检查,我会忽略它。它马虎,但它是唯一能让它工作的方法。现在我有一个可平移视图和拖动对象

0

我不知道我才明白你的问题就在一切,但也许这可以帮助你 View with horizontal and vertical pan/drag and pinch-zoom你应该尝试从亚历克斯的答案代码。该代码正在做一些额外的事情,但您可以只关闭scalelistener(用于缩放)并关闭X轴的平移。该代码还将childviews“内部”移动到画布上,因此您不必在onTouch调用后翻译点击位置。

0

更好的解决方案是让您的视图保持原位。然后将矩阵变换应用于视图并将倒置矩阵应用于MotionEvents。通过这种方式,您始终可以正确地获得您的视图,并且毫无困难地委派您的活动,并且所有的平移都在场景的绘图中进行。移动视图也会遇到一个基本上无法通过的问题,即您无法获得在真实视图范围外开始的MotionEvents。所以,如果你缩小,并按屏幕区域外面的东西它忽略,并不派遣触摸事件。

另外,它在一些实现上疯狂,我认为星系标签10,它只是可怕的fubar和不可能的错误。它会使视图的失效与其他平板电脑有点不同,并刷新视图的错误部分。