Search code examples
androidandroid-buttonandroid-custom-view

Custom button click event through Android-XML


I've created a custom circular imagebutton in GitHub I've my own clicklistener which is invoked onTouchEvent if the touch is on the circular bounds with the logic below

private void onTouchCircle(float x, float y, boolean up) {
    float cx = getWidth()/2;
    float cy = getHeight()/2;
    float distance = (float) Math.sqrt(Math.pow((x - cx), 2) + Math.pow((y - cy), 2));
    float radius = getWidth()/2;
    if (distance < radius  && !up) {
        IS_PRESSED = true;
        getDrawable().setColorFilter(new LightingColorFilter(0xFFFFFFFF, 0X2E2E2E));
        invalidate();
    } else {
        IS_PRESSED = false;
        getDrawable().setColorFilter(null);

        if(distance<radius){
            BUTTON_PRESSED=true;
        }else{
            BUTTON_PRESSED=false;
        }
        invalidate();
    }

    if(up && BUTTON_PRESSED){
        BUTTON_PRESSED=false;
        Log.e(TAG, "distance -- "+distance+" -- radius --"+radius);
        if(onClickListener!=null){
            onClickListener.onCircularButtonClick(this);
        }
    }

}

How do I invoke the click to happen through XML like the android.widget.Button/android.widget.ImageButton? It would be great if I could invoke the method similar to button/imagebutton for my custom control like below. Any help is appreciated.

<com.example.circularimageview.CircularImageView
        xmlns:imaginea="http://schemas.android.com/apk/res/com.example.circularimageview"
        android:id="@+id/imageView1"
        android:layout_width="80dp"
        android:layout_height="80dp"
        android:layout_alignParentLeft="true"
        android:layout_alignParentTop="true"
        android:scaleType="centerCrop"
        android:src="@drawable/breakdancing_android"
        imaginea:alpha="1"
        imaginea:onCircularButtonClick="myFancyMethod" />

public void myFancyMethod(View v) {
    // does something very interesting
}

Solution

  • See how Android does it in their base View.java

    The key lines would be:

    final String handlerName = a.getString(attr);
    if (handlerName != null) {
        setOnCircularClickListener(new OnCircularClickListener() {
            private Method mHandler;
    
            public void onCircularButtonClick(View v) {
                if (mHandler == null) {
                    try {
                        mHandler = getContext().getClass().getMethod(handlerName,
                                View.class);
                    } catch (NoSuchMethodException e) {
                        int id = getId();
                        String idText = id == NO_ID ? "" : " with id '"
                                + getContext().getResources().getResourceEntryName(
                                    id) + "'";
                        throw new IllegalStateException("Could not find a method " +
                                handlerName + "(View) in the activity "
                                + getContext().getClass() + " for onClick handler"
                                + " on view " + CircularImageView.this.getClass() + idText, e);
                    }
                }
                try {
                    mHandler.invoke(getContext(), CircularImageView.this);
                } catch (IllegalAccessException e) {
                    throw new IllegalStateException("Could not execute non "
                            + "public method of the activity", e);
                } catch (InvocationTargetException e) {
                    throw new IllegalStateException("Could not execute "
                            + "method of the activity", e);
                }
        });
    }