2011-07-23 29 views
8

我有兩個ImageButtons,每個裏面的一個RelativeLayout和這兩個RelativeLayouts是在另一個RelativeLayout中,我想爲每個ImageButton設置TouchDelegate。如果通常我將TouchDelegate添加到每個ImageButton並且它的父親是RelativeLayout,那麼只有一個ImageButton可以正常工作,另一個不會擴展它的點擊區域。因此,PLease幫助我瞭解如何在ImageButton中使用TouchDelegate。如果這是不可能的,那麼擴展視圖點擊區域的有效方法是什麼?在此先感謝........如何使用多個TouchDelegate

這裏是我的XML代碼:

<?xml version="1.0" encoding="utf-8"?> 
<RelativeLayout android:id="@+id/FrameContainer" 
android:layout_width="fill_parent" android:layout_height="fill_parent" 
xmlns:android="http://schemas.android.com/apk/res/android"> 
<RelativeLayout android:layout_alignParentLeft="true" 
    android:id="@+id/relativeLayout3" android:layout_width="wrap_content" 
    android:layout_height="wrap_content"> 
    <RelativeLayout android:layout_alignParentLeft="true" 
     android:id="@+id/relativeLayout1" android:layout_width="113dip" 
     android:layout_height="25dip"> 
     <ImageButton android:id="@+id/tutorial1" 
      android:layout_width="wrap_content" android:layout_height="wrap_content" 
      android:background="@null" android:src="@drawable/tutorial" /> 
    </RelativeLayout> 
    <RelativeLayout android:layout_alignParentLeft="true" 
     android:id="@+id/relativeLayout2" android:layout_width="113dip" 
     android:layout_height="25dip" android:layout_marginLeft="100dip"> 
     <ImageButton android:id="@+id/tutorial2" 
      android:layout_width="wrap_content" android:layout_height="wrap_content" 
      android:background="@null" android:src="@drawable/tutorial" 
      android:layout_marginLeft="50dip" /> 
    </RelativeLayout> 
</RelativeLayout> 

我的動態類:

import android.app.Activity; 
import android.graphics.Rect; 
import android.os.Bundle; 
import android.view.TouchDelegate; 
import android.view.View; 
import android.widget.ImageButton; 
import android.widget.Toast; 

public class TestTouchDelegate extends Activity { 
/** Called when the activity is first created. */ 
@Override 
public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.main); 

    View mParent1 = findViewById(R.id.relativeLayout1); 
    mParent1.post(new Runnable() { 
     @Override 
     public void run() { 
      Rect bounds1 = new Rect(); 
      ImageButton mTutorialButton1 = (ImageButton) findViewById(R.id.tutorial1); 
      mTutorialButton1.setEnabled(true); 
      mTutorialButton1.setOnClickListener(new View.OnClickListener() { 
       public void onClick(View view) { 
        Toast.makeText(TestTouchDelegate.this, "Test TouchDelegate 1", Toast.LENGTH_SHORT).show(); 
       } 
      }); 

      mTutorialButton1.getHitRect(bounds1); 
      bounds1.right += 50; 
      TouchDelegate touchDelegate1 = new TouchDelegate(bounds1, mTutorialButton1); 

      if (View.class.isInstance(mTutorialButton1.getParent())) { 
       ((View) mTutorialButton1.getParent()).setTouchDelegate(touchDelegate1); 
      } 
     } 
    }); 

    //View mParent = findViewById(R.id.FrameContainer); 
    View mParent2 = findViewById(R.id.relativeLayout2); 
    mParent2.post(new Runnable() { 
     @Override 
     public void run() { 
      Rect bounds2 = new Rect(); 
      ImageButton mTutorialButton2 = (ImageButton) findViewById(R.id.tutorial2); 
      mTutorialButton2.setEnabled(true); 
      mTutorialButton2.setOnClickListener(new View.OnClickListener() { 
       public void onClick(View view) { 
        Toast.makeText(TestTouchDelegate.this, "Test TouchDelegate 2", Toast.LENGTH_SHORT).show(); 
       } 
      }); 

      mTutorialButton2.getHitRect(bounds2); 
      bounds2.left += 50; 
      TouchDelegate touchDelegate2 = new TouchDelegate(bounds2, mTutorialButton2); 

      if (View.class.isInstance(mTutorialButton2.getParent())) { 
       ((View) mTutorialButton2.getParent()).setTouchDelegate(touchDelegate2); 
      } 
     } 
    }); 

} 

}

回答

3

有隻應該是每個視圖的單觸代表。在View類中getTouchDelegate()的文檔如下:

「獲取此視圖的TouchDelegate。」

只有一個TouchDelegate。每個視圖只能使用一個TouchDelegate,您可以將每個可觸摸的視圖封裝在一個視圖中,並且尺寸反映了您想要觸摸的內容。在廣場的Android開發者給出的你如何能做到這對於只使用一個靜態方法(http://www.youtube.com/watch?v=jF6Ad4GYjRU & T = 37m4s)多視圖的例子:

public static void expandTouchArea(final View bigView, final View smallView, final int extraPadding) { 
bigView.post(new Runnable() { 
    @Override 
    public void run() { 
     Rect rect = new Rect(); 
     smallView.getHitRect(rect); 
     rect.top -= extraPadding; 
     rect.left -= extraPadding; 
     rect.right += extraPadding; 
     rect.bottom += extraPadding; 
     bigView.setTouchDelegate(new TouchDelegate(rect, smallView)); 
    } 
}); 

}

假設您不想混亂您的視圖層次結構。還有兩個我能想到的選項。您可以定義可觸摸視圖內可觸摸內容的邊界,並確保將各個視圖從所有父視圖傳遞給該子視圖。或者,您可以覆蓋getHitRect()作爲可觸摸視圖。前者會很快地混淆你的代碼並使其難以理解,所以後者是更好的前進方向。你想要重寫getHitRect。

哪裏mPadding是你希望身邊視圖可觸摸的額外面積的量,你可以使用類似以下內容:

​​

如果你使用的代碼像上面你必須要考慮什麼可觸摸的景色就在附近。堆疊中最高的視圖的可觸摸區域可能會在另一個視圖的頂部重疊。

另一個類似的選擇是改變可觸摸視圖的填充。我不喜歡這個解決方案,因爲跟蹤視圖如何調整大小會變得很困難。

+1

我試圖重寫getHitRect,但它似乎並沒有工作(它根本沒有被調用)。基本上我創建了一個自定義視圖,它擴展了ImageButton,然後在類中重寫getHitRect(帶有添加的填充),但正如我所提到的,getHitRect永遠不會被調用。是否可以發佈您的解決方案? – stephenteh

+2

事實證明,我提供的解決方案在ICS中不起作用,這可能是它爲什麼不適合你的原因。我寫了一篇關於兩種不同觸摸委託策略的博客文章http://www.brendanweinstein.me/2012/06/26/touchdelegate-and-gethitrect-making-buttons-with-expanded-touch-areas/,您可以獲取樣本https://github.com/brendanw/Touch-Delegates/blob/master/src/com/brendan/touchdelegates/MyTouchDelegate.java上的兩種策略代碼 –

+0

這不回答OP的問題。 OP不會嘗試將多個代理添加到一個視圖。 OPs例子中的兩個ImageButton具有*不同的父母。 – zyamys

15

可以使用複合模式能夠超過一個TouchDelegate添加到視圖。步驟:

  1. 創建TouchDelegateComposite(無論什麼查看,你會傳遞作爲 說法,它只是用來獲取上下文)
  2. 創造必要TouchDelegates並將其添加到複合
  3. 添加複合材料查看他們推薦here(通過view.post(新的Runnable))

    public class TouchDelegateComposite extends TouchDelegate { 
    
        private final List<TouchDelegate> delegates = new ArrayList<TouchDelegate>(); 
        private static final Rect emptyRect = new Rect(); 
    
        public TouchDelegateComposite(View view) { 
         super(emptyRect, view); 
        } 
    
        public void addDelegate(TouchDelegate delegate) { 
         if (delegate != null) { 
          delegates.add(delegate); 
         } 
        } 
    
        @Override 
        public boolean onTouchEvent(MotionEvent event) { 
         boolean res = false; 
         float x = event.getX(); 
         float y = event.getY(); 
         for (TouchDelegate delegate : delegates) { 
          event.setLocation(x, y); 
          res = delegate.onTouchEvent(event) || res; 
         } 
         return res; 
        } 
    
    } 
    
+0

這是一個更好的解決方案,而不是混亂的視圖層次結構,或者使用填充混亂,並且不需要使用子視圖來覆蓋getHitRect()方法。一個小的建議是將@Brendan Weinstein的答案中的expandTouchArea()方法整合到這個類中,以保持整潔/易用性。 – AndroidNoob

+2

我改編了這個解決方案,用相同的父級擴展了可點擊的視圖區域:[gist](https://gist.github.com/nikosk/3854f2effe65438cfa40) @AndroidNoob:包含一個易於使用的靜態方法。像這樣使用:TouchDelegateComposite.expandClickArea(buttonView,parentView,clickListener,paddingInDP); – javito

+0

這不回答OP的問題。 OP不會嘗試將多個代理添加到一個視圖。 OPs例子中的兩個ImageButton具有*不同的父母。 – zyamys

0

爲了讓您代碼工作你需要減少bounds2的左邊界,而不是增加它。

bounds2.left -= 50; 

玩弄TouchDelegate後,我來到了下面的代碼,這對我來說一直工作在任何Android版本。訣竅是在佈局調用後擴展區域。

public class ViewUtils { 

    public static final void extendTouchArea(final View view, 
      final int padding) { 

     view.getViewTreeObserver().addOnGlobalLayoutListener(
       new OnGlobalLayoutListener() { 

      @Override 
      @SuppressWarnings("deprecation") 
      public void onGlobalLayout() { 
       final Rect touchArea = new Rect(); 
       view.getHitRect(touchArea); 
       touchArea.top -= padding; 
       touchArea.bottom += padding; 
       touchArea.left -= padding; 
       touchArea.right += padding; 

       final TouchDelegate touchDelegate = 
        new TouchDelegate(touchArea, view); 
       final View parent = (View) view.getParent(); 
       parent.setTouchDelegate(touchDelegate); 

       view.getViewTreeObserver().removeGlobalOnLayoutListener(this); 
      } 
     }); 
    } 

} 
0

好吧,我想沒有人提供真正的答案做出的IT解決方案,並使其easy.Lately我有同樣的問題和閱讀上述所有我只是不知道如何只是爲了讓work.But最後我做到了首先要牢記在心!讓我們假裝你有一個完整的佈局,它持有你的兩個小按鈕,這個區域必須被擴展,所以你必須在主佈局中做另一個佈局,並把另一個按鈕放到你新創建的佈局上在這種情況下,通過靜態方法,您可以同時將觸摸委託給2個按鈕。現在更深入一步一步地進入代碼! 首先你一定只要找到你的MAINLAYOUT和巴頓這樣的觀點。(這種佈局將舉行我們的第一個按鈕)

RelativeLayout mymainlayout = (RelativeLayout)findViewById(R.id.mymainlayout) 
Button mybutoninthislayout = (Button)findViewById(R.id.mybutton) 

的同意,我們做調查的主要佈局和按鈕視圖,將其牽住一切我們onCreate()顯示佈局,但你必須找到以備後用。下一步是什麼?我們在主佈局中創建另一個RelativeLayout,其寬度和高度符合你的口味(這個新創建的佈局將保存我們的第二個按鈕)

RelativeLayout myinnerlayout = (RelativeLayout)findViewById(R.id.myinnerlayout) 
Button mybuttoninsideinnerlayout = (Button)findViewById(R.id.mysecondbutton) 

的同意,我們做調查的意見,所以我們現在可以只複製和粘貼的C我們的人首先回答你的問題。只需在主要活動中複製該代碼即可。

public static void expandTouchArea(final View bigView, final View smallView, final int extraPadding) { 
    bigView.post(new Runnable() { 
     @Override 
     public void run() { 
      Rect rect = new Rect(); 
      smallView.getHitRect(rect); 
      rect.top -= extraPadding; 
      rect.left -= extraPadding; 
      rect.right += extraPadding; 
      rect.bottom += extraPadding; 
      bigView.setTouchDelegate(new TouchDelegate(rect, smallView)); 
     } 
    }); 
} 

現在如何使用這種方法,並使其工作?這裏是如何! 您onCreate()方法粘貼下面的代碼片段

expandTouchArea(mymainlayout,mybutoninthislayout,60); 
    expandTouchArea(myinnerlayout, mybuttoninsideinnerlayout,60); 

對我們所做的事情在這個snipped.We把我們創建的靜態方法命名爲expandTouchArea(),給了3個參數的說明。 第一個參數,將持有其面積必須擴大 第二個參數的按鍵佈局 - 實際按鈕來擴大面積的它 第三個參數 - 在我們多麼希望按鈕區域進行擴展像素的面積! 享受!

0

我有同樣的問題:試圖添加多個TouchDelegates針對不同LinearLayouts這條路線的觸摸事件分別分開Switches,在一個佈局。

詳情請參考this question asked by memy answer

我發現的是:一旦我附上LinearLayouts分別由另一LinearLayout,分別按預期TouchDelegate開始第二(每隔連續端)工作。

因此,這可能有助於OP爲他的問題創建工作解決方案。 雖然我沒有一個令人滿意的解釋,爲什麼它的行爲如此。