Creating irregular shaped ImageButton with different click states

不想你离开。 提交于 2019-11-30 09:44:22

I think you're actually looking for this:

View.dispatchTouchEvent(...)

You need to override this method in your custom button to return false if point is not in the desired area. I suggest you go about it like this:

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

Why not use OnTouchListener: Because you need to call through to View.onTouchEvent() (which is done in super.dispatchTouchEvent(event)) to let View handle drawable states (it's done in onTouchEvent() using View.refreshDrawableState() method, and there's also some more rather complex logic there)

Why not override onTouchEvent(): Because in View.dispatchTouchEvent() there is a condition that if there is an OnTouchListener, then let the listener handle everything and return true. So if later on you set an OnTouchListener to the button for some reason, your coordinate-based condition in onTouchEvent() would not get checked, because onTouchEvent() would never get called. By overriding dispatchTouchEvent() you filter touches at the very top and leave all the other logic in place - you can add any listeners to the button and they will work as they would for normal button, but only when your condition is true.

I think you need to modify your collision detection for whether touch is inside your button or not. Use folowing approach.

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
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!