2012-06-18 14 views
8

Basılı ve basılı olmayan durumlar için bir seçici olan bir ImageButton oluşturdum ve bu iyi çalışıyor.Farklı tıklama durumlarıyla düzensiz şekilli ImageButton oluşturma

Ancak düğmenin düzensiz bir şekli var ve yalnızca alttaki dikdörtgen resmin saydam olmadığı yerlerde tıklanabilir olmasını istiyorum.

Bu yüzden, Touch olayının koordinatlarını Bitmap'in piksel değerlerine göre kontrol eden bir OnTouchListener uygulamıştım (burada ilk yanıtta açıklandığı gibi: link). Bu, düğmenin basılıp basılmadığına karar veren mantık açısından çalışır, ancak şimdi düğmenin görüntüsü artık basılan görüntüye değişmez. düzeninde

<?xml version="1.0" encoding="utf-8"?> 
<selector xmlns:android="http://schemas.android.com/apk/res/android" > 
    <item android:state_pressed="true" android:drawable="@drawable/button_start_call_pressed" /> 
    <item android:drawable="@drawable/button_start_call_normal" /> 
</selector> 

Kısmen şeffaf ımagebutton:

Seçici xml dosyası: Bir Etkinlikte

<ImageButton 
    android:id="@+id/dashboardStartCallButton" 
    android:background="@null" 
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content" 
    android:src="@drawable/start_call_button_selector" 
    /> 

:

public void onCreate(Bundle savedInstance) { 
    super.onCreate(savedInstance); 
    ... 
    ImageButton startCallButton = (ImageButton) this.findViewById(R.id.dashboardStartCallButton); 
    startCallButton.setOnTouchListener(new OnTouchListener() { 
     @Override 
     public boolean onTouch(View v, MotionEvent event) { 
      return OnStartCallButtonTouch(v,event); 
     }   
    }); 
} 


public boolean OnStartCallButtonTouch(View v, MotionEvent event) 
{ 
    Bitmap TheBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.button_start_call_normal); 
    int eventPadTouch = event.getAction(); 
    int iX = (int) event.getX(); 
    int iY = (int) event.getY(); 
    switch (eventPadTouch) { 
     case MotionEvent.ACTION_DOWN: 
      if (iX>=0 & iY>=0 & iX<TheBitmap.getWidth() & iY<TheBitmap.getHeight()) {     
       if (TheBitmap.getPixel(iX,iY)!=0) { 
        onStartCallButtonClicked(v); 
        return false; 
       } 
      } 
    }   
    return true; 
} 
+0

neden olmasın OnStartCallButtonTouch (v, event) || startCallButton.onTouch() '? –

cevap

10

İşte

ben ne var seni Düşünürüm aslında bu aradığınızı: Sen noktası istenilen alanda değilse yanlış dönmek için özel düğme bu yöntemi geçersiz kılmak gerekir

View.dispatchTouchEvent(...)

. Ben böyle bu konuda gitmek öneririz:

public static class MyButton extends ImageButton { 
    ... 
    @Override 
    public boolean dispatchTouchEvent(MotionEvent event) { 
     int iX = (int) event.getX(); 
     int iY = (int) event.getY(); 
     // TODO Or use a more sophisticated, pixel value-based condition 
     if (!(iX>=0 & iY>=0 & iX<TheBitmap.getWidth() & iY<TheBitmap.getHeight())) { 
      return false; 
     } 
     return super.dispatchTouchEvent(event) 
    } 
} 

OnTouchListener kullanmayın Nedeni: (super.dispatchTouchEvent (event) yapılır) View.onTouchEvent() kadar çağırmanız gerekir Çünkü izin Görüntüle View.dispatchTouchEvent() içinde olduğu için: (bu View.refreshDrawableState() yöntemini kullanarak) (onTouchEvent içinde yapmış ve orada biraz daha oldukça karmaşık bir mantık da vardır)

onTouchEvent() geçersiz kılmaz Neden çekilebilir durumlarını ele Bir OnTouchListener varsa, o zaman dinleyicinin her şeyi ele almasına ve gerçek durumuna dönmesine izin verin. Bu nedenle, daha sonra herhangi bir nedenle düğmeye bir OnTouchListener ayarladıysanız, onTouchEvent() 'daki koordinat tabanlı koşulunuz denetlenmeyecektir, çünkü onTouchEvent() asla çağrılmaz. DispatchTouchEvent() öğesini geçersiz kıldığınızda, filtreyi en üstte dokunduğunuzda ve diğer tüm mantığı yerinde bırakacaksınız - herhangi bir dinleyiciyi düğmeye ekleyebilir ve normal düğme için çalışacakları şekilde çalışacaklardır, ancak yalnızca durumunuz doğru olduğunda.

+0

Hey, nasıl gidiyor? Cevabınız sizin için yaptıysa, lütfen kabul etmeyi düşünün. –

1

Düğme içinde düğmenin olup olmadığını öğrenmek için çarpışma algılamayı değiştirmeniz gerektiğini düşünüyorum. Folowing yaklaşımını kullanın.

public boolean OnStartCallButtonTouch(View v, MotionEvent event) 
{ 
    Bitmap TheBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.button_start_call_normal); 
    int eventPadTouch = event.getAction(); 
    int iX = (int) event.getX(); 
    int iY = (int) event.getY(); 

    int[] location = new int[2]; 
    v.getLocationOnScreen(location); 

    int viewX = location[0]; 
    int viewY = location[1]; 


    switch (eventPadTouch) { 
     case MotionEvent.ACTION_DOWN: 
      if (iX>=viewX & iY>=viewY & iX<=(viewX+TheBitmap.getWidth()) & iY<=(viewY+TheBitmap.getHeight())) {     
       if (TheBitmap.getPixel(iX,iY)!=0) { 
        onStartCallButtonClicked(v); 
        showPressedState(); 
        return false; 
       } 
      } 
      break; 
     case MotionEvent.ACTION_UP: 
     case MotionEvent.ACTION_CANCEL: 
      showNormalState(); 
      break; 
    }   
    return true; 
} 

private void showNormalState() { 
    // set your button background drawable to show normal state 
} 

private void showPressedState() { 
    // set your button background drawable to show pressed state 
} 
İlgili konular