2015-06-30 80 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和不可能的錯誤。它會使視圖的失效與其他平板電腦有點不同,並刷新視圖的錯誤部分。