2012-06-18 38 views
8

Tôi đã tạo một ImageButton với bộ chọn cho trạng thái được nhấn và không được nhấn và hoạt động tốt.Tạo ImageButton có hình dạng bất thường với các trạng thái nhấp chuột khác nhau

Nhưng nút có hình dạng không đều và tôi chỉ muốn nút có thể nhấp vào khi hình ảnh hình chữ nhật bên dưới không trong suốt.

Vì vậy, tôi đã triển khai OnTouchListener kiểm tra tọa độ của sự kiện liên lạc dựa trên giá trị pixel của Bitmap (như được mô tả trong câu trả lời đầu tiên ở đây: link). Tác phẩm này, về mặt logic quyết định nếu nút được nhấn, nhưng bây giờ hình ảnh của nút không thay đổi thành hình ảnh được nhấn nữa.

Dưới đây là những gì tôi có:

Selector tập tin xml:

<?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> 

ImageButton Một phần minh bạch trong cách bố trí:

<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" 
    /> 

Trong Hoạt động:

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

tại sao không 'return OnStartCallButtonTouch (v, event) || startCallButton.onTouch() '? –

Trả lời

10

Tôi nghĩ bạn Đang thực sự tìm kiếm này:

View.dispatchTouchEvent(...)

Bạn cần phải ghi đè phương pháp này trong nút tùy chỉnh của bạn để trở sai nếu điểm không nằm trong khu vực mong muốn. Tôi đề nghị bạn đi về nó như thế này:

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) 
    } 
} 

Tại sao không sử dụng OnTouchListener: Bởi vì bạn cần phải gọi qua để View.onTouchEvent() (được thực hiện trong super.dispatchTouchEvent (sự kiện)) để cho Xem xử lý bang drawable (nó được thực hiện trong onTouchEvent() sử dụng phương pháp View.refreshDrawableState(), và cũng có một số logic hơn khá phức tạp ở đó)

tại sao không ghi đè onTouchEvent(): Bởi vì trong View.dispatchTouchEvent() có một điều kiện là nếu có một OnTouchListener, thì hãy để người nghe xử lý mọi thứ và trả về true. Vì vậy, nếu sau này bạn đặt OnTouchListener thành nút vì lý do nào đó, điều kiện dựa trên tọa độ của bạn trong onTouchEvent() sẽ không được kiểm tra, bởi vì onTouchEvent() sẽ không bao giờ được gọi. Bằng cách ghi đè dispatchTouchEvent() bạn lọc chạm ở trên cùng và để lại tất cả các logic khác tại chỗ - bạn có thể thêm bất kỳ người nghe nào vào nút và chúng sẽ hoạt động giống như nút bình thường, nhưng chỉ khi điều kiện của bạn là đúng.

+0

Hey, thế nào rồi? Nếu câu trả lời đã làm cho bạn, xin vui lòng, hãy xem xét chấp nhận nó. –

1

Tôi nghĩ rằng bạn cần phải sửa đổi phát hiện va chạm của bạn cho dù chạm là bên trong nút của bạn hay không. Sử dụng cách tiếp cận folowing.

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 
}